Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401]

   1  <?php
   2  // This file is part of Moodle - http://moodle.org/
   3  //
   4  // Moodle is free software: you can redistribute it and/or modify
   5  // it under the terms of the GNU General Public License as published by
   6  // the Free Software Foundation, either version 3 of the License, or
   7  // (at your option) any later version.
   8  //
   9  // Moodle is distributed in the hope that it will be useful,
  10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  // GNU General Public License for more details.
  13  //
  14  // You should have received a copy of the GNU General Public License
  15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  16  
  17  namespace core;
  18  
  19  /**
  20   * Tests legacy Moodle date/time functions.
  21   *
  22   * @package   core
  23   * @copyright 2015 Totara Learning Solutions Ltd {@link http://www.totaralms.com/}
  24   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  25   * @author    Petr Skoda <petr.skoda@totaralms.com>
  26   */
  27  class date_legacy_test extends \advanced_testcase {
  28      public function test_settings() {
  29          global $CFG;
  30          $this->resetAfterTest();
  31  
  32          $this->assertNotEmpty($CFG->timezone);
  33  
  34          $this->assertSame('99', $CFG->forcetimezone);
  35  
  36          $user = $this->getDataGenerator()->create_user();
  37          $this->assertSame('99', $user->timezone);
  38      }
  39  
  40      public function test_get_user_timezone() {
  41          global $CFG, $USER;
  42  
  43          $this->resetAfterTest();
  44  
  45          $user = $this->getDataGenerator()->create_user();
  46          $this->setUser($user);
  47  
  48          // All set to something.
  49  
  50          $this->setTimezone('Pacific/Auckland', 'Pacific/Auckland');
  51          $USER->timezone = 'Europe/Prague';
  52  
  53          $tz = get_user_timezone();
  54          $this->assertSame('Europe/Prague', $tz);
  55  
  56          $tz = get_user_timezone(99);
  57          $this->assertSame('Europe/Prague', $tz);
  58          $tz = get_user_timezone('99');
  59          $this->assertSame('Europe/Prague', $tz);
  60  
  61          $tz = get_user_timezone('Europe/Berlin');
  62          $this->assertSame('Europe/Berlin', $tz);
  63  
  64          // User timezone not set.
  65  
  66          $this->setTimezone('Pacific/Auckland', 'Pacific/Auckland');
  67          $USER->timezone = '99';
  68  
  69          $tz = get_user_timezone();
  70          $this->assertSame('Pacific/Auckland', $tz);
  71  
  72          $tz = get_user_timezone(99);
  73          $this->assertSame('Pacific/Auckland', $tz);
  74          $tz = get_user_timezone('99');
  75          $this->assertSame('Pacific/Auckland', $tz);
  76  
  77          $tz = get_user_timezone('Europe/Berlin');
  78          $this->assertSame('Europe/Berlin', $tz);
  79  
  80          // Server timezone not set.
  81  
  82          $this->setTimezone('99', 'Pacific/Auckland');
  83          $USER->timezone = 'Europe/Prague';
  84  
  85          $tz = get_user_timezone();
  86          $this->assertSame('Europe/Prague', $tz);
  87  
  88          $tz = get_user_timezone(99);
  89          $this->assertSame('Europe/Prague', $tz);
  90          $tz = get_user_timezone('99');
  91          $this->assertSame('Europe/Prague', $tz);
  92  
  93          $tz = get_user_timezone('Europe/Berlin');
  94          $this->assertSame('Europe/Berlin', $tz);
  95  
  96          // Server and user timezone not set.
  97  
  98          $this->setTimezone('99', 'Pacific/Auckland');
  99          $USER->timezone = '99';
 100  
 101          $tz = get_user_timezone();
 102          $this->assertSame(99.0, $tz);
 103  
 104          $tz = get_user_timezone(99);
 105          $this->assertSame(99.0, $tz);
 106          $tz = get_user_timezone('99');
 107          $this->assertSame(99.0, $tz);
 108  
 109          $tz = get_user_timezone('Europe/Berlin');
 110          $this->assertSame('Europe/Berlin', $tz);
 111      }
 112  
 113      public function test_dst_offset_on() {
 114          $time = gmmktime(1, 1, 1, 3, 1, 2015);
 115          $this->assertSame(3600, dst_offset_on($time, 'Pacific/Auckland'));
 116          $this->assertSame(0, dst_offset_on($time, 'Australia/Perth'));
 117          $this->assertSame(1800, dst_offset_on($time, 'Australia/Lord_Howe'));
 118          $this->assertSame(0, dst_offset_on($time, 'Europe/Prague'));
 119          $this->assertSame(0, dst_offset_on($time, 'America/New_York'));
 120  
 121          $time = gmmktime(1, 1, 1, 5, 1, 2015);
 122          $this->assertSame(0, dst_offset_on($time, 'Pacific/Auckland'));
 123          $this->assertSame(0, dst_offset_on($time, 'Australia/Perth'));
 124          $this->assertSame(0, dst_offset_on($time, 'Australia/Lord_Howe'));
 125          $this->assertSame(3600, dst_offset_on($time, 'Europe/Prague'));
 126          $this->assertSame(3600, dst_offset_on($time, 'America/New_York'));
 127      }
 128  
 129      public function test_make_timestamp() {
 130          global $CFG;
 131  
 132          $this->resetAfterTest();
 133  
 134          // There are quite a lot of problems, let's pick some less problematic zones for now.
 135          $timezones = array('Europe/Prague', 'Europe/London', 'Australia/Perth', 'Pacific/Auckland', 'America/New_York', '99');
 136  
 137          $dates = array(
 138              array(2, 1, 0, 40, 40),
 139              array(4, 3, 0, 30, 22),
 140              array(9, 5, 0, 20, 19),
 141              array(11, 28, 0, 10, 45),
 142          );
 143          $years = array(1999, 2009, 2014, 2018);
 144  
 145          $this->setTimezone('Pacific/Auckland', 'Pacific/Auckland');
 146          foreach ($timezones as $tz) {
 147              foreach ($years as $year) {
 148                  foreach ($dates as $date) {
 149                      $result = make_timestamp($year, $date[0], $date[1], $date[2], $date[3], $date[4], $tz, true);
 150                      $expected = new \DateTime('now', new \DateTimeZone(($tz == 99 ? 'Pacific/Auckland' : $tz)));
 151                      $expected->setDate($year, $date[0], $date[1]);
 152                      $expected->setTime($date[2], $date[3], $date[4]);
 153                      $this->assertSame($expected->getTimestamp(), $result,
 154                          'Incorrect result for data ' . $expected->format("D, d M Y H:i:s O") . ' ' . $tz);
 155                  }
 156              }
 157          }
 158  
 159          $this->setTimezone('99', 'Pacific/Auckland');
 160          foreach ($timezones as $tz) {
 161              foreach ($years as $year) {
 162                  foreach ($dates as $date) {
 163                      $result = make_timestamp($year, $date[0], $date[1], $date[2], $date[3], $date[4], $tz, true);
 164                      $expected = new \DateTime('now', new \DateTimeZone(($tz == 99 ? 'Pacific/Auckland' : $tz)));
 165                      $expected->setDate($year, $date[0], $date[1]);
 166                      $expected->setTime($date[2], $date[3], $date[4]);
 167                      $this->assertSame($expected->getTimestamp(), $result,
 168                          'Incorrect result for data ' . $expected->format("D, d M Y H:i:s O") . ' ' . $tz);
 169                  }
 170              }
 171          }
 172      }
 173  
 174      public function test_usergetdate() {
 175          global $CFG;
 176  
 177          $this->resetAfterTest();
 178  
 179          // There are quite a lot of problems, let's pick some less problematic zones for now.
 180          $timezones = array('Europe/Prague', 'Europe/London', 'Australia/Perth', 'Pacific/Auckland', 'America/New_York', '99');
 181  
 182          $dates = array(
 183              array(2, 1, 0, 40, 40),
 184              array(4, 3, 0, 30, 22),
 185              array(9, 5, 0, 20, 19),
 186              array(11, 28, 0, 10, 45),
 187          );
 188          $years = array(1999, 2009, 2014, 2018);
 189  
 190          $this->setTimezone('Pacific/Auckland', 'Pacific/Auckland');
 191          foreach ($timezones as $tz) {
 192              foreach ($years as $year) {
 193                  foreach ($dates as $date) {
 194                      $expected = new \DateTime('now', new \DateTimeZone(($tz == 99 ? 'Pacific/Auckland' : $tz)));
 195                      $expected->setDate($year, $date[0], $date[1]);
 196                      $expected->setTime($date[2], $date[3], $date[4]);
 197                      $result = usergetdate($expected->getTimestamp(), $tz);
 198                      unset($result[0]); // Extra introduced by getdate().
 199                      $ex = array(
 200                          'seconds' => $date[4],
 201                          'minutes' => $date[3],
 202                          'hours' => $date[2],
 203                          'mday' => $date[1],
 204                          'wday' => (int)$expected->format('w'),
 205                          'mon' => $date[0],
 206                          'year' => $year,
 207                          'yday' => (int)$expected->format('z'),
 208                          'weekday' => $expected->format('l'),
 209                          'month' => $expected->format('F'),
 210                      );
 211                      $this->assertSame($ex, $result,
 212                          'Incorrect result for data ' . $expected->format("D, d M Y H:i:s O") . ' ' . $tz);
 213                  }
 214              }
 215          }
 216  
 217          $this->setTimezone('99', 'Pacific/Auckland');
 218          foreach ($timezones as $tz) {
 219              foreach ($years as $year) {
 220                  foreach ($dates as $date) {
 221                      $expected = new \DateTime('now', new \DateTimeZone(($tz == 99 ? 'Pacific/Auckland' : $tz)));
 222                      $expected->setDate($year, $date[0], $date[1]);
 223                      $expected->setTime($date[2], $date[3], $date[4]);
 224                      $result = usergetdate($expected->getTimestamp(), $tz);
 225                      unset($result[0]); // Extra introduced by getdate().
 226                      $ex = array(
 227                          'seconds' => $date[4],
 228                          'minutes' => $date[3],
 229                          'hours' => $date[2],
 230                          'mday' => $date[1],
 231                          'wday' => (int)$expected->format('w'),
 232                          'mon' => $date[0],
 233                          'year' => $year,
 234                          'yday' => (int)$expected->format('z'),
 235                          'weekday' => $expected->format('l'),
 236                          'month' => $expected->format('F'),
 237                      );
 238                      $this->assertSame($ex, $result,
 239                          'Incorrect result for data ' . $expected->format("D, d M Y H:i:s O") . ' ' . $tz);
 240                  }
 241              }
 242          }
 243      }
 244  
 245      public function test_userdate() {
 246          global $CFG;
 247  
 248          $this->resetAfterTest();
 249  
 250          $dates = array(
 251              array(2, 1, 0, 40, 40),
 252              array(4, 3, 0, 30, 22),
 253              array(9, 5, 0, 20, 19),
 254              array(11, 28, 0, 10, 45),
 255          );
 256          $years = array(1999, 2009, 2014, 2018);
 257  
 258          $users = array();
 259          $users[] = $this->getDataGenerator()->create_user(array('timezone' => 99));
 260          $users[] = $this->getDataGenerator()->create_user(array('timezone' => 'Europe/Prague'));
 261          $users[] = $this->getDataGenerator()->create_user(array('timezone' => 'Pacific/Auckland'));
 262          $users[] = $this->getDataGenerator()->create_user(array('timezone' => 'Australia/Perth'));
 263          $users[] = $this->getDataGenerator()->create_user(array('timezone' => 'America/New_York'));
 264  
 265          $format = get_string('strftimedaydatetime', 'langconfig');
 266  
 267          $this->setTimezone('Pacific/Auckland', 'Pacific/Auckland');
 268          foreach ($years as $year) {
 269              foreach ($dates as $date) {
 270                  $expected = new \DateTime('now', new \DateTimeZone('UTC'));
 271                  $expected->setDate($year, $date[0], $date[1]);
 272                  $expected->setTime($date[2], $date[3], $date[4]);
 273  
 274                  foreach ($users as $user) {
 275                      $this->setUser($user);
 276                      $expected->setTimezone(new \DateTimeZone(($user->timezone == 99 ? 'Pacific/Auckland' : $user->timezone)));
 277                      $result = userdate($expected->getTimestamp(), '', 99, false, false);
 278                      date_default_timezone_set($expected->getTimezone()->getName());
 279                      $ex = \core_date::strftime($format, $expected->getTimestamp());
 280                      date_default_timezone_set($CFG->timezone);
 281                      $this->assertSame($ex, $result);
 282                  }
 283              }
 284          }
 285      }
 286  
 287      public function test_usertime() {
 288          // This is a useless bad hack, it needs to be completely eliminated.
 289  
 290          $time = gmmktime(1, 1, 1, 3, 1, 2015);
 291          $this->assertSame($time - (60 * 60 * 1), usertime($time, '1'));
 292          $this->assertSame($time - (60 * 60 * -1), usertime($time, '-1'));
 293          $this->assertSame($time - (60 * 60 * 1), usertime($time, 'Europe/Prague'));
 294          $this->assertSame($time - (60 * 60 * 8), usertime($time, 'Australia/Perth'));
 295          $this->assertSame($time - (60 * 60 * 12), usertime($time, 'Pacific/Auckland'));
 296          $this->assertSame($time - (60 * 60 * -5), usertime($time, 'America/New_York'));
 297  
 298          $time = gmmktime(1, 1, 1, 5, 1, 2015);
 299          $this->assertSame($time - (60 * 60 * 1), usertime($time, '1'));
 300          $this->assertSame($time - (60 * 60 * -1), usertime($time, '-1'));
 301          $this->assertSame($time - (60 * 60 * 1), usertime($time, 'Europe/Prague'));
 302          $this->assertSame($time - (60 * 60 * 8), usertime($time, 'Australia/Perth'));
 303          $this->assertSame($time - (60 * 60 * 12), usertime($time, 'Pacific/Auckland'));
 304          $this->assertSame($time - (60 * 60 * -5), usertime($time, 'America/New_York'));
 305      }
 306  
 307      public function test_usertimezone() {
 308          global $USER;
 309          $this->resetAfterTest();
 310  
 311          $this->setTimezone('Pacific/Auckland', 'Pacific/Auckland');
 312  
 313          $USER->timezone = 'Europe/Prague';
 314          $this->assertSame('Europe/Prague', usertimezone());
 315  
 316          $USER->timezone = '1';
 317          $this->assertSame('UTC+1', usertimezone());
 318  
 319          $USER->timezone = '0';
 320          $this->assertSame('UTC', usertimezone());
 321  
 322          $USER->timezone = '99';
 323          $this->assertSame('Pacific/Auckland', usertimezone());
 324  
 325          $USER->timezone = '99';
 326          $this->assertSame('Europe/Berlin', usertimezone('Europe/Berlin'));
 327  
 328          $USER->timezone = '99';
 329          $this->assertSame('Pacific/Auckland', usertimezone('99'));
 330  
 331          $USER->timezone = 'Europe/Prague';
 332          $this->assertSame('Europe/Prague', usertimezone('99'));
 333  
 334          // When passed an unknown non-whole hour TZ, verify we round to closest
 335          // hour. (Possible for legacy reasons when old timezones go away).
 336          $USER->timezone = '-9.23';
 337          $this->assertSame('UTC-9', usertimezone('99'));
 338      }
 339  }