Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

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

…ake_timestamp functions
  • Loading branch information...
commit 014fba4928b9c9282c3affaf8243d9b914267328 1 parent dba2410
Rajesh Taneja authored

Showing 2 changed files with 328 additions and 26 deletions. Show diff stats Hide diff stats

  1. +32 25 lib/moodlelib.php
  2. +296 1 lib/simpletest/testmoodlelib.php
57 lib/moodlelib.php
@@ -1554,26 +1554,27 @@ function get_user_preferences($name = null, $default = null, $user = null) {
1554 1554 * @param int $hour The hour part to create timestamp of
1555 1555 * @param int $minute The minute part to create timestamp of
1556 1556 * @param int $second The second part to create timestamp of
1557   - * @param float $timezone Timezone modifier
1558   - * @param bool $applydst Toggle Daylight Saving Time, default true
  1557 + * @param mixed $timezone Timezone modifier, if 99 then use default user's timezone
  1558 + * @param bool $applydst Toggle Daylight Saving Time, default true, will be
  1559 + * applied only if timezone is 99 or string.
1559 1560 * @return int timestamp
1560 1561 */
1561 1562 function make_timestamp($year, $month=1, $day=1, $hour=0, $minute=0, $second=0, $timezone=99, $applydst=true) {
1562 1563
1563   - $strtimezone = NULL;
1564   - if (!is_numeric($timezone)) {
1565   - $strtimezone = $timezone;
1566   - }
  1564 + //save input timezone, required for dst offset check.
  1565 + $passedtimezone = $timezone;
1567 1566
1568 1567 $timezone = get_user_timezone_offset($timezone);
1569 1568
1570   - if (abs($timezone) > 13) {
  1569 + if (abs($timezone) > 13) { //server time
1571 1570 $time = mktime((int)$hour, (int)$minute, (int)$second, (int)$month, (int)$day, (int)$year);
1572 1571 } else {
1573 1572 $time = gmmktime((int)$hour, (int)$minute, (int)$second, (int)$month, (int)$day, (int)$year);
1574 1573 $time = usertime($time, $timezone);
1575   - if($applydst) {
1576   - $time -= dst_offset_on($time, $strtimezone);
  1574 +
  1575 + //Apply dst for string timezones or if 99 then try dst offset with user's default timezone
  1576 + if ($applydst && ((99 == $passedtimezone) || !is_numeric($passedtimezone))) {
  1577 + $time -= dst_offset_on($time, $passedtimezone);
1577 1578 }
1578 1579 }
1579 1580
@@ -1664,7 +1665,8 @@ function format_time($totalsecs, $str=NULL) {
1664 1665 * @param int $date the timestamp in UTC, as obtained from the database.
1665 1666 * @param string $format strftime format. You should probably get this using
1666 1667 * get_string('strftime...', 'langconfig');
1667   - * @param float $timezone by default, uses the user's time zone.
  1668 + * @param mixed $timezone by default, uses the user's time zone. if numeric and
  1669 + * not 99 then daylight saving will not be added.
1668 1670 * @param bool $fixday If true (default) then the leading zero from %d is removed.
1669 1671 * If false then the leading zero is maintained.
1670 1672 * @return string the formatted date/time.
@@ -1673,11 +1675,6 @@ function userdate($date, $format = '', $timezone = 99, $fixday = true) {
1673 1675
1674 1676 global $CFG;
1675 1677
1676   - $strtimezone = NULL;
1677   - if (!is_numeric($timezone)) {
1678   - $strtimezone = $timezone;
1679   - }
1680   -
1681 1678 if (empty($format)) {
1682 1679 $format = get_string('strftimedaydatetime', 'langconfig');
1683 1680 }
@@ -1689,7 +1686,11 @@ function userdate($date, $format = '', $timezone = 99, $fixday = true) {
1689 1686 $fixday = ($formatnoday != $format);
1690 1687 }
1691 1688
1692   - $date += dst_offset_on($date, $strtimezone);
  1689 + //add daylight saving offset for string timezones only, as we can't get dst for
  1690 + //float values. if timezone is 99 (user default timezone), then try update dst.
  1691 + if ((99 == $timezone) || !is_numeric($timezone)) {
  1692 + $date += dst_offset_on($date, $timezone);
  1693 + }
1693 1694
1694 1695 $timezone = get_user_timezone_offset($timezone);
1695 1696
@@ -1732,15 +1733,14 @@ function userdate($date, $format = '', $timezone = 99, $fixday = true) {
1732 1733 * @todo Finish documenting this function
1733 1734 * @uses HOURSECS
1734 1735 * @param int $time Timestamp in GMT
1735   - * @param float $timezone ?
  1736 + * @param mixed $timezone offset time with timezone, if float and not 99, then no
  1737 + * dst offset is applyed
1736 1738 * @return array An array that represents the date in user time
1737 1739 */
1738 1740 function usergetdate($time, $timezone=99) {
1739 1741
1740   - $strtimezone = NULL;
1741   - if (!is_numeric($timezone)) {
1742   - $strtimezone = $timezone;
1743   - }
  1742 + //save input timezone, required for dst offset check.
  1743 + $passedtimezone = $timezone;
1744 1744
1745 1745 $timezone = get_user_timezone_offset($timezone);
1746 1746
@@ -1748,8 +1748,12 @@ function usergetdate($time, $timezone=99) {
1748 1748 return getdate($time);
1749 1749 }
1750 1750
1751   - // There is no gmgetdate so we use gmdate instead
1752   - $time += dst_offset_on($time, $strtimezone);
  1751 + //add daylight saving offset for string timezones only, as we can't get dst for
  1752 + //float values. if timezone is 99 (user default timezone), then try update dst.
  1753 + if ($passedtimezone == 99 || !is_numeric($passedtimezone)) {
  1754 + $time += dst_offset_on($time, $passedtimezone);
  1755 + }
  1756 +
1753 1757 $time += intval((float)$timezone * HOURSECS);
1754 1758
1755 1759 $datestring = gmstrftime('%B_%A_%j_%Y_%m_%w_%d_%H_%M_%S', $time);
@@ -1900,7 +1904,7 @@ function get_timezone_offset($tz) {
1900 1904 *
1901 1905 * @global object
1902 1906 * @global object
1903   - * @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
  1907 + * @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
1904 1908 * @return mixed
1905 1909 */
1906 1910 function get_user_timezone($tz = 99) {
@@ -1954,7 +1958,7 @@ function get_timezone_record($timezonename) {
1954 1958 * @global object
1955 1959 * @param mixed $from_year Start year for the table, defaults to 1971
1956 1960 * @param mixed $to_year End year for the table, defaults to 2035
1957   - * @param mixed $strtimezone
  1961 + * @param mixed $strtimezone, if null or 99 then user's default timezone is used
1958 1962 * @return bool
1959 1963 */
1960 1964 function calculate_user_dst_table($from_year = NULL, $to_year = NULL, $strtimezone = NULL) {
@@ -2115,9 +2119,12 @@ function dst_changes_for_year($year, $timezone) {
2115 2119
2116 2120 /**
2117 2121 * Calculates the Daylight Saving Offset for a given date/time (timestamp)
  2122 + * - Note: Daylight saving only works for string timezones and not for float.
2118 2123 *
2119 2124 * @global object
2120 2125 * @param int $time must NOT be compensated at all, it has to be a pure timestamp
  2126 + * @param mixed $strtimezone timezone for which offset is expected, if 99 or null
  2127 + * then user's default timezone is used.
2121 2128 * @return int
2122 2129 */
2123 2130 function dst_offset_on($time, $strtimezone = NULL) {
297 lib/simpletest/testmoodlelib.php
@@ -515,7 +515,14 @@ function test_shorten_text() {
515 515 }
516 516
517 517 function test_usergetdate() {
518   - global $USER;
  518 + global $USER, $CFG;
  519 +
  520 + //Check if forcetimezone is set then save it and set it to use user timezone
  521 + $cfgforcetimezone = null;
  522 + if (isset($CFG->forcetimezone)) {
  523 + $cfgforcetimezone = $CFG->forcetimezone;
  524 + $CFG->forcetimezone = 99; //get user default timezone.
  525 + }
519 526
520 527 $userstimezone = $USER->timezone;
521 528 $USER->timezone = 2;//set the timezone to a known state
@@ -559,6 +566,12 @@ function test_usergetdate() {
559 566
560 567 //set the timezone back to what it was
561 568 $USER->timezone = $userstimezone;
  569 +
  570 + //restore forcetimezone if changed.
  571 + if (!is_null($cfgforcetimezone)) {
  572 + $CFG->forcetimezone = $cfgforcetimezone;
  573 + }
  574 +
562 575 setlocale(LC_TIME, $oldlocale);
563 576 }
564 577
@@ -757,4 +770,286 @@ public function test_set_user_preference() {
757 770 $this->assertTrue(true);
758 771 }
759 772 }
  773 +
  774 + public function test_userdate() {
  775 + global $USER, $CFG;
  776 +
  777 + $testvalues = array(
  778 + array(
  779 + 'time' => '1309514400',
  780 + 'usertimezone' => 'America/Moncton',
  781 + 'timezone' => '0.0', //no dst offset
  782 + 'expectedoutput' => 'Friday, 1 July 2011, 10:00 AM'
  783 + ),
  784 + array(
  785 + 'time' => '1309514400',
  786 + 'usertimezone' => 'America/Moncton',
  787 + 'timezone' => '99', //dst offset and timezone offset.
  788 + 'expectedoutput' => 'Friday, 1 July 2011, 07:00 AM'
  789 + ),
  790 + array(
  791 + 'time' => '1309514400',
  792 + 'usertimezone' => 'America/Moncton',
  793 + 'timezone' => 'America/Moncton', //dst offset and timezone offset.
  794 + 'expectedoutput' => 'Friday, 1 July 2011, 07:00 AM'
  795 + ),
  796 + array(
  797 + 'time' => '1293876000 ',
  798 + 'usertimezone' => 'America/Moncton',
  799 + 'timezone' => '0.0', //no dst offset
  800 + 'expectedoutput' => 'Saturday, 1 January 2011, 10:00 AM'
  801 + ),
  802 + array(
  803 + 'time' => '1293876000 ',
  804 + 'usertimezone' => 'America/Moncton',
  805 + 'timezone' => '99', //no dst offset in jan, so just timezone offset.
  806 + 'expectedoutput' => 'Saturday, 1 January 2011, 06:00 AM'
  807 + ),
  808 + array(
  809 + 'time' => '1293876000 ',
  810 + 'usertimezone' => 'America/Moncton',
  811 + 'timezone' => 'America/Moncton', //no dst offset in jan
  812 + 'expectedoutput' => 'Saturday, 1 January 2011, 06:00 AM'
  813 + ),
  814 + array(
  815 + 'time' => '1293876000 ',
  816 + 'usertimezone' => '2',
  817 + 'timezone' => '99', //take user timezone
  818 + 'expectedoutput' => 'Saturday, 1 January 2011, 12:00 PM'
  819 + ),
  820 + array(
  821 + 'time' => '1293876000 ',
  822 + 'usertimezone' => '-2',
  823 + 'timezone' => '99', //take user timezone
  824 + 'expectedoutput' => 'Saturday, 1 January 2011, 08:00 AM'
  825 + ),
  826 + array(
  827 + 'time' => '1293876000 ',
  828 + 'usertimezone' => '-10',
  829 + 'timezone' => '2', //take this timezone
  830 + 'expectedoutput' => 'Saturday, 1 January 2011, 12:00 PM'
  831 + ),
  832 + array(
  833 + 'time' => '1293876000 ',
  834 + 'usertimezone' => '-10',
  835 + 'timezone' => '-2', //take this timezone
  836 + 'expectedoutput' => 'Saturday, 1 January 2011, 08:00 AM'
  837 + ),
  838 + array(
  839 + 'time' => '1293876000 ',
  840 + 'usertimezone' => '-10',
  841 + 'timezone' => 'random/time', //this should show server time
  842 + 'expectedoutput' => 'Saturday, 1 January 2011, 06:00 PM'
  843 + ),
  844 + array(
  845 + 'time' => '1293876000 ',
  846 + 'usertimezone' => '14', //server time zone
  847 + 'timezone' => '99', //this should show user time
  848 + 'expectedoutput' => 'Saturday, 1 January 2011, 06:00 PM'
  849 + ),
  850 + );
  851 +
  852 + //Check if forcetimezone is set then save it and set it to use user timezone
  853 + $cfgforcetimezone = null;
  854 + if (isset($CFG->forcetimezone)) {
  855 + $cfgforcetimezone = $CFG->forcetimezone;
  856 + $CFG->forcetimezone = 99; //get user default timezone.
  857 + }
  858 + //store user default timezone to restore later
  859 + $userstimezone = $USER->timezone;
  860 +
  861 + // The string version of date comes from server locale setting and does
  862 + // not respect user language, so it is necessary to reset that.
  863 + $oldlocale = setlocale(LC_TIME, '0');
  864 + setlocale(LC_TIME, 'en_AU.UTF-8');
  865 +
  866 + foreach ($testvalues as $vals) {
  867 + $USER->timezone = $vals['usertimezone'];
  868 + $actualoutput = userdate($vals['time'], '%A, %d %B %Y, %I:%M %p', $vals['timezone']);
  869 + $this->assertEqual($vals['expectedoutput'], $actualoutput,
  870 + "Expected: {$vals['expectedoutput']} => Actual: {$actualoutput},
  871 + Please check if timezones are updated (Site adminstration -> location -> update timezone)");
  872 + }
  873 +
  874 + //restore user timezone back to what it was
  875 + $USER->timezone = $userstimezone;
  876 +
  877 + //restore forcetimezone
  878 + if (!is_null($cfgforcetimezone)) {
  879 + $CFG->forcetimezone = $cfgforcetimezone;
  880 + }
  881 +
  882 + setlocale(LC_TIME, $oldlocale);
  883 + }
  884 +
  885 + public function test_make_timestamp() {
  886 + global $USER, $CFG;
  887 +
  888 + $testvalues = array(
  889 + array(
  890 + 'usertimezone' => 'America/Moncton',
  891 + 'year' => '2011',
  892 + 'month' => '7',
  893 + 'day' => '1',
  894 + 'hour' => '10',
  895 + 'minutes' => '00',
  896 + 'seconds' => '00',
  897 + 'timezone' => '0.0', //no dst offset
  898 + 'applydst' => false,
  899 + 'expectedoutput' => '1309528800'
  900 + ),
  901 + array(
  902 + 'usertimezone' => 'America/Moncton',
  903 + 'year' => '2011',
  904 + 'month' => '7',
  905 + 'day' => '1',
  906 + 'hour' => '10',
  907 + 'minutes' => '00',
  908 + 'seconds' => '00',
  909 + 'timezone' => '99', //user default timezone
  910 + 'applydst' => false, //don't apply dst
  911 + 'expectedoutput' => '1309528800'
  912 + ),
  913 + array(
  914 + 'usertimezone' => 'America/Moncton',
  915 + 'year' => '2011',
  916 + 'month' => '7',
  917 + 'day' => '1',
  918 + 'hour' => '10',
  919 + 'minutes' => '00',
  920 + 'seconds' => '00',
  921 + 'timezone' => '99', //user default timezone
  922 + 'applydst' => true, //apply dst
  923 + 'expectedoutput' => '1309525200'
  924 + ),
  925 + array(
  926 + 'usertimezone' => 'America/Moncton',
  927 + 'year' => '2011',
  928 + 'month' => '7',
  929 + 'day' => '1',
  930 + 'hour' => '10',
  931 + 'minutes' => '00',
  932 + 'seconds' => '00',
  933 + 'timezone' => 'America/Moncton', //string timezone
  934 + 'applydst' => true, //apply dst
  935 + 'expectedoutput' => '1309525200'
  936 + ),
  937 + array(
  938 + 'usertimezone' => '2',//no dst applyed
  939 + 'year' => '2011',
  940 + 'month' => '7',
  941 + 'day' => '1',
  942 + 'hour' => '10',
  943 + 'minutes' => '00',
  944 + 'seconds' => '00',
  945 + 'timezone' => '99', //take user timezone
  946 + 'applydst' => true, //apply dst
  947 + 'expectedoutput' => '1309507200'
  948 + ),
  949 + array(
  950 + 'usertimezone' => '-2',//no dst applyed
  951 + 'year' => '2011',
  952 + 'month' => '7',
  953 + 'day' => '1',
  954 + 'hour' => '10',
  955 + 'minutes' => '00',
  956 + 'seconds' => '00',
  957 + 'timezone' => '99', //take usertimezone
  958 + 'applydst' => true, //apply dst
  959 + 'expectedoutput' => '1309521600'
  960 + ),
  961 + array(
  962 + 'usertimezone' => '-10',//no dst applyed
  963 + 'year' => '2011',
  964 + 'month' => '7',
  965 + 'day' => '1',
  966 + 'hour' => '10',
  967 + 'minutes' => '00',
  968 + 'seconds' => '00',
  969 + 'timezone' => '2', //take this timezone
  970 + 'applydst' => true, //apply dst
  971 + 'expectedoutput' => '1309507200'
  972 + ),
  973 + array(
  974 + 'usertimezone' => '-10',//no dst applyed
  975 + 'year' => '2011',
  976 + 'month' => '7',
  977 + 'day' => '1',
  978 + 'hour' => '10',
  979 + 'minutes' => '00',
  980 + 'seconds' => '00',
  981 + 'timezone' => '-2', //take this timezone
  982 + 'applydst' => true, //apply dst,
  983 + 'expectedoutput' => '1309521600'
  984 + ),
  985 + array(
  986 + 'usertimezone' => '-10',//no dst applyed
  987 + 'year' => '2011',
  988 + 'month' => '7',
  989 + 'day' => '1',
  990 + 'hour' => '10',
  991 + 'minutes' => '00',
  992 + 'seconds' => '00',
  993 + 'timezone' => 'random/time', //This should show server time
  994 + 'applydst' => true, //apply dst,
  995 + 'expectedoutput' => '1309485600'
  996 + ),
  997 + array(
  998 + 'usertimezone' => '14',//server time
  999 + 'year' => '2011',
  1000 + 'month' => '7',
  1001 + 'day' => '1',
  1002 + 'hour' => '10',
  1003 + 'minutes' => '00',
  1004 + 'seconds' => '00',
  1005 + 'timezone' => '99', //get user time
  1006 + 'applydst' => true, //apply dst,
  1007 + 'expectedoutput' => '1309485600'
  1008 + )
  1009 + );
  1010 +
  1011 + //Check if forcetimezone is set then save it and set it to use user timezone
  1012 + $cfgforcetimezone = null;
  1013 + if (isset($CFG->forcetimezone)) {
  1014 + $cfgforcetimezone = $CFG->forcetimezone;
  1015 + $CFG->forcetimezone = 99; //get user default timezone.
  1016 + }
  1017 +
  1018 + //store user default timezone to restore later
  1019 + $userstimezone = $USER->timezone;
  1020 +
  1021 + // The string version of date comes from server locale setting and does
  1022 + // not respect user language, so it is necessary to reset that.
  1023 + $oldlocale = setlocale(LC_TIME, '0');
  1024 + setlocale(LC_TIME, 'en_AU.UTF-8');
  1025 +
  1026 + //Test make_timestamp with all testvals and assert if anything wrong.
  1027 + foreach ($testvalues as $vals) {
  1028 + $USER->timezone = $vals['usertimezone'];
  1029 + $actualoutput = make_timestamp(
  1030 + $vals['year'],
  1031 + $vals['month'],
  1032 + $vals['day'],
  1033 + $vals['hour'],
  1034 + $vals['minutes'],
  1035 + $vals['seconds'],
  1036 + $vals['timezone'],
  1037 + $vals['applydst']
  1038 + );
  1039 +
  1040 + $this->assertEqual($vals['expectedoutput'], $actualoutput,
  1041 + "Expected: {$vals['expectedoutput']} => Actual: {$actualoutput},
  1042 + Please check if timezones are updated (Site adminstration -> location -> update timezone)");
  1043 + }
  1044 +
  1045 + //restore user timezone back to what it was
  1046 + $USER->timezone = $userstimezone;
  1047 +
  1048 + //restore forcetimezone
  1049 + if (!is_null($cfgforcetimezone)) {
  1050 + $CFG->forcetimezone = $cfgforcetimezone;
  1051 + }
  1052 +
  1053 + setlocale(LC_TIME, $oldlocale);
  1054 + }
760 1055 }

0 comments on commit 014fba4

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