Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 3.9.x will end* 10 May 2021 (12 months).
  • Bug fixes for security issues in 3.9.x will end* 8 May 2023 (36 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.

Differences Between: [Versions 39 and 310] [Versions 39 and 400] [Versions 39 and 401] [Versions 39 and 402] [Versions 39 and 403]

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