1
0
mirror of https://github.com/phpbb/phpbb.git synced 2025-07-30 21:40:43 +02:00

Merge pull request #843 from nickvergessen/feature/new-tz-handling

Feature/new tz handling
This commit is contained in:
Nils Adermann
2012-07-19 08:46:25 -07:00
48 changed files with 935 additions and 281 deletions

View File

@@ -57,8 +57,7 @@ class acp_board
'board_disable_msg' => false,
'default_lang' => array('lang' => 'DEFAULT_LANGUAGE', 'validate' => 'lang', 'type' => 'select', 'function' => 'language_select', 'params' => array('{CONFIG_VALUE}'), 'explain' => false),
'default_dateformat' => array('lang' => 'DEFAULT_DATE_FORMAT', 'validate' => 'string', 'type' => 'custom', 'method' => 'dateformat_select', 'explain' => true),
'board_timezone' => array('lang' => 'SYSTEM_TIMEZONE', 'validate' => 'string', 'type' => 'select', 'function' => 'tz_select', 'params' => array('{CONFIG_VALUE}', 1), 'explain' => true),
'board_dst' => array('lang' => 'SYSTEM_DST', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
'board_timezone' => array('lang' => 'SYSTEM_TIMEZONE', 'validate' => 'timezone', 'type' => 'custom', 'method' => 'timezone_select', 'explain' => true),
'default_style' => array('lang' => 'DEFAULT_STYLE', 'validate' => 'int', 'type' => 'select', 'function' => 'style_select', 'params' => array('{CONFIG_VALUE}', false), 'explain' => false),
'override_user_style' => array('lang' => 'OVERRIDE_STYLE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
@@ -897,6 +896,18 @@ class acp_board
'<br /><br /><input class="button2" type="submit" id="' . $key . '_enable" name="' . $key . '_enable" value="' . $user->lang['ALLOW_QUICK_REPLY_BUTTON'] . '" />';
}
/**
* Select guest timezone
*/
function timezone_select($value, $key)
{
global $user;
$timezone_select = phpbb_timezone_select($user, $value, true);
$timezone_select['tz_select'];
return '<select name="config[' . $key . ']" id="' . $key . '">' . $timezone_select['tz_select'] . '</select>';
}
/**
* Select default dateformat
@@ -907,10 +918,14 @@ class acp_board
// Let the format_date function operate with the acp values
$old_tz = $user->timezone;
$old_dst = $user->dst;
$user->timezone = $config['board_timezone'] * 3600;
$user->dst = $config['board_dst'] * 3600;
try
{
$user->timezone = new DateTimeZone($config['board_timezone']);
}
catch (Exception $e)
{
// If the board timezone is invalid, we just use the users timezone.
}
$dateformat_options = '';
@@ -930,7 +945,6 @@ class acp_board
// Reset users date options
$user->timezone = $old_tz;
$user->dst = $old_dst;
return "<select name=\"dateoptions\" id=\"dateoptions\" onchange=\"if (this.value == 'custom') { document.getElementById('" . addslashes($key) . "').value = '" . addslashes($value) . "'; } else { document.getElementById('" . addslashes($key) . "').value = this.value; }\">$dateformat_options</select>
<input type=\"text\" name=\"config[$key]\" id=\"$key\" value=\"$value\" maxlength=\"30\" />";

View File

@@ -1460,9 +1460,8 @@ class acp_users
$data = array(
'dateformat' => utf8_normalize_nfc(request_var('dateformat', $user_row['user_dateformat'], true)),
'lang' => basename(request_var('lang', $user_row['user_lang'])),
'tz' => request_var('tz', (float) $user_row['user_timezone']),
'tz' => request_var('tz', $user_row['user_timezone']),
'style' => request_var('style', $user_row['user_style']),
'dst' => request_var('dst', $user_row['user_dst']),
'viewemail' => request_var('viewemail', $user_row['user_allow_viewemail']),
'massemail' => request_var('massemail', $user_row['user_allow_massemail']),
'hideonline' => request_var('hideonline', !$user_row['user_allow_viewonline']),
@@ -1497,7 +1496,7 @@ class acp_users
$error = validate_data($data, array(
'dateformat' => array('string', false, 1, 30),
'lang' => array('match', false, '#^[a-z_\-]{2,}$#i'),
'tz' => array('num', false, -14, 14),
'tz' => array('timezone'),
'topic_sk' => array('string', false, 1, 1),
'topic_sd' => array('string', false, 1, 1),
@@ -1533,7 +1532,6 @@ class acp_users
'user_notify_type' => $data['notifymethod'],
'user_notify_pm' => $data['notifypm'],
'user_dst' => $data['dst'],
'user_dateformat' => $data['dateformat'],
'user_lang' => $data['lang'],
'user_timezone' => $data['tz'],
@@ -1643,6 +1641,7 @@ class acp_users
${'s_sort_' . $sort_option . '_dir'} .= '</select>';
}
$timezone_selects = phpbb_timezone_select($user, $data['tz'], true);
$template->assign_vars(array(
'S_PREFS' => true,
'S_JABBER_DISABLED' => ($config['jab_enable'] && $user_row['user_jabber'] && @extension_loaded('xml')) ? false : true,
@@ -1656,7 +1655,6 @@ class acp_users
'NOTIFY_BOTH' => ($data['notifymethod'] == NOTIFY_BOTH) ? true : false,
'NOTIFY_PM' => $data['notifypm'],
'POPUP_PM' => $data['popuppm'],
'DST' => $data['dst'],
'BBCODE' => $data['bbcode'],
'SMILIES' => $data['smilies'],
'ATTACH_SIG' => $data['sig'],
@@ -1683,7 +1681,8 @@ class acp_users
'S_LANG_OPTIONS' => language_select($data['lang']),
'S_STYLE_OPTIONS' => style_select($data['style']),
'S_TZ_OPTIONS' => tz_select($data['tz'], true),
'S_TZ_OPTIONS' => $timezone_selects['tz_select'],
'S_TZ_DATE_OPTIONS' => $timezone_selects['tz_dates'],
)
);

158
phpBB/includes/datetime.php Normal file
View File

@@ -0,0 +1,158 @@
<?php
/**
*
* @package phpBB3
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*/
/**
* phpBB custom extensions to the PHP DateTime class
* This handles the relative formats phpBB employs
*/
class phpbb_datetime extends DateTime
{
/**
* String used to wrap the date segment which should be replaced by today/tomorrow/yesterday
*/
const RELATIVE_WRAPPER = '|';
/**
* @var user User who is the context for this DateTime instance
*/
protected $user;
/**
* @var array Date formats are preprocessed by phpBB, to save constant recalculation they are cached.
*/
static protected $format_cache = array();
/**
* Constructs a new instance of phpbb_datetime, expanded to include an argument to inject
* the user context and modify the timezone to the users selected timezone if one is not set.
*
* @param string $time String in a format accepted by strtotime().
* @param DateTimeZone $timezone Time zone of the time.
* @param user User object for context.
*/
public function __construct($user, $time = 'now', DateTimeZone $timezone = null)
{
$this->user = $user;
$timezone = $timezone ?: $this->user->timezone;
parent::__construct($time, $timezone);
}
/**
* Formats the current date time into the specified format
*
* @param string $format Optional format to use for output, defaults to users chosen format
* @param boolean $force_absolute Force output of a non relative date
* @return string Formatted date time
*/
public function format($format = '', $force_absolute = false)
{
$format = $format ? $format : $this->user->date_format;
$format = self::format_cache($format, $this->user);
$relative = ($format['is_short'] && !$force_absolute);
$now = new self($this->user, 'now', $this->user->timezone);
$timestamp = $this->getTimestamp();
$now_ts = $now->getTimeStamp();
$delta = $now_ts - $timestamp;
if ($relative)
{
/*
* Check the delta is less than or equal to 1 hour
* and the delta not more than a minute in the past
* and the delta is either greater than -5 seconds or timestamp
* and current time are of the same minute (they must be in the same hour already)
* finally check that relative dates are supported by the language pack
*/
if ($delta <= 3600 && $delta > -60 &&
($delta >= -5 || (($now_ts / 60) % 60) == (($timestamp / 60) % 60))
&& isset($this->user->lang['datetime']['AGO']))
{
return $this->user->lang(array('datetime', 'AGO'), max(0, (int) floor($delta / 60)));
}
else
{
$midnight = clone $now;
$midnight->setTime(0, 0, 0);
$midnight = $midnight->getTimestamp();
$day = false;
if ($timestamp > $midnight + 86400)
{
$day = 'TOMORROW';
}
else if ($timestamp > $midnight)
{
$day = 'TODAY';
}
else if ($timestamp > $midnight - 86400)
{
$day = 'YESTERDAY';
}
if ($day !== false)
{
// Format using the short formatting and finally swap out the relative token placeholder with the correct value
return str_replace(self::RELATIVE_WRAPPER . self::RELATIVE_WRAPPER, $this->user->lang['datetime'][$day], strtr(parent::format($format['format_short']), $format['lang']));
}
}
}
return strtr(parent::format($format['format_long']), $format['lang']);
}
/**
* Magic method to convert DateTime object to string
*
* @return Formatted date time, according to the users default settings.
*/
public function __toString()
{
return $this->format();
}
/**
* Pre-processes the specified date format
*
* @param string $format Output format
* @param user $user User object to use for localisation
* @return array Processed date format
*/
static protected function format_cache($format, $user)
{
$lang = $user->lang_name;
if (!isset(self::$format_cache[$lang]))
{
self::$format_cache[$lang] = array();
}
if (!isset(self::$format_cache[$lang][$format]))
{
// Is the user requesting a friendly date format (i.e. 'Today 12:42')?
self::$format_cache[$lang][$format] = array(
'is_short' => strpos($format, self::RELATIVE_WRAPPER) !== false,
'format_short' => substr($format, 0, strpos($format, self::RELATIVE_WRAPPER)) . self::RELATIVE_WRAPPER . self::RELATIVE_WRAPPER . substr(strrchr($format, self::RELATIVE_WRAPPER), 1),
'format_long' => str_replace(self::RELATIVE_WRAPPER, '', $format),
'lang' => $user->lang['datetime'],
);
// Short representation of month in format? Some languages use different terms for the long and short format of May
if ((strpos($format, '\M') === false && strpos($format, 'M') !== false) || (strpos($format, '\r') === false && strpos($format, 'r') !== false))
{
self::$format_cache[$lang][$format]['lang']['May'] = $user->lang['datetime']['May_short'];
}
}
return self::$format_cache[$lang][$format];
}
}

View File

@@ -1068,33 +1068,210 @@ function style_select($default = '', $all = false)
return $style_options;
}
/**
* Format the timezone offset with hours and minutes
*
* @param int $tz_offset Timezone offset in seconds
* @return string Normalized offset string: -7200 => -02:00
* 16200 => +04:30
*/
function phpbb_format_timezone_offset($tz_offset)
{
$sign = ($tz_offset < 0) ? '-' : '+';
$time_offset = abs($tz_offset);
$offset_seconds = $time_offset % 3600;
$offset_minutes = $offset_seconds / 60;
$offset_hours = ($time_offset - $offset_seconds) / 3600;
$offset_string = sprintf("%s%02d:%02d", $sign, $offset_hours, $offset_minutes);
return $offset_string;
}
/**
* Compares two time zone labels.
* Arranges them in increasing order by timezone offset.
* Places UTC before other timezones in the same offset.
*/
function phpbb_tz_select_compare($a, $b)
{
$a_sign = $a[3];
$b_sign = $b[3];
if ($a_sign != $b_sign)
{
return $a_sign == '-' ? -1 : 1;
}
$a_offset = substr($a, 4, 5);
$b_offset = substr($b, 4, 5);
if ($a_offset == $b_offset)
{
$a_name = substr($a, 12);
$b_name = substr($b, 12);
if ($a_name == $b_name)
{
return 0;
}
else if ($a_name == 'UTC')
{
return -1;
}
else if ($b_name == 'UTC')
{
return 1;
}
else
{
return $a_name < $b_name ? -1 : 1;
}
}
else
{
if ($a_sign == '-')
{
return $a_offset > $b_offset ? -1 : 1;
}
else
{
return $a_offset < $b_offset ? -1 : 1;
}
}
}
/**
* Return list of timezone identifiers
* We also add the selected timezone if we can create an object with it.
* DateTimeZone::listIdentifiers seems to not add all identifiers to the list,
* because some are only kept for backward compatible reasons. If the user has
* a deprecated value, we add it here, so it can still be kept. Once the user
* changed his value, there is no way back to deprecated values.
*
* @param string $selected_timezone Additional timezone that shall
* be added to the list of identiers
* @return array DateTimeZone::listIdentifiers and additional
* selected_timezone if it is a valid timezone.
*/
function phpbb_get_timezone_identifiers($selected_timezone)
{
$timezones = DateTimeZone::listIdentifiers();
if (!in_array($selected_timezone, $timezones))
{
try
{
// Add valid timezones that are currently selected but not returned
// by DateTimeZone::listIdentifiers
$validate_timezone = new DateTimeZone($selected_timezone);
$timezones[] = $selected_timezone;
}
catch (Exception $e)
{
}
}
return $timezones;
}
/**
* Pick a timezone
*
* @param string $default A timezone to select
* @param boolean $truncate Shall we truncate the options text
*
* @return string Returns the options for timezone selector only
*
* @deprecated
*/
function tz_select($default = '', $truncate = false)
{
global $user;
$tz_select = '';
foreach ($user->lang['tz_zones'] as $offset => $zone)
$timezone_select = phpbb_timezone_select($user, $default, $truncate);
return $timezone_select['tz_select'];
}
/**
* Options to pick a timezone and date/time
*
* @param phpbb_user $user Object of the current user
* @param string $default A timezone to select
* @param boolean $truncate Shall we truncate the options text
*
* @return array Returns an array, also containing the options for the time selector.
*/
function phpbb_timezone_select($user, $default = '', $truncate = false)
{
static $timezones;
$default_offset = '';
if (!isset($timezones))
{
if ($truncate)
$unsorted_timezones = phpbb_get_timezone_identifiers($default);
$timezones = array();
foreach ($unsorted_timezones as $timezone)
{
$zone_trunc = truncate_string($zone, 50, 255, false, '...');
$tz = new DateTimeZone($timezone);
$dt = new phpbb_datetime($user, 'now', $tz);
$offset = $dt->getOffset();
$current_time = $dt->format($user->lang['DATETIME_FORMAT'], true);
$offset_string = phpbb_format_timezone_offset($offset);
$timezones['GMT' . $offset_string . ' - ' . $timezone] = array(
'tz' => $timezone,
'offest' => 'GMT' . $offset_string,
'current' => $current_time,
);
if ($timezone === $default)
{
$default_offset = 'GMT' . $offset_string;
}
}
unset($unsorted_timezones);
uksort($timezones, 'phpbb_tz_select_compare');
}
$tz_select = $tz_dates = $opt_group = '';
foreach ($timezones as $timezone)
{
if ($opt_group != $timezone['offest'])
{
$tz_select .= ($opt_group) ? '</optgroup>' : '';
$tz_select .= '<optgroup label="' . $timezone['offest'] . ' - ' . $timezone['current'] . '">';
$opt_group = $timezone['offest'];
$selected = ($default_offset == $timezone['offest']) ? ' selected="selected"' : '';
$tz_dates .= '<option value="' . $timezone['offest'] . ' - ' . $timezone['current'] . '"' . $selected . '>' . $timezone['offest'] . ' - ' . $timezone['current'] . '</option>';
}
if (isset($user->lang['timezones'][$timezone['tz']]))
{
$title = $label = $user->lang['timezones'][$timezone['tz']];
}
else
{
$zone_trunc = $zone;
// No label, we'll figure one out
$bits = explode('/', str_replace('_', ' ', $timezone['tz']));
$label = implode(' - ', $bits);
$title = $timezone['offest'] . ' - ' . $label;
}
if (is_numeric($offset))
if ($truncate)
{
$selected = ($offset == $default) ? ' selected="selected"' : '';
$tz_select .= '<option title="' . $zone . '" value="' . $offset . '"' . $selected . '>' . $zone_trunc . '</option>';
$label = truncate_string($label, 50, 255, false, '...');
}
}
return $tz_select;
$selected = ($timezone['tz'] === $default) ? ' selected="selected"' : '';
$tz_select .= '<option title="' . $title . '" value="' . $timezone['tz'] . '"' . $selected . '>' . $label . '</option>';
}
$tz_select .= '</optgroup>';
return array(
'tz_select' => $tz_select,
'tz_dates' => $tz_dates,
);
}
// Functions handling topic/post tracking/marking
@@ -4701,9 +4878,6 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0
$board_url = generate_board_url() . '/';
$web_path = (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH) ? $board_url : $phpbb_root_path;
// Which timezone?
$tz = ($user->data['user_id'] != ANONYMOUS) ? strval(doubleval($user->data['user_timezone'])) : strval(doubleval($config['board_timezone']));
// Send a proper content-language to the output
$user_lang = $user->lang['USER_LANG'];
if (strpos($user_lang, '-x-') !== false)
@@ -4726,6 +4900,14 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0
}
}
$dt = new phpbb_datetime($user, 'now', $user->timezone);
$timezone_offset = 'GMT' . phpbb_format_timezone_offset($dt->getOffset());
$timezone_name = $user->timezone->getName();
if (isset($user->lang['timezones'][$timezone_name]))
{
$timezone_name = $user->lang['timezones'][$timezone_name];
}
// The following assigns all _common_ variables that may be used at any point in a template.
$template->assign_vars(array(
'SITENAME' => $config['sitename'],
@@ -4793,7 +4975,7 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0
'S_CONTENT_FLOW_BEGIN' => ($user->lang['DIRECTION'] == 'ltr') ? 'left' : 'right',
'S_CONTENT_FLOW_END' => ($user->lang['DIRECTION'] == 'ltr') ? 'right' : 'left',
'S_CONTENT_ENCODING' => 'UTF-8',
'S_TIMEZONE' => ($user->data['user_dst'] || ($user->data['user_id'] == ANONYMOUS && $config['board_dst'])) ? sprintf($user->lang['ALL_TIMES'], $user->lang['tz'][$tz], $user->lang['tz']['dst']) : sprintf($user->lang['ALL_TIMES'], $user->lang['tz'][$tz], ''),
'S_TIMEZONE' => sprintf($user->lang['ALL_TIMES'], $timezone_offset, $timezone_name),
'S_DISPLAY_ONLINE_LIST' => ($l_online_time) ? 1 : 0,
'S_DISPLAY_SEARCH' => (!$config['load_search']) ? 0 : (isset($auth) ? ($auth->acl_get('u_search') && $auth->acl_getf_global('f_search')) : 1),
'S_DISPLAY_PM' => ($config['allow_privmsg'] && !empty($user->data['is_registered']) && ($auth->acl_get('u_readpm') || $auth->acl_get('u_sendpm'))) ? true : false,

View File

@@ -1884,7 +1884,7 @@ function add_bots()
'user_email' => '',
'user_lang' => $config['default_lang'],
'user_style' => 1,
'user_timezone' => 0,
'user_timezone' => 'UTC',
'user_allow_massemail' => 0,
);

View File

@@ -554,9 +554,12 @@ class custom_profile
else if ($day && $month && $year)
{
global $user;
// Date should display as the same date for every user regardless of timezone, so remove offset
// to compensate for the offset added by phpbb_user::format_date()
return $user->format_date(gmmktime(0, 0, 0, $month, $day, $year) - ($user->timezone + $user->dst), $user->lang['DATE_FORMAT'], true);
// Date should display as the same date for every user regardless of timezone
return $user->create_datetime()
->setDate($year, $month, $day)
->setTime(0, 0, 0)
->format($user->lang['DATE_FORMAT'], true);
}
return $value;

View File

@@ -197,7 +197,6 @@ function user_add($user_row, $cp_data = false)
'user_lastpost_time' => 0,
'user_lastpage' => '',
'user_posts' => 0,
'user_dst' => (int) $config['board_dst'],
'user_colour' => '',
'user_occ' => '',
'user_interests' => '',
@@ -677,8 +676,10 @@ function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reas
if (sizeof($ban_other) == 3 && ((int)$ban_other[0] < 9999) &&
(strlen($ban_other[0]) == 4) && (strlen($ban_other[1]) == 2) && (strlen($ban_other[2]) == 2))
{
$time_offset = (isset($user->timezone) && isset($user->dst)) ? (int) $user->timezone + (int) $user->dst : 0;
$ban_end = max($current_time, gmmktime(0, 0, 0, (int)$ban_other[1], (int)$ban_other[2], (int)$ban_other[0]) - $time_offset);
$ban_end = max($current_time, $user->create_datetime()
->setDate((int) $ban_other[0], (int) $ban_other[1], (int) $ban_other[2])
->setTime(0, 0, 0)
->getTimestamp() + $user->timezone->getOffset(new DateTime('UTC')));
}
else
{
@@ -1247,10 +1248,21 @@ function validate_data($data, $val_ary)
$function = array_shift($validate);
array_unshift($validate, $data[$var]);
if ($result = call_user_func_array('validate_' . $function, $validate))
if (function_exists('phpbb_validate_' . $function))
{
// Since errors are checked later for their language file existence, we need to make sure custom errors are not adjusted.
$error[] = (empty($user->lang[$result . '_' . strtoupper($var)])) ? $result : $result . '_' . strtoupper($var);
if ($result = call_user_func_array('phpbb_validate_' . $function, $validate))
{
// Since errors are checked later for their language file existence, we need to make sure custom errors are not adjusted.
$error[] = (empty($user->lang[$result . '_' . strtoupper($var)])) ? $result : $result . '_' . strtoupper($var);
}
}
else
{
if ($result = call_user_func_array('validate_' . $function, $validate))
{
// Since errors are checked later for their language file existence, we need to make sure custom errors are not adjusted.
$error[] = (empty($user->lang[$result . '_' . strtoupper($var)])) ? $result : $result . '_' . strtoupper($var);
}
}
}
}
@@ -1395,6 +1407,22 @@ function validate_language_iso_name($lang_iso)
return ($lang_id) ? false : 'WRONG_DATA';
}
/**
* Validate Timezone Name
*
* Tests whether a timezone name is valid
*
* @param string $timezone The timezone string to test
*
* @return bool|string Either false if validation succeeded or
* a string which will be used as the error message
* (with the variable name appended)
*/
function phpbb_validate_timezone($timezone)
{
return (in_array($timezone, phpbb_get_timezone_identifiers($timezone))) ? false : 'TIMEZONE_INVALID';
}
/**
* Check to see if the username has been taken, or if it is disallowed.
* Also checks if it includes the " character, which we don't allow in usernames.

View File

@@ -304,7 +304,6 @@ class phpbb_questionnaire_phpbb_data_provider
'avatar_max_width' => true,
'avatar_min_height' => true,
'avatar_min_width' => true,
'board_dst' => true,
'board_email_form' => true,
'board_hide_emails' => true,
'board_timezone' => true,

View File

@@ -41,9 +41,8 @@ class ucp_prefs
'dateformat' => request_var('dateformat', $user->data['user_dateformat'], true),
'lang' => basename(request_var('lang', $user->data['user_lang'])),
'style' => request_var('style', (int) $user->data['user_style']),
'tz' => request_var('tz', (float) $user->data['user_timezone']),
'tz' => request_var('tz', $user->data['user_timezone']),
'dst' => request_var('dst', (bool) $user->data['user_dst']),
'viewemail' => request_var('viewemail', (bool) $user->data['user_allow_viewemail']),
'massemail' => request_var('massemail', (bool) $user->data['user_allow_massemail']),
'hideonline' => request_var('hideonline', (bool) !$user->data['user_allow_viewonline']),
@@ -72,7 +71,7 @@ class ucp_prefs
$error = validate_data($data, array(
'dateformat' => array('string', false, 1, 30),
'lang' => array('language_iso_name'),
'tz' => array('num', false, -14, 14),
'tz' => array('timezone'),
));
if (!check_form_key('ucp_prefs_personal'))
@@ -93,7 +92,6 @@ class ucp_prefs
'user_notify_pm' => $data['notifypm'],
'user_options' => $user->data['user_options'],
'user_dst' => $data['dst'],
'user_dateformat' => $data['dateformat'],
'user_lang' => $data['lang'],
'user_timezone' => $data['tz'],
@@ -133,6 +131,7 @@ class ucp_prefs
}
$dateformat_options .= '>' . $user->lang['CUSTOM_DATEFORMAT'] . '</option>';
$timezone_selects = phpbb_timezone_select($user, $data['tz'], true);
$template->assign_vars(array(
'ERROR' => (sizeof($error)) ? implode('<br />', $error) : '',
@@ -145,7 +144,6 @@ class ucp_prefs
'S_HIDE_ONLINE' => $data['hideonline'],
'S_NOTIFY_PM' => $data['notifypm'],
'S_POPUP_PM' => $data['popuppm'],
'S_DST' => $data['dst'],
'DATE_FORMAT' => $data['dateformat'],
'A_DATE_FORMAT' => addslashes($data['dateformat']),
@@ -156,7 +154,8 @@ class ucp_prefs
'S_LANG_OPTIONS' => language_select($data['lang']),
'S_STYLE_OPTIONS' => ($config['override_user_style']) ? '' : style_select($data['style']),
'S_TZ_OPTIONS' => tz_select($data['tz'], true),
'S_TZ_OPTIONS' => $timezone_selects['tz_select'],
'S_TZ_DATE_OPTIONS' => $timezone_selects['tz_dates'],
'S_CAN_HIDE_ONLINE' => ($auth->acl_get('u_hideonline')) ? true : false,
'S_SELECT_NOTIFY' => ($config['jab_enable'] && $user->data['user_jabber'] && @extension_loaded('xml')) ? true : false)
);

View File

@@ -100,7 +100,7 @@ class ucp_register
'username' => utf8_normalize_nfc(request_var('username', '', true)),
'email' => strtolower(request_var('email', '')),
'lang' => $user->lang_name,
'tz' => request_var('tz', (float) $config['board_timezone']),
'tz' => request_var('tz', $config['board_timezone']),
));
}
@@ -120,7 +120,10 @@ class ucp_register
if ($coppa === false && $config['coppa_enable'])
{
$now = getdate();
$coppa_birthday = $user->format_date(mktime($now['hours'] + $user->data['user_dst'], $now['minutes'], $now['seconds'], $now['mon'], $now['mday'] - 1, $now['year'] - 13), $user->lang['DATE_FORMAT']);
$coppa_birthday = $user->create_datetime()
->setDate($now['year'] - 13, $now['mon'], $now['mday'] - 1)
->setTime(0, 0, 0)
->format($user->lang['DATE_FORMAT'], true);
unset($now);
$template->assign_vars(array(
@@ -163,7 +166,6 @@ class ucp_register
$captcha->init(CONFIRM_REG);
}
$is_dst = $config['board_dst'];
$timezone = $config['board_timezone'];
$data = array(
@@ -172,7 +174,7 @@ class ucp_register
'password_confirm' => request_var('password_confirm', '', true),
'email' => strtolower(request_var('email', '')),
'lang' => basename(request_var('lang', $user->lang_name)),
'tz' => request_var('tz', (float) $timezone),
'tz' => request_var('tz', $timezone),
);
// Check and initialize some variables if needed
@@ -189,7 +191,7 @@ class ucp_register
'email' => array(
array('string', false, 6, 60),
array('email')),
'tz' => array('num', false, -14, 14),
'tz' => array('timezone'),
'lang' => array('language_iso_name'),
));
@@ -279,8 +281,7 @@ class ucp_register
'user_password' => phpbb_hash($data['new_password']),
'user_email' => $data['email'],
'group_id' => (int) $group_id,
'user_timezone' => (float) $data['tz'],
'user_dst' => $is_dst,
'user_timezone' => $data['tz'],
'user_lang' => $data['lang'],
'user_type' => $user_type,
'user_actkey' => $user_actkey,
@@ -441,6 +442,7 @@ class ucp_register
break;
}
$timezone_selects = phpbb_timezone_select($user, $data['tz'], true);
$template->assign_vars(array(
'ERROR' => (sizeof($error)) ? implode('<br />', $error) : '',
'USERNAME' => $data['username'],
@@ -453,7 +455,8 @@ class ucp_register
'L_PASSWORD_EXPLAIN' => $user->lang($config['pass_complex'] . '_EXPLAIN', $user->lang('CHARACTERS', (int) $config['min_pass_chars']), $user->lang('CHARACTERS', (int) $config['max_pass_chars'])),
'S_LANG_OPTIONS' => language_select($data['lang']),
'S_TZ_OPTIONS' => tz_select($data['tz']),
'S_TZ_OPTIONS' => $timezone_selects['tz_select'],
'S_TZ_DATE_OPTIONS' => $timezone_selects['tz_dates'],
'S_CONFIRM_REFRESH' => ($config['enable_confirm'] && $config['confirm_refresh']) ? true : false,
'S_REGISTRATION' => true,
'S_COPPA' => $coppa,

View File

@@ -0,0 +1,112 @@
<?php
/**
*
* @package phpBB3
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*/
/**
* phpBB Update Helpers
*/
class phpbb_update_helpers
{
/**
* Determine the new timezone for a given phpBB 3.0 timezone and
* "Daylight Saving Time" option
*
* @param $timezone float Users timezone in 3.0
* @param $dst int Users daylight saving time
* @return string Users new php Timezone which is used since 3.1
*/
function convert_phpbb30_timezone($timezone, $dst)
{
$offset = $timezone + $dst;
switch ($timezone)
{
case '-12':
return 'Etc/GMT' . $offset; //'[UTC - 12] Baker Island Time'
case '-11':
return 'Etc/GMT' . $offset; //'[UTC - 11] Niue Time, Samoa Standard Time'
case '-10':
return 'Etc/GMT' . $offset; //'[UTC - 10] Hawaii-Aleutian Standard Time, Cook Island Time'
case '-9.5':
return 'Pacific/Marquesas'; //'[UTC - 9:30] Marquesas Islands Time'
case '-9':
return 'Etc/GMT' . $offset; //'[UTC - 9] Alaska Standard Time, Gambier Island Time'
case '-8':
return 'Etc/GMT' . $offset; //'[UTC - 8] Pacific Standard Time'
case '-7':
return 'Etc/GMT' . $offset; //'[UTC - 7] Mountain Standard Time'
case '-6':
return 'Etc/GMT' . $offset; //'[UTC - 6] Central Standard Time'
case '-5':
return 'Etc/GMT' . $offset; //'[UTC - 5] Eastern Standard Time'
case '-4.5':
return 'America/Caracas'; //'[UTC - 4:30] Venezuelan Standard Time'
case '-4':
return 'Etc/GMT' . $offset; //'[UTC - 4] Atlantic Standard Time'
case '-3.5':
return 'America/St_Johns'; //'[UTC - 3:30] Newfoundland Standard Time'
case '-3':
return 'Etc/GMT' . $offset; //'[UTC - 3] Amazon Standard Time, Central Greenland Time'
case '-2':
return 'Etc/GMT' . $offset; //'[UTC - 2] Fernando de Noronha Time, South Georgia &amp; the South Sandwich Islands Time'
case '-1':
return 'Etc/GMT' . $offset; //'[UTC - 1] Azores Standard Time, Cape Verde Time, Eastern Greenland Time'
case '0':
return (!$dst) ? 'UTC' : 'Etc/GMT+1'; //'[UTC] Western European Time, Greenwich Mean Time'
case '1':
return 'Etc/GMT+' . $offset; //'[UTC + 1] Central European Time, West African Time'
case '2':
return 'Etc/GMT+' . $offset; //'[UTC + 2] Eastern European Time, Central African Time'
case '3':
return 'Etc/GMT+' . $offset; //'[UTC + 3] Moscow Standard Time, Eastern African Time'
case '3.5':
return 'Asia/Tehran'; //'[UTC + 3:30] Iran Standard Time'
case '4':
return 'Etc/GMT+' . $offset; //'[UTC + 4] Gulf Standard Time, Samara Standard Time'
case '4.5':
return 'Asia/Kabul'; //'[UTC + 4:30] Afghanistan Time'
case '5':
return 'Etc/GMT+' . $offset; //'[UTC + 5] Pakistan Standard Time, Yekaterinburg Standard Time'
case '5.5':
return 'Asia/Kolkata'; //'[UTC + 5:30] Indian Standard Time, Sri Lanka Time'
case '5.75':
return 'Asia/Kathmandu'; //'[UTC + 5:45] Nepal Time'
case '6':
return 'Etc/GMT+' . $offset; //'[UTC + 6] Bangladesh Time, Bhutan Time, Novosibirsk Standard Time'
case '6.5':
return 'Indian/Cocos'; //'[UTC + 6:30] Cocos Islands Time, Myanmar Time'
case '7':
return 'Etc/GMT+' . $offset; //'[UTC + 7] Indochina Time, Krasnoyarsk Standard Time'
case '8':
return 'Etc/GMT+' . $offset; //'[UTC + 8] Chinese Standard Time, Australian Western Standard Time, Irkutsk Standard Time'
case '8.75':
return 'Australia/Eucla'; //'[UTC + 8:45] Southeastern Western Australia Standard Time'
case '9':
return 'Etc/GMT+' . $offset; //'[UTC + 9] Japan Standard Time, Korea Standard Time, Chita Standard Time'
case '9.5':
return 'Australia/ACT'; //'[UTC + 9:30] Australian Central Standard Time'
case '10':
return 'Etc/GMT+' . $offset; //'[UTC + 10] Australian Eastern Standard Time, Vladivostok Standard Time'
case '10.5':
return 'Australia/Lord_Howe'; //'[UTC + 10:30] Lord Howe Standard Time'
case '11':
return 'Etc/GMT+' . $offset; //'[UTC + 11] Solomon Island Time, Magadan Standard Time'
case '11.5':
return 'Pacific/Norfolk'; //'[UTC + 11:30] Norfolk Island Time'
case '12':
return 'Etc/GMT+12'; //'[UTC + 12] New Zealand Time, Fiji Time, Kamchatka Standard Time'
case '12.75':
return 'Pacific/Chatham'; //'[UTC + 12:45] Chatham Islands Time'
case '13':
return 'Pacific/Tongatapu'; //'[UTC + 13] Tonga Time, Phoenix Islands Time'
case '14':
return 'Pacific/Kiritimati'; //'[UTC + 14] Line Island Time'
default:
return 'UTC';
}
}
}

View File

@@ -29,8 +29,11 @@ class phpbb_user extends phpbb_session
var $help = array();
var $style = array();
var $date_format;
var $timezone;
var $dst;
/**
* DateTimeZone object holding the timezone of the user
*/
public $timezone;
var $lang_name = false;
var $lang_id = false;
@@ -79,15 +82,13 @@ class phpbb_user extends phpbb_session
$this->lang_name = (file_exists($this->lang_path . $this->data['user_lang'] . "/common.$phpEx")) ? $this->data['user_lang'] : basename($config['default_lang']);
$this->date_format = $this->data['user_dateformat'];
$this->timezone = $this->data['user_timezone'] * 3600;
$this->dst = $this->data['user_dst'] * 3600;
$user_timezone = $this->data['user_timezone'];
}
else
{
$this->lang_name = basename($config['default_lang']);
$this->date_format = $config['default_dateformat'];
$this->timezone = $config['board_timezone'] * 3600;
$this->dst = $config['board_dst'] * 3600;
$user_timezone = $config['board_timezone'];
/**
* If a guest user is surfing, we try to guess his/her language first by obtaining the browser language
@@ -126,6 +127,16 @@ class phpbb_user extends phpbb_session
*/
}
try
{
$this->timezone = new DateTimeZone($user_timezone);
}
catch (Exception $e)
{
// If the timezone the user has selected is invalid, we fall back to UTC.
$this->timezone = new DateTimeZone('UTC');
}
// We include common language file here to not load it every time a custom language file is included
$lang = &$this->lang;
@@ -612,70 +623,46 @@ class phpbb_user extends phpbb_session
*/
function format_date($gmepoch, $format = false, $forcedate = false)
{
static $midnight;
static $date_cache;
static $utc;
$format = (!$format) ? $this->date_format : $format;
$now = time();
$delta = $now - $gmepoch;
if (!isset($date_cache[$format]))
if (!isset($utc))
{
// Is the user requesting a friendly date format (i.e. 'Today 12:42')?
$date_cache[$format] = array(
'is_short' => strpos($format, '|'),
'format_short' => substr($format, 0, strpos($format, '|')) . '||' . substr(strrchr($format, '|'), 1),
'format_long' => str_replace('|', '', $format),
'lang' => $this->lang['datetime'],
);
// Short representation of month in format? Some languages use different terms for the long and short format of May
if ((strpos($format, '\M') === false && strpos($format, 'M') !== false) || (strpos($format, '\r') === false && strpos($format, 'r') !== false))
{
$date_cache[$format]['lang']['May'] = $this->lang['datetime']['May_short'];
}
$utc = new DateTimeZone('UTC');
}
// Zone offset
$zone_offset = $this->timezone + $this->dst;
$time = new phpbb_datetime($this, "@$gmepoch", $utc);
$time->setTimezone($this->timezone);
// Show date < 1 hour ago as 'xx min ago' but not greater than 60 seconds in the future
// A small tolerence is given for times in the future but in the same minute are displayed as '< than a minute ago'
if ($delta < 3600 && $delta > -60 && ($delta >= -5 || (($now / 60) % 60) == (($gmepoch / 60) % 60)) && $date_cache[$format]['is_short'] !== false && !$forcedate && isset($this->lang['datetime']['AGO']))
{
return $this->lang(array('datetime', 'AGO'), max(0, (int) floor($delta / 60)));
}
return $time->format($format, $forcedate);
}
if (!$midnight)
{
list($d, $m, $y) = explode(' ', gmdate('j n Y', time() + $zone_offset));
$midnight = gmmktime(0, 0, 0, $m, $d, $y) - $zone_offset;
}
/**
* Create a phpbb_datetime object in the context of the current user
*
* @since 3.1
* @param string $time String in a format accepted by strtotime().
* @param DateTimeZone $timezone Time zone of the time.
* @return phpbb_datetime Date time object linked to the current users locale
*/
public function create_datetime($time = 'now', DateTimeZone $timezone = null)
{
$timezone = $timezone ?: $this->timezone;
return new phpbb_datetime($this, $time, $timezone);
}
if ($date_cache[$format]['is_short'] !== false && !$forcedate && !($gmepoch < $midnight - 86400 || $gmepoch > $midnight + 172800))
{
$day = false;
if ($gmepoch > $midnight + 86400)
{
$day = 'TOMORROW';
}
else if ($gmepoch > $midnight)
{
$day = 'TODAY';
}
else if ($gmepoch > $midnight - 86400)
{
$day = 'YESTERDAY';
}
if ($day !== false)
{
return str_replace('||', $this->lang['datetime'][$day], strtr(@gmdate($date_cache[$format]['format_short'], $gmepoch + $zone_offset), $date_cache[$format]['lang']));
}
}
return strtr(@gmdate($date_cache[$format]['format_long'], $gmepoch + $zone_offset), $date_cache[$format]['lang']);
/**
* Get the UNIX timestamp for a datetime in the users timezone, so we can store it in the database.
*
* @param string $format Format of the entered date/time
* @param string $time Date/time with the timezone applied
* @param DateTimeZone $timezone Timezone of the date/time, falls back to timezone of current user
* @return int Returns the unix timestamp
*/
public function get_timestamp_from_format($format, $time, DateTimeZone $timezone = null)
{
$timezone = $timezone ?: $this->timezone;
$date = DateTime::createFromFormat($format, $time, $timezone);
return ($date !== false) ? $date->format('U') : false;
}
/**