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]

   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  /**
  18   * Tests core_date class.
  19   *
  20   * @package   core
  21   * @copyright 2015 Totara Learning Solutions Ltd {@link http://www.totaralms.com/}
  22   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   * @author    Petr Skoda <petr.skoda@totaralms.com>
  24   */
  25  
  26  defined('MOODLE_INTERNAL') || die();
  27  
  28  /**
  29   * Tests core_date class.
  30   *
  31   * @package   core
  32   * @copyright 2015 Totara Learning Solutions Ltd {@link http://www.totaralms.com/}
  33   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  34   * @author    Petr Skoda <petr.skoda@totaralms.com>
  35   * @covers \core_date
  36   * @coversDefaultClass \core_date
  37   */
  38  class date_test extends advanced_testcase {
  39      /**
  40       * @covers ::get_default_php_timezone
  41       */
  42      public function test_get_default_php_timezone() {
  43          $this->resetAfterTest();
  44  
  45          $origtz = core_date::get_default_php_timezone();
  46          $this->assertNotEmpty($origtz);
  47  
  48          $this->setTimezone('Pacific/Auckland', 'Europe/Prague');
  49          $this->assertSame('Europe/Prague', core_date::get_default_php_timezone());
  50  
  51          $this->setTimezone('Pacific/Auckland', 'UTC');
  52          $this->assertSame('UTC', core_date::get_default_php_timezone());
  53  
  54          $this->setTimezone('Pacific/Auckland', 'GMT');
  55          $this->assertSame('GMT', core_date::get_default_php_timezone());
  56      }
  57  
  58      /**
  59       * @covers ::normalise_timezone
  60       */
  61      public function test_normalise_timezone() {
  62          $this->resetAfterTest();
  63  
  64          $this->setTimezone('Pacific/Auckland');
  65          $this->assertSame('Pacific/Auckland', core_date::normalise_timezone('Pacific/Auckland'));
  66          $this->assertSame('Pacific/Auckland', core_date::normalise_timezone('99'));
  67          $this->assertSame('Pacific/Auckland', core_date::normalise_timezone(99));
  68          $this->assertSame('GMT', core_date::normalise_timezone('GMT'));
  69          $this->assertSame('UTC', core_date::normalise_timezone('UTC'));
  70          $this->assertSame('Pacific/Auckland', core_date::normalise_timezone('xxxxxxxx'));
  71          $this->assertSame('Europe/Berlin', core_date::normalise_timezone('Central European Time'));
  72          $this->assertSame('Etc/GMT', core_date::normalise_timezone('0'));
  73          $this->assertSame('Etc/GMT', core_date::normalise_timezone('0.0'));
  74          $this->assertSame('Etc/GMT-2', core_date::normalise_timezone(2));
  75          $this->assertSame('Etc/GMT-2', core_date::normalise_timezone('2.0'));
  76          $this->assertSame('Etc/GMT+2', core_date::normalise_timezone(-2));
  77          $this->assertSame('Etc/GMT+2', core_date::normalise_timezone('-2.0'));
  78          $this->assertSame('Etc/GMT+4', core_date::normalise_timezone(-4));
  79          $this->assertSame('Etc/GMT-2', core_date::normalise_timezone('UTC+2'));
  80          $this->assertSame('Etc/GMT+2', core_date::normalise_timezone('UTC-2'));
  81          $this->assertSame('Etc/GMT-2', core_date::normalise_timezone('GMT+2'));
  82          $this->assertSame('Etc/GMT+2', core_date::normalise_timezone('GMT-2'));
  83          $this->assertSame('Etc/GMT+12', core_date::normalise_timezone(-12));
  84          $this->assertSame('Pacific/Auckland', core_date::normalise_timezone(-13));
  85          $this->assertSame('Pacific/Auckland', core_date::normalise_timezone(-14));
  86          $this->assertSame('Etc/GMT-12', core_date::normalise_timezone(12));
  87          $this->assertSame('Etc/GMT-13', core_date::normalise_timezone(13));
  88          $this->assertSame('Etc/GMT-14', core_date::normalise_timezone(14));
  89  
  90          $this->assertSame('Asia/Kabul', core_date::normalise_timezone(4.5));
  91          $this->assertSame('Asia/Kolkata', core_date::normalise_timezone(5.5));
  92          $this->assertSame('Asia/Rangoon', core_date::normalise_timezone(6.5));
  93          $this->assertSame('Australia/Darwin', core_date::normalise_timezone('9.5'));
  94  
  95          $this->setTimezone('99', 'Pacific/Auckland');
  96          $this->assertSame('Pacific/Auckland', core_date::normalise_timezone('Pacific/Auckland'));
  97          $this->assertSame('Pacific/Auckland', core_date::normalise_timezone('99'));
  98          $this->assertSame('Pacific/Auckland', core_date::normalise_timezone(99));
  99          $this->assertSame('GMT', core_date::normalise_timezone('GMT'));
 100          $this->assertSame('UTC', core_date::normalise_timezone('UTC'));
 101          $this->assertSame('Pacific/Auckland', core_date::normalise_timezone('xxxxxxxx'));
 102          $this->assertSame('Europe/Berlin', core_date::normalise_timezone('Central European Time'));
 103          $this->assertSame('Etc/GMT', core_date::normalise_timezone('0'));
 104          $this->assertSame('Etc/GMT', core_date::normalise_timezone('0.0'));
 105          $this->assertSame('Etc/GMT-2', core_date::normalise_timezone(2));
 106          $this->assertSame('Etc/GMT-2', core_date::normalise_timezone('2.0'));
 107          $this->assertSame('Etc/GMT+2', core_date::normalise_timezone(-2));
 108          $this->assertSame('Etc/GMT+2', core_date::normalise_timezone('-2.0'));
 109          $this->assertSame('Etc/GMT-2', core_date::normalise_timezone('UTC+2'));
 110          $this->assertSame('Etc/GMT+2', core_date::normalise_timezone('UTC-2'));
 111          $this->assertSame('Etc/GMT-2', core_date::normalise_timezone('GMT+2'));
 112          $this->assertSame('Etc/GMT+2', core_date::normalise_timezone('GMT-2'));
 113          $this->assertSame('Etc/GMT+12', core_date::normalise_timezone(-12));
 114          $this->assertSame('Pacific/Auckland', core_date::normalise_timezone(-13));
 115          $this->assertSame('Pacific/Auckland', core_date::normalise_timezone(-14));
 116          $this->assertSame('Etc/GMT-12', core_date::normalise_timezone(12));
 117          $this->assertSame('Etc/GMT-13', core_date::normalise_timezone(13));
 118          $this->assertSame('Etc/GMT-14', core_date::normalise_timezone(14));
 119  
 120          $this->setTimezone('Pacific/Auckland', 'Pacific/Auckland');
 121          $tz = new DateTimeZone('Pacific/Auckland');
 122          $this->assertSame('Pacific/Auckland', core_date::normalise_timezone($tz));
 123      }
 124  
 125      /**
 126       * @covers ::normalise_timezone
 127       */
 128      public function test_windows_conversion() {
 129          $file = __DIR__ . '/fixtures/timezonewindows.xml';
 130  
 131          $contents = file_get_contents($file);
 132          preg_match_all('/<mapZone other="([^"]+)" territory="001" type="([^"]+)"\/>/', $contents, $matches, PREG_SET_ORDER);
 133  
 134          $this->assertCount(104, $matches); // NOTE: If the file contents change edit the core_date class and update this.
 135  
 136          foreach ($matches as $match) {
 137              $result = core_date::normalise_timezone($match[1]);
 138              if ($result == $match[2]) {
 139                  $this->assertSame($match[2], $result);
 140              } else {
 141                  $data = new DateTime('now', new DateTimeZone($match[2]));
 142                  $expectedoffset = $data->getOffset();
 143                  $data = new DateTime('now', new DateTimeZone($result));
 144                  $resultoffset = $data->getOffset();
 145                  $this->assertSame($expectedoffset, $resultoffset, "$match[1] is expected to be converted to $match[2] not $result");
 146              }
 147          }
 148      }
 149  
 150      /**
 151       * Sanity test for PHP stuff.
 152       */
 153      public function test_php_gmt_offsets() {
 154          $this->resetAfterTest();
 155  
 156          $this->setTimezone('Pacific/Auckland', 'Pacific/Auckland');
 157  
 158          for ($i = -12; $i < 0; $i++) {
 159              $date = new DateTime('now', new DateTimeZone("Etc/GMT{$i}"));
 160              $this->assertSame(- $i * 60 * 60, $date->getOffset());
 161              $date = new DateTime('now', new DateTimeZone(core_date::normalise_timezone("GMT{$i}")));
 162              $this->assertSame($i * 60 * 60, $date->getOffset());
 163              $date = new DateTime('now', new DateTimeZone(core_date::normalise_timezone("UTC{$i}")));
 164              $this->assertSame($i * 60 * 60, $date->getOffset());
 165          }
 166  
 167          $date = new DateTime('now', new DateTimeZone('Etc/GMT'));
 168          $this->assertSame(0, $date->getOffset());
 169  
 170          for ($i = 1; $i <= 12; $i++) {
 171              $date = new DateTime('now', new DateTimeZone("Etc/GMT+{$i}"));
 172              $this->assertSame(- $i * 60 * 60, $date->getOffset());
 173              $date = new DateTime('now', new DateTimeZone(core_date::normalise_timezone("GMT+{$i}")));
 174              $this->assertSame($i * 60 * 60, $date->getOffset());
 175              $date = new DateTime('now', new DateTimeZone(core_date::normalise_timezone("UTC+{$i}")));
 176              $this->assertSame($i * 60 * 60, $date->getOffset());
 177          }
 178      }
 179  
 180      /**
 181       * We are only checking lang strings existence here, not code.
 182       *
 183       * @coversNothing
 184       */
 185      public function test_timezone_all_lang_strings() {
 186          // We only run this test when PHPUNIT_LONGTEST is enabled, test_get_localised_timezone()
 187          // is already checking the names of a few, hopefully stable enough to be run always.
 188          if (!PHPUNIT_LONGTEST) {
 189              $this->markTestSkipped('PHPUNIT_LONGTEST is not defined');
 190          }
 191  
 192          $phpzones = DateTimeZone::listIdentifiers();
 193          $manager = get_string_manager();
 194          foreach ($phpzones as $tz) {
 195              $this->assertTrue($manager->string_exists(strtolower($tz), 'core_timezones'),
 196                      'String for timezone ' . strtolower($tz) . ' not found.');
 197          }
 198      }
 199  
 200      /**
 201       * @covers ::get_localised_timezone
 202       */
 203      public function test_get_localised_timezone() {
 204          $this->resetAfterTest();
 205  
 206          $this->setTimezone('Pacific/Auckland', 'Pacific/Auckland');
 207  
 208          $result = core_date::get_localised_timezone('Pacific/Auckland');
 209          $this->assertSame('Pacific/Auckland', $result);
 210  
 211          $result = core_date::get_localised_timezone('Europe/Madrid');
 212          $this->assertSame('Europe/Madrid', $result);
 213  
 214          $result = core_date::get_localised_timezone('America/New_York');
 215          $this->assertSame('America/New_York', $result);
 216  
 217          $result = core_date::get_localised_timezone('99');
 218          $this->assertSame('Server timezone (Pacific/Auckland)', $result);
 219  
 220          $result = core_date::get_localised_timezone(99);
 221          $this->assertSame('Server timezone (Pacific/Auckland)', $result);
 222  
 223          $result = core_date::get_localised_timezone('Etc/GMT-1');
 224          $this->assertSame('UTC+1', $result);
 225  
 226          $result = core_date::get_localised_timezone('Etc/GMT+2');
 227          $this->assertSame('UTC-2', $result);
 228  
 229          $result = core_date::get_localised_timezone('GMT');
 230          $this->assertSame('UTC', $result);
 231  
 232          $result = core_date::get_localised_timezone('Etc/GMT');
 233          $this->assertSame('UTC', $result);
 234      }
 235  
 236      /**
 237       * @covers ::get_list_of_timezones
 238       */
 239      public function test_get_list_of_timezones() {
 240          $this->resetAfterTest();
 241  
 242          $this->setTimezone('Pacific/Auckland', 'Pacific/Auckland');
 243  
 244          $phpzones = DateTimeZone::listIdentifiers();
 245  
 246          $zones = core_date::get_list_of_timezones();
 247          $this->assertSame(count($phpzones), count($zones));
 248          foreach ($zones as $zone => $zonename) {
 249              $this->assertSame($zone, $zonename); // The same in English!
 250              $this->assertContains($zone, $phpzones); // No extras expected.
 251          }
 252  
 253          $this->assertSame($zones, core_date::get_list_of_timezones(null, false));
 254  
 255          $nnzones = core_date::get_list_of_timezones(null, true);
 256          $last = $nnzones['99'];
 257          $this->assertSame('Server timezone (Pacific/Auckland)', $last);
 258          unset($nnzones['99']);
 259          $this->assertSame($zones, $nnzones);
 260  
 261          $nnzones = core_date::get_list_of_timezones('99', false);
 262          $last = $nnzones['99'];
 263          $this->assertSame('Server timezone (Pacific/Auckland)', $last);
 264          unset($nnzones['99']);
 265          $this->assertSame($zones, $nnzones);
 266  
 267          $xxzones = core_date::get_list_of_timezones('xx', false);
 268          $xx = $xxzones['xx'];
 269          $this->assertSame('Invalid timezone "xx"', $xx);
 270          unset($xxzones['xx']);
 271          $this->assertSame($zones, $xxzones);
 272  
 273          $xxzones = core_date::get_list_of_timezones('1', false);
 274          $xx = $xxzones['1'];
 275          $this->assertSame('Invalid timezone "UTC+1.0"', $xx);
 276          unset($xxzones['1']);
 277          $this->assertSame($zones, $xxzones);
 278  
 279          $xxzones = core_date::get_list_of_timezones('-1.5', false);
 280          $xx = $xxzones['-1.5'];
 281          $this->assertSame('Invalid timezone "UTC-1.5"', $xx);
 282          unset($xxzones['-1.5']);
 283          $this->assertSame($zones, $xxzones);
 284  
 285      }
 286  
 287      /**
 288       * @covers ::get_server_timezone
 289       */
 290      public function test_get_server_timezone() {
 291          global $CFG;
 292          $this->resetAfterTest();
 293  
 294          $this->setTimezone('Pacific/Auckland', 'Pacific/Auckland');
 295          $this->assertSame('Pacific/Auckland', core_date::get_server_timezone());
 296  
 297          $this->setTimezone('Pacific/Auckland', 'Europe/Prague');
 298          $this->assertSame('Pacific/Auckland', core_date::get_server_timezone());
 299  
 300          $this->setTimezone('99', 'Pacific/Auckland');
 301          $this->assertSame('Pacific/Auckland', core_date::get_server_timezone());
 302  
 303          $this->setTimezone(99, 'Pacific/Auckland');
 304          $this->assertSame('Pacific/Auckland', core_date::get_server_timezone());
 305  
 306          $this->setTimezone('Pacific/Auckland', 'Pacific/Auckland');
 307          unset($CFG->timezone);
 308          $this->assertSame('Pacific/Auckland', core_date::get_server_timezone());
 309  
 310          // Admin should fix the settings.
 311          $this->setTimezone('xxx/zzzz', 'Europe/Prague');
 312          $this->assertSame('Europe/Prague', core_date::get_server_timezone());
 313      }
 314  
 315      /**
 316       * @covers ::get_server_timezone_object
 317       */
 318      public function test_get_server_timezone_object() {
 319          $this->resetAfterTest();
 320  
 321          $zones = core_date::get_list_of_timezones();
 322          foreach ($zones as $zone) {
 323              $this->setTimezone($zone, 'Pacific/Auckland');
 324              $tz = core_date::get_server_timezone_object();
 325              $this->assertInstanceOf('DateTimeZone', $tz);
 326              $this->assertSame($zone, $tz->getName());
 327          }
 328      }
 329  
 330      /**
 331       * @covers ::set_default_server_timezone
 332       */
 333      public function test_set_default_server_timezone() {
 334          global $CFG;
 335          $this->resetAfterTest();
 336  
 337          $this->setTimezone('Europe/Prague', 'Pacific/Auckland');
 338          unset($CFG->timezone);
 339          date_default_timezone_set('UTC');
 340          core_date::set_default_server_timezone();
 341          $this->assertSame('Pacific/Auckland', date_default_timezone_get());
 342  
 343          $this->setTimezone('', 'Pacific/Auckland');
 344          date_default_timezone_set('UTC');
 345          core_date::set_default_server_timezone();
 346          $this->assertSame('Pacific/Auckland', date_default_timezone_get());
 347  
 348          $this->setTimezone('99', 'Pacific/Auckland');
 349          date_default_timezone_set('UTC');
 350          core_date::set_default_server_timezone();
 351          $this->assertSame('Pacific/Auckland', date_default_timezone_get());
 352  
 353          $this->setTimezone(99, 'Pacific/Auckland');
 354          date_default_timezone_set('UTC');
 355          core_date::set_default_server_timezone();
 356          $this->assertSame('Pacific/Auckland', date_default_timezone_get());
 357  
 358          $this->setTimezone('Europe/Prague', 'Pacific/Auckland');
 359          $CFG->timezone = 'UTC';
 360          core_date::set_default_server_timezone();
 361          $this->assertSame('UTC', date_default_timezone_get());
 362  
 363          $this->setTimezone('Europe/Prague', 'Pacific/Auckland');
 364          $CFG->timezone = 'Australia/Perth';
 365          core_date::set_default_server_timezone();
 366          $this->assertSame('Australia/Perth', date_default_timezone_get());
 367  
 368          $this->setTimezone('0', 'Pacific/Auckland');
 369          date_default_timezone_set('UTC');
 370          core_date::set_default_server_timezone();
 371          $this->assertSame('Etc/GMT', date_default_timezone_get());
 372  
 373          $this->setTimezone('1', 'Pacific/Auckland');
 374          date_default_timezone_set('UTC');
 375          core_date::set_default_server_timezone();
 376          $this->assertSame('Etc/GMT-1', date_default_timezone_get());
 377  
 378          $this->setTimezone(1, 'Pacific/Auckland');
 379          date_default_timezone_set('UTC');
 380          core_date::set_default_server_timezone();
 381          $this->assertSame('Etc/GMT-1', date_default_timezone_get());
 382  
 383          $this->setTimezone('1.0', 'Pacific/Auckland');
 384          date_default_timezone_set('UTC');
 385          core_date::set_default_server_timezone();
 386          $this->assertSame('Etc/GMT-1', date_default_timezone_get());
 387      }
 388  
 389      public function legacyUserTimezoneProvider() {
 390          return [
 391              ['', 'Australia/Perth'],            // Fallback on default timezone.
 392              ['-13.0', 'Australia/Perth'],       // Fallback on default timezone.
 393              ['-12.5', 'Etc/GMT+12'],
 394              ['-12.0', 'Etc/GMT+12'],
 395              ['-11.5', 'Etc/GMT+11'],
 396              ['-11.0', 'Etc/GMT+11'],
 397              ['-10.5', 'Etc/GMT+10'],
 398              ['-10.0', 'Etc/GMT+10'],
 399              ['-9.5', 'Etc/GMT+9'],
 400              ['-9.0', 'Etc/GMT+9'],
 401              ['-8.5', 'Etc/GMT+8'],
 402              ['-8.0', 'Etc/GMT+8'],
 403              ['-7.5', 'Etc/GMT+7'],
 404              ['-7.0', 'Etc/GMT+7'],
 405              ['-6.5', 'Etc/GMT+6'],
 406              ['-6.0', 'Etc/GMT+6'],
 407              ['-5.5', 'Etc/GMT+5'],
 408              ['-5.0', 'Etc/GMT+5'],
 409              ['-4.5', 'Etc/GMT+4'],
 410              ['-4.0', 'Etc/GMT+4'],
 411              ['-3.5', 'Etc/GMT+3'],
 412              ['-3.0', 'Etc/GMT+3'],
 413              ['-2.5', 'Etc/GMT+2'],
 414              ['-2.0', 'Etc/GMT+2'],
 415              ['-1.5', 'Etc/GMT+1'],
 416              ['-1.0', 'Etc/GMT+1'],
 417              ['-0.5', 'Etc/GMT'],
 418              ['0', 'Etc/GMT'],
 419              ['0.0', 'Etc/GMT'],
 420              ['0.5', 'Etc/GMT'],
 421              ['1.0', 'Etc/GMT-1'],
 422              ['1.5', 'Etc/GMT-1'],
 423              ['2.0', 'Etc/GMT-2'],
 424              ['2.5', 'Etc/GMT-2'],
 425              ['3.0', 'Etc/GMT-3'],
 426              ['3.5', 'Etc/GMT-3'],
 427              ['4.0', 'Etc/GMT-4'],
 428              ['4.5', 'Asia/Kabul'],
 429              ['5.0', 'Etc/GMT-5'],
 430              ['5.5', 'Asia/Kolkata'],
 431              ['6.0', 'Etc/GMT-6'],
 432              ['6.5', 'Asia/Rangoon'],
 433              ['7.0', 'Etc/GMT-7'],
 434              ['7.5', 'Etc/GMT-7'],
 435              ['8.0', 'Etc/GMT-8'],
 436              ['8.5', 'Etc/GMT-8'],
 437              ['9.0', 'Etc/GMT-9'],
 438              ['9.5', 'Australia/Darwin'],
 439              ['10.0', 'Etc/GMT-10'],
 440              ['10.5', 'Etc/GMT-10'],
 441              ['11.0', 'Etc/GMT-11'],
 442              ['11.5', 'Etc/GMT-11'],
 443              ['12.0', 'Etc/GMT-12'],
 444              ['12.5', 'Etc/GMT-12'],
 445              ['13.0', 'Etc/GMT-13'],
 446          ];
 447      }
 448  
 449      /**
 450       * @dataProvider legacyUserTimezoneProvider
 451       * @covers ::get_user_timezone
 452       * @param string $tz The legacy timezone.
 453       * @param string $expected The expected converted timezone.
 454       */
 455      public function test_get_legacy_user_timezone($tz, $expected) {
 456          $this->setTimezone('Australia/Perth', 'Australia/Perth');
 457          $this->assertEquals($expected, core_date::get_user_timezone($tz));
 458      }
 459  
 460      /**
 461       * @covers ::get_user_timezone
 462       */
 463      public function test_get_user_timezone() {
 464          global $CFG, $USER;
 465          $this->resetAfterTest();
 466  
 467          // Null parameter.
 468  
 469          $this->setTimezone('Europe/Prague', 'Pacific/Auckland');
 470          $USER->timezone = 'Pacific/Auckland';
 471          $CFG->forcetimezone = '99';
 472          $this->assertSame('Pacific/Auckland', core_date::get_user_timezone(null));
 473          $this->assertSame('Pacific/Auckland', core_date::get_user_timezone());
 474  
 475          $this->setTimezone('Europe/Prague', 'Pacific/Auckland');
 476          $USER->timezone = 'Pacific/Auckland';
 477          $CFG->forcetimezone = 'Europe/Berlin';
 478          $this->assertSame('Europe/Berlin', core_date::get_user_timezone(null));
 479          $this->assertSame('Europe/Berlin', core_date::get_user_timezone());
 480  
 481          $this->setTimezone('Europe/Prague', 'Pacific/Auckland');
 482          $USER->timezone = 'Pacific/Auckland';
 483          $CFG->forcetimezone = 'xxx/yyy';
 484          $this->assertSame('Europe/Prague', core_date::get_user_timezone(null));
 485          $this->assertSame('Europe/Prague', core_date::get_user_timezone());
 486  
 487          $this->setTimezone('Europe/Prague', 'Pacific/Auckland');
 488          $USER->timezone = 'abc/def';
 489          $CFG->forcetimezone = '99';
 490          $this->assertSame('Europe/Prague', core_date::get_user_timezone(null));
 491          $this->assertSame('Europe/Prague', core_date::get_user_timezone());
 492  
 493          $this->setTimezone('xxx/yyy', 'Europe/London');
 494          $USER->timezone = 'abc/def';
 495          $CFG->forcetimezone = 'Europe/Berlin';
 496          $this->assertSame('Europe/Berlin', core_date::get_user_timezone(null));
 497          $this->assertSame('Europe/Berlin', core_date::get_user_timezone());
 498  
 499          $this->setTimezone('xxx/yyy', 'Europe/London');
 500          $USER->timezone = 'abc/def';
 501          $CFG->forcetimezone = 99;
 502          $this->assertSame('Europe/London', core_date::get_user_timezone(null));
 503          $this->assertSame('Europe/London', core_date::get_user_timezone());
 504  
 505          // User object parameter.
 506          $admin = get_admin();
 507  
 508          $this->setTimezone('Europe/London');
 509          $USER->timezone = 'Pacific/Auckland';
 510          $CFG->forcetimezone = '99';
 511          $admin->timezone = 'Australia/Perth';
 512          $this->assertSame('Australia/Perth', core_date::get_user_timezone($admin));
 513  
 514          $this->setTimezone('Europe/Prague');
 515          $USER->timezone = 'Pacific/Auckland';
 516          $CFG->forcetimezone = '99';
 517          $admin->timezone = '99';
 518          $this->assertSame('Europe/Prague', core_date::get_user_timezone($admin));
 519  
 520          $this->setTimezone('99', 'Europe/London');
 521          $USER->timezone = 'Pacific/Auckland';
 522          $CFG->forcetimezone = '99';
 523          $admin->timezone = '99';
 524          $this->assertSame('Europe/London', core_date::get_user_timezone($admin));
 525  
 526          $this->setTimezone('Europe/Prague');
 527          $USER->timezone = 'Pacific/Auckland';
 528          $CFG->forcetimezone = '99';
 529          $admin->timezone = 'xx/zz';
 530          $this->assertSame('Europe/Prague', core_date::get_user_timezone($admin));
 531  
 532          $this->setTimezone('Europe/Prague');
 533          $USER->timezone = 'Pacific/Auckland';
 534          $CFG->forcetimezone = '99';
 535          unset($admin->timezone);
 536          $this->assertSame('Europe/Prague', core_date::get_user_timezone($admin));
 537  
 538          $this->setTimezone('Europe/Prague');
 539          $USER->timezone = 'Pacific/Auckland';
 540          $CFG->forcetimezone = 'Europe/Berlin';
 541          $admin->timezone = 'Australia/Perth';
 542          $this->assertSame('Europe/Berlin', core_date::get_user_timezone($admin));
 543  
 544          // Other scalar parameter.
 545  
 546          $this->setTimezone('Europe/Prague');
 547          $CFG->forcetimezone = '99';
 548  
 549          $USER->timezone = 'Pacific/Auckland';
 550          $this->assertSame('Pacific/Auckland', core_date::get_user_timezone('99'));
 551          $this->assertSame('Etc/GMT-1', core_date::get_user_timezone('1'));
 552          $this->assertSame('Etc/GMT+1', core_date::get_user_timezone(-1));
 553          $this->assertSame('Europe/London', core_date::get_user_timezone('Europe/London'));
 554          $USER->timezone = '99';
 555          $this->assertSame('Europe/Prague', core_date::get_user_timezone('99'));
 556          $this->assertSame('Europe/London', core_date::get_user_timezone('Europe/London'));
 557          $this->assertSame('Europe/Prague', core_date::get_user_timezone('xxx/zzz'));
 558          $USER->timezone = 'xxz/zzz';
 559          $this->assertSame('Europe/Prague', core_date::get_user_timezone('99'));
 560  
 561          $this->setTimezone('99', 'Europe/Prague');
 562          $CFG->forcetimezone = '99';
 563  
 564          $USER->timezone = 'Pacific/Auckland';
 565          $this->assertSame('Pacific/Auckland', core_date::get_user_timezone('99'));
 566          $this->assertSame('Europe/London', core_date::get_user_timezone('Europe/London'));
 567          $USER->timezone = '99';
 568          $this->assertSame('Europe/Prague', core_date::get_user_timezone('99'));
 569          $this->assertSame('Europe/London', core_date::get_user_timezone('Europe/London'));
 570          $this->assertSame('Europe/Prague', core_date::get_user_timezone('xxx/zzz'));
 571          $USER->timezone = 99;
 572          $this->assertSame('Europe/London', core_date::get_user_timezone('Europe/London'));
 573          $this->assertSame('Europe/Prague', core_date::get_user_timezone('xxx/zzz'));
 574          $USER->timezone = 'xxz/zzz';
 575          $this->assertSame('Europe/Prague', core_date::get_user_timezone('99'));
 576  
 577          $this->setTimezone('xxx', 'Europe/Prague');
 578          $CFG->forcetimezone = '99';
 579          $USER->timezone = 'xxx';
 580          $this->assertSame('Europe/Prague', core_date::get_user_timezone('99'));
 581          $this->assertSame('Europe/Prague', core_date::get_user_timezone(99));
 582          $this->assertSame('Etc/GMT-1', core_date::get_user_timezone(1));
 583  
 584          $this->setTimezone('Europe/Prague');
 585          $CFG->forcetimezone = 'Pacific/Auckland';
 586          $USER->timezone = 'Europe/London';
 587          $this->assertSame('Pacific/Auckland', core_date::get_user_timezone(99));
 588          $this->assertSame('Europe/Berlin', core_date::get_user_timezone('Europe/Berlin'));
 589  
 590          // TZ object param.
 591  
 592          $this->setTimezone('UTC');
 593          $USER->timezone = 'Europe/London';
 594          $CFG->forcetimezone = 99;
 595          $tz = new DateTimeZone('Pacific/Auckland');
 596          $this->assertSame('Pacific/Auckland', core_date::get_user_timezone($tz));
 597      }
 598  
 599      /**
 600       * @covers ::get_user_timezone_object
 601       */
 602      public function test_get_user_timezone_object() {
 603          global $CFG, $USER;
 604          $this->resetAfterTest();
 605  
 606          $this->setTimezone('Pacific/Auckland');
 607          $CFG->forcetimezone = '99';
 608  
 609          $zones = core_date::get_list_of_timezones();
 610          foreach ($zones as $zone) {
 611              $USER->timezone = $zone;
 612              $tz = core_date::get_user_timezone_object();
 613              $this->assertInstanceOf('DateTimeZone', $tz);
 614              $this->assertSame($zone, $tz->getName());
 615          }
 616      }
 617  }