Skip to content
Browse files

MDL-27577 moodlelib - fixed dst offset in userdate, usergetdate and m…

…ake_timestamp functions
  • Loading branch information...
1 parent dba2410 commit 014fba4928b9c9282c3affaf8243d9b914267328 Rajesh Taneja committed May 27, 2011
Showing with 328 additions and 26 deletions.
  1. +32 −25 lib/moodlelib.php
  2. +296 −1 lib/simpletest/testmoodlelib.php
View
57 lib/moodlelib.php
@@ -1554,26 +1554,27 @@ function get_user_preferences($name = null, $default = null, $user = null) {
* @param int $hour The hour part to create timestamp of
* @param int $minute The minute part to create timestamp of
* @param int $second The second part to create timestamp of
- * @param float $timezone Timezone modifier
- * @param bool $applydst Toggle Daylight Saving Time, default true
+ * @param mixed $timezone Timezone modifier, if 99 then use default user's timezone
+ * @param bool $applydst Toggle Daylight Saving Time, default true, will be
+ * applied only if timezone is 99 or string.
* @return int timestamp
*/
function make_timestamp($year, $month=1, $day=1, $hour=0, $minute=0, $second=0, $timezone=99, $applydst=true) {
- $strtimezone = NULL;
- if (!is_numeric($timezone)) {
- $strtimezone = $timezone;
- }
+ //save input timezone, required for dst offset check.
+ $passedtimezone = $timezone;
$timezone = get_user_timezone_offset($timezone);
- if (abs($timezone) > 13) {
+ if (abs($timezone) > 13) { //server time
$time = mktime((int)$hour, (int)$minute, (int)$second, (int)$month, (int)$day, (int)$year);
} else {
$time = gmmktime((int)$hour, (int)$minute, (int)$second, (int)$month, (int)$day, (int)$year);
$time = usertime($time, $timezone);
- if($applydst) {
- $time -= dst_offset_on($time, $strtimezone);
+
+ //Apply dst for string timezones or if 99 then try dst offset with user's default timezone
+ if ($applydst && ((99 == $passedtimezone) || !is_numeric($passedtimezone))) {
+ $time -= dst_offset_on($time, $passedtimezone);
}
}
@@ -1664,7 +1665,8 @@ function format_time($totalsecs, $str=NULL) {
* @param int $date the timestamp in UTC, as obtained from the database.
* @param string $format strftime format. You should probably get this using
* get_string('strftime...', 'langconfig');
- * @param float $timezone by default, uses the user's time zone.
+ * @param mixed $timezone by default, uses the user's time zone. if numeric and
+ * not 99 then daylight saving will not be added.
* @param bool $fixday If true (default) then the leading zero from %d is removed.
* If false then the leading zero is maintained.
* @return string the formatted date/time.
@@ -1673,11 +1675,6 @@ function userdate($date, $format = '', $timezone = 99, $fixday = true) {
global $CFG;
- $strtimezone = NULL;
- if (!is_numeric($timezone)) {
- $strtimezone = $timezone;
- }
-
if (empty($format)) {
$format = get_string('strftimedaydatetime', 'langconfig');
}
@@ -1689,7 +1686,11 @@ function userdate($date, $format = '', $timezone = 99, $fixday = true) {
$fixday = ($formatnoday != $format);
}
- $date += dst_offset_on($date, $strtimezone);
+ //add daylight saving offset for string timezones only, as we can't get dst for
+ //float values. if timezone is 99 (user default timezone), then try update dst.
+ if ((99 == $timezone) || !is_numeric($timezone)) {
+ $date += dst_offset_on($date, $timezone);
+ }
$timezone = get_user_timezone_offset($timezone);
@@ -1732,24 +1733,27 @@ function userdate($date, $format = '', $timezone = 99, $fixday = true) {
* @todo Finish documenting this function
* @uses HOURSECS
* @param int $time Timestamp in GMT
- * @param float $timezone ?
+ * @param mixed $timezone offset time with timezone, if float and not 99, then no
+ * dst offset is applyed
* @return array An array that represents the date in user time
*/
function usergetdate($time, $timezone=99) {
- $strtimezone = NULL;
- if (!is_numeric($timezone)) {
- $strtimezone = $timezone;
- }
+ //save input timezone, required for dst offset check.
+ $passedtimezone = $timezone;
$timezone = get_user_timezone_offset($timezone);
if (abs($timezone) > 13) { // Server time
return getdate($time);
}
- // There is no gmgetdate so we use gmdate instead
- $time += dst_offset_on($time, $strtimezone);
+ //add daylight saving offset for string timezones only, as we can't get dst for
+ //float values. if timezone is 99 (user default timezone), then try update dst.
+ if ($passedtimezone == 99 || !is_numeric($passedtimezone)) {
+ $time += dst_offset_on($time, $passedtimezone);
+ }
+
$time += intval((float)$timezone * HOURSECS);
$datestring = gmstrftime('%B_%A_%j_%Y_%m_%w_%d_%H_%M_%S', $time);
@@ -1900,7 +1904,7 @@ function get_timezone_offset($tz) {
*
* @global object
* @global object
- * @param float $tz If this value is provided and not equal to 99, it will be returned as is and no other settings will be checked
+ * @param mixed $tz If this value is provided and not equal to 99, it will be returned as is and no other settings will be checked
* @return mixed
*/
function get_user_timezone($tz = 99) {
@@ -1954,7 +1958,7 @@ function get_timezone_record($timezonename) {
* @global object
* @param mixed $from_year Start year for the table, defaults to 1971
* @param mixed $to_year End year for the table, defaults to 2035
- * @param mixed $strtimezone
+ * @param mixed $strtimezone, if null or 99 then user's default timezone is used
* @return bool
*/
function calculate_user_dst_table($from_year = NULL, $to_year = NULL, $strtimezone = NULL) {
@@ -2115,9 +2119,12 @@ function dst_changes_for_year($year, $timezone) {
/**
* Calculates the Daylight Saving Offset for a given date/time (timestamp)
+ * - Note: Daylight saving only works for string timezones and not for float.
*
* @global object
* @param int $time must NOT be compensated at all, it has to be a pure timestamp
+ * @param mixed $strtimezone timezone for which offset is expected, if 99 or null
+ * then user's default timezone is used.
* @return int
*/
function dst_offset_on($time, $strtimezone = NULL) {
View
297 lib/simpletest/testmoodlelib.php
@@ -515,7 +515,14 @@ function test_shorten_text() {
}
function test_usergetdate() {
- global $USER;
+ global $USER, $CFG;
+
+ //Check if forcetimezone is set then save it and set it to use user timezone
+ $cfgforcetimezone = null;
+ if (isset($CFG->forcetimezone)) {
+ $cfgforcetimezone = $CFG->forcetimezone;
+ $CFG->forcetimezone = 99; //get user default timezone.
+ }
$userstimezone = $USER->timezone;
$USER->timezone = 2;//set the timezone to a known state
@@ -559,6 +566,12 @@ function test_usergetdate() {
//set the timezone back to what it was
$USER->timezone = $userstimezone;
+
+ //restore forcetimezone if changed.
+ if (!is_null($cfgforcetimezone)) {
+ $CFG->forcetimezone = $cfgforcetimezone;
+ }
+
setlocale(LC_TIME, $oldlocale);
}
@@ -757,4 +770,286 @@ public function test_set_user_preference() {
$this->assertTrue(true);
}
}
+
+ public function test_userdate() {
+ global $USER, $CFG;
+
+ $testvalues = array(
+ array(
+ 'time' => '1309514400',
+ 'usertimezone' => 'America/Moncton',
+ 'timezone' => '0.0', //no dst offset
+ 'expectedoutput' => 'Friday, 1 July 2011, 10:00 AM'
+ ),
+ array(
+ 'time' => '1309514400',
+ 'usertimezone' => 'America/Moncton',
+ 'timezone' => '99', //dst offset and timezone offset.
+ 'expectedoutput' => 'Friday, 1 July 2011, 07:00 AM'
+ ),
+ array(
+ 'time' => '1309514400',
+ 'usertimezone' => 'America/Moncton',
+ 'timezone' => 'America/Moncton', //dst offset and timezone offset.
+ 'expectedoutput' => 'Friday, 1 July 2011, 07:00 AM'
+ ),
+ array(
+ 'time' => '1293876000 ',
+ 'usertimezone' => 'America/Moncton',
+ 'timezone' => '0.0', //no dst offset
+ 'expectedoutput' => 'Saturday, 1 January 2011, 10:00 AM'
+ ),
+ array(
+ 'time' => '1293876000 ',
+ 'usertimezone' => 'America/Moncton',
+ 'timezone' => '99', //no dst offset in jan, so just timezone offset.
+ 'expectedoutput' => 'Saturday, 1 January 2011, 06:00 AM'
+ ),
+ array(
+ 'time' => '1293876000 ',
+ 'usertimezone' => 'America/Moncton',
+ 'timezone' => 'America/Moncton', //no dst offset in jan
+ 'expectedoutput' => 'Saturday, 1 January 2011, 06:00 AM'
+ ),
+ array(
+ 'time' => '1293876000 ',
+ 'usertimezone' => '2',
+ 'timezone' => '99', //take user timezone
+ 'expectedoutput' => 'Saturday, 1 January 2011, 12:00 PM'
+ ),
+ array(
+ 'time' => '1293876000 ',
+ 'usertimezone' => '-2',
+ 'timezone' => '99', //take user timezone
+ 'expectedoutput' => 'Saturday, 1 January 2011, 08:00 AM'
+ ),
+ array(
+ 'time' => '1293876000 ',
+ 'usertimezone' => '-10',
+ 'timezone' => '2', //take this timezone
+ 'expectedoutput' => 'Saturday, 1 January 2011, 12:00 PM'
+ ),
+ array(
+ 'time' => '1293876000 ',
+ 'usertimezone' => '-10',
+ 'timezone' => '-2', //take this timezone
+ 'expectedoutput' => 'Saturday, 1 January 2011, 08:00 AM'
+ ),
+ array(
+ 'time' => '1293876000 ',
+ 'usertimezone' => '-10',
+ 'timezone' => 'random/time', //this should show server time
+ 'expectedoutput' => 'Saturday, 1 January 2011, 06:00 PM'
+ ),
+ array(
+ 'time' => '1293876000 ',
+ 'usertimezone' => '14', //server time zone
+ 'timezone' => '99', //this should show user time
+ 'expectedoutput' => 'Saturday, 1 January 2011, 06:00 PM'
+ ),
+ );
+
+ //Check if forcetimezone is set then save it and set it to use user timezone
+ $cfgforcetimezone = null;
+ if (isset($CFG->forcetimezone)) {
+ $cfgforcetimezone = $CFG->forcetimezone;
+ $CFG->forcetimezone = 99; //get user default timezone.
+ }
+ //store user default timezone to restore later
+ $userstimezone = $USER->timezone;
+
+ // The string version of date comes from server locale setting and does
+ // not respect user language, so it is necessary to reset that.
+ $oldlocale = setlocale(LC_TIME, '0');
+ setlocale(LC_TIME, 'en_AU.UTF-8');
+
+ foreach ($testvalues as $vals) {
+ $USER->timezone = $vals['usertimezone'];
+ $actualoutput = userdate($vals['time'], '%A, %d %B %Y, %I:%M %p', $vals['timezone']);
+ $this->assertEqual($vals['expectedoutput'], $actualoutput,
+ "Expected: {$vals['expectedoutput']} => Actual: {$actualoutput},
+ Please check if timezones are updated (Site adminstration -> location -> update timezone)");
+ }
+
+ //restore user timezone back to what it was
+ $USER->timezone = $userstimezone;
+
+ //restore forcetimezone
+ if (!is_null($cfgforcetimezone)) {
+ $CFG->forcetimezone = $cfgforcetimezone;
+ }
+
+ setlocale(LC_TIME, $oldlocale);
+ }
+
+ public function test_make_timestamp() {
+ global $USER, $CFG;
+
+ $testvalues = array(
+ array(
+ 'usertimezone' => 'America/Moncton',
+ 'year' => '2011',
+ 'month' => '7',
+ 'day' => '1',
+ 'hour' => '10',
+ 'minutes' => '00',
+ 'seconds' => '00',
+ 'timezone' => '0.0', //no dst offset
+ 'applydst' => false,
+ 'expectedoutput' => '1309528800'
+ ),
+ array(
+ 'usertimezone' => 'America/Moncton',
+ 'year' => '2011',
+ 'month' => '7',
+ 'day' => '1',
+ 'hour' => '10',
+ 'minutes' => '00',
+ 'seconds' => '00',
+ 'timezone' => '99', //user default timezone
+ 'applydst' => false, //don't apply dst
+ 'expectedoutput' => '1309528800'
+ ),
+ array(
+ 'usertimezone' => 'America/Moncton',
+ 'year' => '2011',
+ 'month' => '7',
+ 'day' => '1',
+ 'hour' => '10',
+ 'minutes' => '00',
+ 'seconds' => '00',
+ 'timezone' => '99', //user default timezone
+ 'applydst' => true, //apply dst
+ 'expectedoutput' => '1309525200'
+ ),
+ array(
+ 'usertimezone' => 'America/Moncton',
+ 'year' => '2011',
+ 'month' => '7',
+ 'day' => '1',
+ 'hour' => '10',
+ 'minutes' => '00',
+ 'seconds' => '00',
+ 'timezone' => 'America/Moncton', //string timezone
+ 'applydst' => true, //apply dst
+ 'expectedoutput' => '1309525200'
+ ),
+ array(
+ 'usertimezone' => '2',//no dst applyed
+ 'year' => '2011',
+ 'month' => '7',
+ 'day' => '1',
+ 'hour' => '10',
+ 'minutes' => '00',
+ 'seconds' => '00',
+ 'timezone' => '99', //take user timezone
+ 'applydst' => true, //apply dst
+ 'expectedoutput' => '1309507200'
+ ),
+ array(
+ 'usertimezone' => '-2',//no dst applyed
+ 'year' => '2011',
+ 'month' => '7',
+ 'day' => '1',
+ 'hour' => '10',
+ 'minutes' => '00',
+ 'seconds' => '00',
+ 'timezone' => '99', //take usertimezone
+ 'applydst' => true, //apply dst
+ 'expectedoutput' => '1309521600'
+ ),
+ array(
+ 'usertimezone' => '-10',//no dst applyed
+ 'year' => '2011',
+ 'month' => '7',
+ 'day' => '1',
+ 'hour' => '10',
+ 'minutes' => '00',
+ 'seconds' => '00',
+ 'timezone' => '2', //take this timezone
+ 'applydst' => true, //apply dst
+ 'expectedoutput' => '1309507200'
+ ),
+ array(
+ 'usertimezone' => '-10',//no dst applyed
+ 'year' => '2011',
+ 'month' => '7',
+ 'day' => '1',
+ 'hour' => '10',
+ 'minutes' => '00',
+ 'seconds' => '00',
+ 'timezone' => '-2', //take this timezone
+ 'applydst' => true, //apply dst,
+ 'expectedoutput' => '1309521600'
+ ),
+ array(
+ 'usertimezone' => '-10',//no dst applyed
+ 'year' => '2011',
+ 'month' => '7',
+ 'day' => '1',
+ 'hour' => '10',
+ 'minutes' => '00',
+ 'seconds' => '00',
+ 'timezone' => 'random/time', //This should show server time
+ 'applydst' => true, //apply dst,
+ 'expectedoutput' => '1309485600'
+ ),
+ array(
+ 'usertimezone' => '14',//server time
+ 'year' => '2011',
+ 'month' => '7',
+ 'day' => '1',
+ 'hour' => '10',
+ 'minutes' => '00',
+ 'seconds' => '00',
+ 'timezone' => '99', //get user time
+ 'applydst' => true, //apply dst,
+ 'expectedoutput' => '1309485600'
+ )
+ );
+
+ //Check if forcetimezone is set then save it and set it to use user timezone
+ $cfgforcetimezone = null;
+ if (isset($CFG->forcetimezone)) {
+ $cfgforcetimezone = $CFG->forcetimezone;
+ $CFG->forcetimezone = 99; //get user default timezone.
+ }
+
+ //store user default timezone to restore later
+ $userstimezone = $USER->timezone;
+
+ // The string version of date comes from server locale setting and does
+ // not respect user language, so it is necessary to reset that.
+ $oldlocale = setlocale(LC_TIME, '0');
+ setlocale(LC_TIME, 'en_AU.UTF-8');
+
+ //Test make_timestamp with all testvals and assert if anything wrong.
+ foreach ($testvalues as $vals) {
+ $USER->timezone = $vals['usertimezone'];
+ $actualoutput = make_timestamp(
+ $vals['year'],
+ $vals['month'],
+ $vals['day'],
+ $vals['hour'],
+ $vals['minutes'],
+ $vals['seconds'],
+ $vals['timezone'],
+ $vals['applydst']
+ );
+
+ $this->assertEqual($vals['expectedoutput'], $actualoutput,
+ "Expected: {$vals['expectedoutput']} => Actual: {$actualoutput},
+ Please check if timezones are updated (Site adminstration -> location -> update timezone)");
+ }
+
+ //restore user timezone back to what it was
+ $USER->timezone = $userstimezone;
+
+ //restore forcetimezone
+ if (!is_null($cfgforcetimezone)) {
+ $CFG->forcetimezone = $cfgforcetimezone;
+ }
+
+ setlocale(LC_TIME, $oldlocale);
+ }
}

0 comments on commit 014fba4

Please sign in to comment.
Something went wrong with that request. Please try again.