| 1 | efrain | 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 |  */
 | 
        
           | 1441 | ariadna | 38 | final class date_test extends advanced_testcase {
 | 
        
           | 1 | efrain | 39 |     /**
 | 
        
           |  |  | 40 |      * @covers ::get_default_php_timezone
 | 
        
           |  |  | 41 |      */
 | 
        
           | 11 | efrain | 42 |     public function test_get_default_php_timezone(): void {
 | 
        
           | 1 | efrain | 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 |      */
 | 
        
           | 11 | efrain | 61 |     public function test_normalise_timezone(): void {
 | 
        
           | 1 | efrain | 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 |      */
 | 
        
           | 11 | efrain | 128 |     public function test_windows_conversion(): void {
 | 
        
           | 1441 | ariadna | 129 |         $file = self::get_fixture_path('core', 'timezonewindows.xml');
 | 
        
           | 1 | efrain | 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 |      */
 | 
        
           | 11 | efrain | 153 |     public function test_php_gmt_offsets(): void {
 | 
        
           | 1 | efrain | 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 |      */
 | 
        
           | 11 | efrain | 185 |     public function test_timezone_all_lang_strings(): void {
 | 
        
           | 1 | efrain | 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 |      */
 | 
        
           | 11 | efrain | 203 |     public function test_get_localised_timezone(): void {
 | 
        
           | 1 | efrain | 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 |      */
 | 
        
           | 11 | efrain | 239 |     public function test_get_list_of_timezones(): void {
 | 
        
           | 1 | efrain | 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 |      */
 | 
        
           | 11 | efrain | 290 |     public function test_get_server_timezone(): void {
 | 
        
           | 1 | efrain | 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.
 | 
        
           | 1441 | ariadna | 311 |         set_error_handler(function ($errno, $errstr): void {
 | 
        
           |  |  | 312 |             $this->assertStringContainsString('Unknown or bad timezone', $errstr);
 | 
        
           |  |  | 313 |             restore_error_handler();
 | 
        
           |  |  | 314 |         }, E_ALL);
 | 
        
           | 1 | efrain | 315 |         $this->setTimezone('xxx/zzzz', 'Europe/Prague');
 | 
        
           | 1441 | ariadna | 316 |         set_error_handler(function ($errno, $errstr): void {
 | 
        
           |  |  | 317 |             $this->assertStringContainsString('Unknown or bad timezone', $errstr);
 | 
        
           |  |  | 318 |             restore_error_handler();
 | 
        
           |  |  | 319 |         }, E_ALL);
 | 
        
           | 1 | efrain | 320 |         $this->assertSame('Europe/Prague', core_date::get_server_timezone());
 | 
        
           |  |  | 321 |     }
 | 
        
           |  |  | 322 |   | 
        
           |  |  | 323 |     /**
 | 
        
           |  |  | 324 |      * @covers ::get_server_timezone_object
 | 
        
           |  |  | 325 |      */
 | 
        
           | 11 | efrain | 326 |     public function test_get_server_timezone_object(): void {
 | 
        
           | 1 | efrain | 327 |         $this->resetAfterTest();
 | 
        
           |  |  | 328 |   | 
        
           |  |  | 329 |         $zones = core_date::get_list_of_timezones();
 | 
        
           |  |  | 330 |         foreach ($zones as $zone) {
 | 
        
           |  |  | 331 |             $this->setTimezone($zone, 'Pacific/Auckland');
 | 
        
           |  |  | 332 |             $tz = core_date::get_server_timezone_object();
 | 
        
           |  |  | 333 |             $this->assertInstanceOf('DateTimeZone', $tz);
 | 
        
           |  |  | 334 |             $this->assertSame($zone, $tz->getName());
 | 
        
           |  |  | 335 |         }
 | 
        
           |  |  | 336 |     }
 | 
        
           |  |  | 337 |   | 
        
           |  |  | 338 |     /**
 | 
        
           |  |  | 339 |      * @covers ::set_default_server_timezone
 | 
        
           |  |  | 340 |      */
 | 
        
           | 11 | efrain | 341 |     public function test_set_default_server_timezone(): void {
 | 
        
           | 1 | efrain | 342 |         global $CFG;
 | 
        
           |  |  | 343 |         $this->resetAfterTest();
 | 
        
           |  |  | 344 |   | 
        
           |  |  | 345 |         $this->setTimezone('Europe/Prague', 'Pacific/Auckland');
 | 
        
           |  |  | 346 |         unset($CFG->timezone);
 | 
        
           |  |  | 347 |         date_default_timezone_set('UTC');
 | 
        
           |  |  | 348 |         core_date::set_default_server_timezone();
 | 
        
           |  |  | 349 |         $this->assertSame('Pacific/Auckland', date_default_timezone_get());
 | 
        
           |  |  | 350 |   | 
        
           |  |  | 351 |         $this->setTimezone('', 'Pacific/Auckland');
 | 
        
           |  |  | 352 |         date_default_timezone_set('UTC');
 | 
        
           |  |  | 353 |         core_date::set_default_server_timezone();
 | 
        
           |  |  | 354 |         $this->assertSame('Pacific/Auckland', date_default_timezone_get());
 | 
        
           |  |  | 355 |   | 
        
           |  |  | 356 |         $this->setTimezone('99', 'Pacific/Auckland');
 | 
        
           |  |  | 357 |         date_default_timezone_set('UTC');
 | 
        
           |  |  | 358 |         core_date::set_default_server_timezone();
 | 
        
           |  |  | 359 |         $this->assertSame('Pacific/Auckland', date_default_timezone_get());
 | 
        
           |  |  | 360 |   | 
        
           |  |  | 361 |         $this->setTimezone(99, 'Pacific/Auckland');
 | 
        
           |  |  | 362 |         date_default_timezone_set('UTC');
 | 
        
           |  |  | 363 |         core_date::set_default_server_timezone();
 | 
        
           |  |  | 364 |         $this->assertSame('Pacific/Auckland', date_default_timezone_get());
 | 
        
           |  |  | 365 |   | 
        
           |  |  | 366 |         $this->setTimezone('Europe/Prague', 'Pacific/Auckland');
 | 
        
           |  |  | 367 |         $CFG->timezone = 'UTC';
 | 
        
           |  |  | 368 |         core_date::set_default_server_timezone();
 | 
        
           |  |  | 369 |         $this->assertSame('UTC', date_default_timezone_get());
 | 
        
           |  |  | 370 |   | 
        
           |  |  | 371 |         $this->setTimezone('Europe/Prague', 'Pacific/Auckland');
 | 
        
           |  |  | 372 |         $CFG->timezone = 'Australia/Perth';
 | 
        
           |  |  | 373 |         core_date::set_default_server_timezone();
 | 
        
           |  |  | 374 |         $this->assertSame('Australia/Perth', date_default_timezone_get());
 | 
        
           |  |  | 375 |   | 
        
           |  |  | 376 |         $this->setTimezone('0', 'Pacific/Auckland');
 | 
        
           |  |  | 377 |         date_default_timezone_set('UTC');
 | 
        
           |  |  | 378 |         core_date::set_default_server_timezone();
 | 
        
           |  |  | 379 |         $this->assertSame('Etc/GMT', date_default_timezone_get());
 | 
        
           |  |  | 380 |   | 
        
           |  |  | 381 |         $this->setTimezone('1', 'Pacific/Auckland');
 | 
        
           |  |  | 382 |         date_default_timezone_set('UTC');
 | 
        
           |  |  | 383 |         core_date::set_default_server_timezone();
 | 
        
           |  |  | 384 |         $this->assertSame('Etc/GMT-1', date_default_timezone_get());
 | 
        
           |  |  | 385 |   | 
        
           |  |  | 386 |         $this->setTimezone(1, 'Pacific/Auckland');
 | 
        
           |  |  | 387 |         date_default_timezone_set('UTC');
 | 
        
           |  |  | 388 |         core_date::set_default_server_timezone();
 | 
        
           |  |  | 389 |         $this->assertSame('Etc/GMT-1', date_default_timezone_get());
 | 
        
           |  |  | 390 |   | 
        
           |  |  | 391 |         $this->setTimezone('1.0', 'Pacific/Auckland');
 | 
        
           |  |  | 392 |         date_default_timezone_set('UTC');
 | 
        
           |  |  | 393 |         core_date::set_default_server_timezone();
 | 
        
           |  |  | 394 |         $this->assertSame('Etc/GMT-1', date_default_timezone_get());
 | 
        
           |  |  | 395 |     }
 | 
        
           |  |  | 396 |   | 
        
           | 1441 | ariadna | 397 |     public static function legacyUserTimezoneProvider(): array {
 | 
        
           | 1 | efrain | 398 |         return [
 | 
        
           |  |  | 399 |             ['', 'Australia/Perth'],            // Fallback on default timezone.
 | 
        
           |  |  | 400 |             ['-13.0', 'Australia/Perth'],       // Fallback on default timezone.
 | 
        
           |  |  | 401 |             ['-12.5', 'Etc/GMT+12'],
 | 
        
           |  |  | 402 |             ['-12.0', 'Etc/GMT+12'],
 | 
        
           |  |  | 403 |             ['-11.5', 'Etc/GMT+11'],
 | 
        
           |  |  | 404 |             ['-11.0', 'Etc/GMT+11'],
 | 
        
           |  |  | 405 |             ['-10.5', 'Etc/GMT+10'],
 | 
        
           |  |  | 406 |             ['-10.0', 'Etc/GMT+10'],
 | 
        
           |  |  | 407 |             ['-9.5', 'Etc/GMT+9'],
 | 
        
           |  |  | 408 |             ['-9.0', 'Etc/GMT+9'],
 | 
        
           |  |  | 409 |             ['-8.5', 'Etc/GMT+8'],
 | 
        
           |  |  | 410 |             ['-8.0', 'Etc/GMT+8'],
 | 
        
           |  |  | 411 |             ['-7.5', 'Etc/GMT+7'],
 | 
        
           |  |  | 412 |             ['-7.0', 'Etc/GMT+7'],
 | 
        
           |  |  | 413 |             ['-6.5', 'Etc/GMT+6'],
 | 
        
           |  |  | 414 |             ['-6.0', 'Etc/GMT+6'],
 | 
        
           |  |  | 415 |             ['-5.5', 'Etc/GMT+5'],
 | 
        
           |  |  | 416 |             ['-5.0', 'Etc/GMT+5'],
 | 
        
           |  |  | 417 |             ['-4.5', 'Etc/GMT+4'],
 | 
        
           |  |  | 418 |             ['-4.0', 'Etc/GMT+4'],
 | 
        
           |  |  | 419 |             ['-3.5', 'Etc/GMT+3'],
 | 
        
           |  |  | 420 |             ['-3.0', 'Etc/GMT+3'],
 | 
        
           |  |  | 421 |             ['-2.5', 'Etc/GMT+2'],
 | 
        
           |  |  | 422 |             ['-2.0', 'Etc/GMT+2'],
 | 
        
           |  |  | 423 |             ['-1.5', 'Etc/GMT+1'],
 | 
        
           |  |  | 424 |             ['-1.0', 'Etc/GMT+1'],
 | 
        
           |  |  | 425 |             ['-0.5', 'Etc/GMT'],
 | 
        
           |  |  | 426 |             ['0', 'Etc/GMT'],
 | 
        
           |  |  | 427 |             ['0.0', 'Etc/GMT'],
 | 
        
           |  |  | 428 |             ['0.5', 'Etc/GMT'],
 | 
        
           |  |  | 429 |             ['1.0', 'Etc/GMT-1'],
 | 
        
           |  |  | 430 |             ['1.5', 'Etc/GMT-1'],
 | 
        
           |  |  | 431 |             ['2.0', 'Etc/GMT-2'],
 | 
        
           |  |  | 432 |             ['2.5', 'Etc/GMT-2'],
 | 
        
           |  |  | 433 |             ['3.0', 'Etc/GMT-3'],
 | 
        
           |  |  | 434 |             ['3.5', 'Etc/GMT-3'],
 | 
        
           |  |  | 435 |             ['4.0', 'Etc/GMT-4'],
 | 
        
           |  |  | 436 |             ['4.5', 'Asia/Kabul'],
 | 
        
           |  |  | 437 |             ['5.0', 'Etc/GMT-5'],
 | 
        
           |  |  | 438 |             ['5.5', 'Asia/Kolkata'],
 | 
        
           |  |  | 439 |             ['6.0', 'Etc/GMT-6'],
 | 
        
           |  |  | 440 |             ['6.5', 'Asia/Rangoon'],
 | 
        
           |  |  | 441 |             ['7.0', 'Etc/GMT-7'],
 | 
        
           |  |  | 442 |             ['7.5', 'Etc/GMT-7'],
 | 
        
           |  |  | 443 |             ['8.0', 'Etc/GMT-8'],
 | 
        
           |  |  | 444 |             ['8.5', 'Etc/GMT-8'],
 | 
        
           |  |  | 445 |             ['9.0', 'Etc/GMT-9'],
 | 
        
           |  |  | 446 |             ['9.5', 'Australia/Darwin'],
 | 
        
           |  |  | 447 |             ['10.0', 'Etc/GMT-10'],
 | 
        
           |  |  | 448 |             ['10.5', 'Etc/GMT-10'],
 | 
        
           |  |  | 449 |             ['11.0', 'Etc/GMT-11'],
 | 
        
           |  |  | 450 |             ['11.5', 'Etc/GMT-11'],
 | 
        
           |  |  | 451 |             ['12.0', 'Etc/GMT-12'],
 | 
        
           |  |  | 452 |             ['12.5', 'Etc/GMT-12'],
 | 
        
           |  |  | 453 |             ['13.0', 'Etc/GMT-13'],
 | 
        
           |  |  | 454 |         ];
 | 
        
           |  |  | 455 |     }
 | 
        
           |  |  | 456 |   | 
        
           |  |  | 457 |     /**
 | 
        
           |  |  | 458 |      * @dataProvider legacyUserTimezoneProvider
 | 
        
           |  |  | 459 |      * @covers ::get_user_timezone
 | 
        
           |  |  | 460 |      * @param string $tz The legacy timezone.
 | 
        
           |  |  | 461 |      * @param string $expected The expected converted timezone.
 | 
        
           |  |  | 462 |      */
 | 
        
           | 11 | efrain | 463 |     public function test_get_legacy_user_timezone($tz, $expected): void {
 | 
        
           | 1 | efrain | 464 |         $this->setTimezone('Australia/Perth', 'Australia/Perth');
 | 
        
           |  |  | 465 |         $this->assertEquals($expected, core_date::get_user_timezone($tz));
 | 
        
           |  |  | 466 |     }
 | 
        
           |  |  | 467 |   | 
        
           |  |  | 468 |     /**
 | 
        
           |  |  | 469 |      * @covers ::get_user_timezone
 | 
        
           |  |  | 470 |      */
 | 
        
           | 11 | efrain | 471 |     public function test_get_user_timezone(): void {
 | 
        
           | 1 | efrain | 472 |         global $CFG, $USER;
 | 
        
           |  |  | 473 |         $this->resetAfterTest();
 | 
        
           |  |  | 474 |   | 
        
           |  |  | 475 |         // Null parameter.
 | 
        
           |  |  | 476 |   | 
        
           |  |  | 477 |         $this->setTimezone('Europe/Prague', 'Pacific/Auckland');
 | 
        
           |  |  | 478 |         $USER->timezone = 'Pacific/Auckland';
 | 
        
           |  |  | 479 |         $CFG->forcetimezone = '99';
 | 
        
           |  |  | 480 |         $this->assertSame('Pacific/Auckland', core_date::get_user_timezone(null));
 | 
        
           |  |  | 481 |         $this->assertSame('Pacific/Auckland', core_date::get_user_timezone());
 | 
        
           |  |  | 482 |   | 
        
           |  |  | 483 |         $this->setTimezone('Europe/Prague', 'Pacific/Auckland');
 | 
        
           |  |  | 484 |         $USER->timezone = 'Pacific/Auckland';
 | 
        
           |  |  | 485 |         $CFG->forcetimezone = 'Europe/Berlin';
 | 
        
           |  |  | 486 |         $this->assertSame('Europe/Berlin', core_date::get_user_timezone(null));
 | 
        
           |  |  | 487 |         $this->assertSame('Europe/Berlin', core_date::get_user_timezone());
 | 
        
           |  |  | 488 |   | 
        
           |  |  | 489 |         $this->setTimezone('Europe/Prague', 'Pacific/Auckland');
 | 
        
           |  |  | 490 |         $USER->timezone = 'Pacific/Auckland';
 | 
        
           |  |  | 491 |         $CFG->forcetimezone = 'xxx/yyy';
 | 
        
           |  |  | 492 |         $this->assertSame('Europe/Prague', core_date::get_user_timezone(null));
 | 
        
           |  |  | 493 |         $this->assertSame('Europe/Prague', core_date::get_user_timezone());
 | 
        
           |  |  | 494 |   | 
        
           |  |  | 495 |         $this->setTimezone('Europe/Prague', 'Pacific/Auckland');
 | 
        
           |  |  | 496 |         $USER->timezone = 'abc/def';
 | 
        
           |  |  | 497 |         $CFG->forcetimezone = '99';
 | 
        
           |  |  | 498 |         $this->assertSame('Europe/Prague', core_date::get_user_timezone(null));
 | 
        
           |  |  | 499 |         $this->assertSame('Europe/Prague', core_date::get_user_timezone());
 | 
        
           |  |  | 500 |   | 
        
           | 1441 | ariadna | 501 |         $invokable = self::get_invokable();
 | 
        
           |  |  | 502 |         set_error_handler($invokable, E_ALL);
 | 
        
           | 1 | efrain | 503 |         $this->setTimezone('xxx/yyy', 'Europe/London');
 | 
        
           | 1441 | ariadna | 504 |         $this->assertCount(1, $invokable->get_invocations());
 | 
        
           | 1 | efrain | 505 |         $USER->timezone = 'abc/def';
 | 
        
           |  |  | 506 |         $CFG->forcetimezone = 'Europe/Berlin';
 | 
        
           |  |  | 507 |         $this->assertSame('Europe/Berlin', core_date::get_user_timezone(null));
 | 
        
           |  |  | 508 |         $this->assertSame('Europe/Berlin', core_date::get_user_timezone());
 | 
        
           | 1441 | ariadna | 509 |         $this->assertCount(1, $invokable->get_invocations());
 | 
        
           |  |  | 510 |         restore_error_handler();
 | 
        
           | 1 | efrain | 511 |   | 
        
           | 1441 | ariadna | 512 |         $invokable = self::get_invokable();
 | 
        
           |  |  | 513 |         set_error_handler($invokable, E_ALL);
 | 
        
           | 1 | efrain | 514 |         $this->setTimezone('xxx/yyy', 'Europe/London');
 | 
        
           | 1441 | ariadna | 515 |         $this->assertCount(1, $invokable->get_invocations());
 | 
        
           |  |  | 516 |         restore_error_handler();
 | 
        
           |  |  | 517 |   | 
        
           | 1 | efrain | 518 |         $USER->timezone = 'abc/def';
 | 
        
           |  |  | 519 |         $CFG->forcetimezone = 99;
 | 
        
           | 1441 | ariadna | 520 |         $invokable = self::get_invokable();
 | 
        
           |  |  | 521 |         set_error_handler($invokable, E_ALL);
 | 
        
           | 1 | efrain | 522 |         $this->assertSame('Europe/London', core_date::get_user_timezone(null));
 | 
        
           | 1441 | ariadna | 523 |         $this->assertCount(1, $invokable->get_invocations());
 | 
        
           |  |  | 524 |         restore_error_handler();
 | 
        
           |  |  | 525 |   | 
        
           |  |  | 526 |         $invokable = self::get_invokable();
 | 
        
           |  |  | 527 |         set_error_handler($invokable, E_ALL);
 | 
        
           | 1 | efrain | 528 |         $this->assertSame('Europe/London', core_date::get_user_timezone());
 | 
        
           | 1441 | ariadna | 529 |         $this->assertCount(1, $invokable->get_invocations());
 | 
        
           |  |  | 530 |         restore_error_handler();
 | 
        
           | 1 | efrain | 531 |   | 
        
           |  |  | 532 |         // User object parameter.
 | 
        
           |  |  | 533 |         $admin = get_admin();
 | 
        
           |  |  | 534 |   | 
        
           |  |  | 535 |         $this->setTimezone('Europe/London');
 | 
        
           |  |  | 536 |         $USER->timezone = 'Pacific/Auckland';
 | 
        
           |  |  | 537 |         $CFG->forcetimezone = '99';
 | 
        
           |  |  | 538 |         $admin->timezone = 'Australia/Perth';
 | 
        
           |  |  | 539 |         $this->assertSame('Australia/Perth', core_date::get_user_timezone($admin));
 | 
        
           |  |  | 540 |   | 
        
           |  |  | 541 |         $this->setTimezone('Europe/Prague');
 | 
        
           |  |  | 542 |         $USER->timezone = 'Pacific/Auckland';
 | 
        
           |  |  | 543 |         $CFG->forcetimezone = '99';
 | 
        
           |  |  | 544 |         $admin->timezone = '99';
 | 
        
           |  |  | 545 |         $this->assertSame('Europe/Prague', core_date::get_user_timezone($admin));
 | 
        
           |  |  | 546 |   | 
        
           |  |  | 547 |         $this->setTimezone('99', 'Europe/London');
 | 
        
           |  |  | 548 |         $USER->timezone = 'Pacific/Auckland';
 | 
        
           |  |  | 549 |         $CFG->forcetimezone = '99';
 | 
        
           |  |  | 550 |         $admin->timezone = '99';
 | 
        
           |  |  | 551 |         $this->assertSame('Europe/London', core_date::get_user_timezone($admin));
 | 
        
           |  |  | 552 |   | 
        
           |  |  | 553 |         $this->setTimezone('Europe/Prague');
 | 
        
           |  |  | 554 |         $USER->timezone = 'Pacific/Auckland';
 | 
        
           |  |  | 555 |         $CFG->forcetimezone = '99';
 | 
        
           |  |  | 556 |         $admin->timezone = 'xx/zz';
 | 
        
           |  |  | 557 |         $this->assertSame('Europe/Prague', core_date::get_user_timezone($admin));
 | 
        
           |  |  | 558 |   | 
        
           |  |  | 559 |         $this->setTimezone('Europe/Prague');
 | 
        
           |  |  | 560 |         $USER->timezone = 'Pacific/Auckland';
 | 
        
           |  |  | 561 |         $CFG->forcetimezone = '99';
 | 
        
           |  |  | 562 |         unset($admin->timezone);
 | 
        
           |  |  | 563 |         $this->assertSame('Europe/Prague', core_date::get_user_timezone($admin));
 | 
        
           |  |  | 564 |   | 
        
           |  |  | 565 |         $this->setTimezone('Europe/Prague');
 | 
        
           |  |  | 566 |         $USER->timezone = 'Pacific/Auckland';
 | 
        
           |  |  | 567 |         $CFG->forcetimezone = 'Europe/Berlin';
 | 
        
           |  |  | 568 |         $admin->timezone = 'Australia/Perth';
 | 
        
           |  |  | 569 |         $this->assertSame('Europe/Berlin', core_date::get_user_timezone($admin));
 | 
        
           |  |  | 570 |   | 
        
           |  |  | 571 |         // Other scalar parameter.
 | 
        
           |  |  | 572 |   | 
        
           |  |  | 573 |         $this->setTimezone('Europe/Prague');
 | 
        
           |  |  | 574 |         $CFG->forcetimezone = '99';
 | 
        
           |  |  | 575 |   | 
        
           |  |  | 576 |         $USER->timezone = 'Pacific/Auckland';
 | 
        
           |  |  | 577 |         $this->assertSame('Pacific/Auckland', core_date::get_user_timezone('99'));
 | 
        
           |  |  | 578 |         $this->assertSame('Etc/GMT-1', core_date::get_user_timezone('1'));
 | 
        
           |  |  | 579 |         $this->assertSame('Etc/GMT+1', core_date::get_user_timezone(-1));
 | 
        
           |  |  | 580 |         $this->assertSame('Europe/London', core_date::get_user_timezone('Europe/London'));
 | 
        
           |  |  | 581 |         $USER->timezone = '99';
 | 
        
           |  |  | 582 |         $this->assertSame('Europe/Prague', core_date::get_user_timezone('99'));
 | 
        
           |  |  | 583 |         $this->assertSame('Europe/London', core_date::get_user_timezone('Europe/London'));
 | 
        
           |  |  | 584 |         $this->assertSame('Europe/Prague', core_date::get_user_timezone('xxx/zzz'));
 | 
        
           |  |  | 585 |         $USER->timezone = 'xxz/zzz';
 | 
        
           |  |  | 586 |         $this->assertSame('Europe/Prague', core_date::get_user_timezone('99'));
 | 
        
           |  |  | 587 |   | 
        
           |  |  | 588 |         $this->setTimezone('99', 'Europe/Prague');
 | 
        
           |  |  | 589 |         $CFG->forcetimezone = '99';
 | 
        
           |  |  | 590 |   | 
        
           |  |  | 591 |         $USER->timezone = 'Pacific/Auckland';
 | 
        
           |  |  | 592 |         $this->assertSame('Pacific/Auckland', core_date::get_user_timezone('99'));
 | 
        
           |  |  | 593 |         $this->assertSame('Europe/London', core_date::get_user_timezone('Europe/London'));
 | 
        
           |  |  | 594 |         $USER->timezone = '99';
 | 
        
           |  |  | 595 |         $this->assertSame('Europe/Prague', core_date::get_user_timezone('99'));
 | 
        
           |  |  | 596 |         $this->assertSame('Europe/London', core_date::get_user_timezone('Europe/London'));
 | 
        
           |  |  | 597 |         $this->assertSame('Europe/Prague', core_date::get_user_timezone('xxx/zzz'));
 | 
        
           |  |  | 598 |         $USER->timezone = 99;
 | 
        
           |  |  | 599 |         $this->assertSame('Europe/London', core_date::get_user_timezone('Europe/London'));
 | 
        
           |  |  | 600 |         $this->assertSame('Europe/Prague', core_date::get_user_timezone('xxx/zzz'));
 | 
        
           |  |  | 601 |         $USER->timezone = 'xxz/zzz';
 | 
        
           | 1441 | ariadna | 602 |   | 
        
           |  |  | 603 |         $invokable = self::get_invokable();
 | 
        
           |  |  | 604 |         set_error_handler($invokable, E_ALL);
 | 
        
           | 1 | efrain | 605 |         $this->assertSame('Europe/Prague', core_date::get_user_timezone('99'));
 | 
        
           | 1441 | ariadna | 606 |         $this->assertCount(0, $invokable->get_invocations());
 | 
        
           |  |  | 607 |         restore_error_handler();
 | 
        
           | 1 | efrain | 608 |   | 
        
           | 1441 | ariadna | 609 |         $invokable = self::get_invokable();
 | 
        
           |  |  | 610 |         set_error_handler($invokable, E_ALL);
 | 
        
           | 1 | efrain | 611 |         $this->setTimezone('xxx', 'Europe/Prague');
 | 
        
           | 1441 | ariadna | 612 |         $this->assertCount(1, $invokable->get_invocations());
 | 
        
           |  |  | 613 |         restore_error_handler();
 | 
        
           |  |  | 614 |   | 
        
           | 1 | efrain | 615 |         $CFG->forcetimezone = '99';
 | 
        
           |  |  | 616 |         $USER->timezone = 'xxx';
 | 
        
           | 1441 | ariadna | 617 |         $invokable = self::get_invokable();
 | 
        
           |  |  | 618 |         set_error_handler($invokable, E_ALL);
 | 
        
           | 1 | efrain | 619 |         $this->assertSame('Europe/Prague', core_date::get_user_timezone('99'));
 | 
        
           | 1441 | ariadna | 620 |         $this->assertCount(1, $invokable->get_invocations());
 | 
        
           | 1 | efrain | 621 |         $this->assertSame('Europe/Prague', core_date::get_user_timezone(99));
 | 
        
           | 1441 | ariadna | 622 |         $this->assertCount(2, $invokable->get_invocations());
 | 
        
           | 1 | efrain | 623 |         $this->assertSame('Etc/GMT-1', core_date::get_user_timezone(1));
 | 
        
           | 1441 | ariadna | 624 |         $this->assertCount(2, $invokable->get_invocations());
 | 
        
           |  |  | 625 |         restore_error_handler();
 | 
        
           | 1 | efrain | 626 |   | 
        
           |  |  | 627 |         $this->setTimezone('Europe/Prague');
 | 
        
           |  |  | 628 |         $CFG->forcetimezone = 'Pacific/Auckland';
 | 
        
           |  |  | 629 |         $USER->timezone = 'Europe/London';
 | 
        
           |  |  | 630 |         $this->assertSame('Pacific/Auckland', core_date::get_user_timezone(99));
 | 
        
           |  |  | 631 |         $this->assertSame('Europe/Berlin', core_date::get_user_timezone('Europe/Berlin'));
 | 
        
           |  |  | 632 |   | 
        
           |  |  | 633 |         // TZ object param.
 | 
        
           |  |  | 634 |   | 
        
           |  |  | 635 |         $this->setTimezone('UTC');
 | 
        
           |  |  | 636 |         $USER->timezone = 'Europe/London';
 | 
        
           |  |  | 637 |         $CFG->forcetimezone = 99;
 | 
        
           |  |  | 638 |         $tz = new DateTimeZone('Pacific/Auckland');
 | 
        
           | 1441 | ariadna | 639 |         $invokable = self::get_invokable();
 | 
        
           |  |  | 640 |         set_error_handler($invokable, E_ALL);
 | 
        
           | 1 | efrain | 641 |         $this->assertSame('Pacific/Auckland', core_date::get_user_timezone($tz));
 | 
        
           | 1441 | ariadna | 642 |         $this->assertCount(0, $invokable->get_invocations());
 | 
        
           |  |  | 643 |         restore_error_handler();
 | 
        
           | 1 | efrain | 644 |     }
 | 
        
           |  |  | 645 |   | 
        
           |  |  | 646 |     /**
 | 
        
           |  |  | 647 |      * @covers ::get_user_timezone_object
 | 
        
           |  |  | 648 |      */
 | 
        
           | 11 | efrain | 649 |     public function test_get_user_timezone_object(): void {
 | 
        
           | 1 | efrain | 650 |         global $CFG, $USER;
 | 
        
           |  |  | 651 |         $this->resetAfterTest();
 | 
        
           |  |  | 652 |   | 
        
           |  |  | 653 |         $this->setTimezone('Pacific/Auckland');
 | 
        
           |  |  | 654 |         $CFG->forcetimezone = '99';
 | 
        
           |  |  | 655 |   | 
        
           |  |  | 656 |         $zones = core_date::get_list_of_timezones();
 | 
        
           |  |  | 657 |         foreach ($zones as $zone) {
 | 
        
           |  |  | 658 |             $USER->timezone = $zone;
 | 
        
           |  |  | 659 |             $tz = core_date::get_user_timezone_object();
 | 
        
           |  |  | 660 |             $this->assertInstanceOf('DateTimeZone', $tz);
 | 
        
           |  |  | 661 |             $this->assertSame($zone, $tz->getName());
 | 
        
           |  |  | 662 |         }
 | 
        
           |  |  | 663 |     }
 | 
        
           |  |  | 664 |   | 
        
           |  |  | 665 |     /**
 | 
        
           |  |  | 666 |      * Data provider for the values for test_core_strftime().
 | 
        
           |  |  | 667 |      *
 | 
        
           |  |  | 668 |      * @return array
 | 
        
           |  |  | 669 |      */
 | 
        
           |  |  | 670 |     public static function get_strftime_provider(): array {
 | 
        
           |  |  | 671 |         return [
 | 
        
           |  |  | 672 |             'string_c' => [
 | 
        
           |  |  | 673 |                 "1708405742",
 | 
        
           |  |  | 674 |                 "%c",
 | 
        
           |  |  | 675 |                 "20 February 2024 at 1:09 pm",
 | 
        
           |  |  | 676 |             ],
 | 
        
           | 1441 | ariadna | 677 |             'Month Year only' => [
 | 
        
           |  |  | 678 |                 "1708405742",
 | 
        
           |  |  | 679 |                 "%B %Y",
 | 
        
           |  |  | 680 |                 "February 2024",
 | 
        
           |  |  | 681 |             ],
 | 
        
           |  |  | 682 |             'Abbreviated Month Year only' => [
 | 
        
           |  |  | 683 |                 "1708405742",
 | 
        
           |  |  | 684 |                 "%b %Y",
 | 
        
           |  |  | 685 |                 "Feb 2024",
 | 
        
           |  |  | 686 |             ],
 | 
        
           |  |  | 687 |             'DD Month Year' => [
 | 
        
           |  |  | 688 |                 "1708405742",
 | 
        
           |  |  | 689 |                 "%d %B %Y",
 | 
        
           |  |  | 690 |                 "20 February 2024",
 | 
        
           |  |  | 691 |             ],
 | 
        
           |  |  | 692 |             'D Month Year' => [
 | 
        
           |  |  | 693 |                 "1708405742",
 | 
        
           |  |  | 694 |                 "%e %B %Y",
 | 
        
           |  |  | 695 |                 "20 February 2024",
 | 
        
           |  |  | 696 |             ],
 | 
        
           |  |  | 697 |             'Abbreviated DD Month Year' => [
 | 
        
           |  |  | 698 |                 "1708405742",
 | 
        
           |  |  | 699 |                 "%d %b %Y",
 | 
        
           |  |  | 700 |                 "20 Feb 2024",
 | 
        
           |  |  | 701 |             ],
 | 
        
           |  |  | 702 |             'Abbreviated D Month Year' => [
 | 
        
           |  |  | 703 |                 "1708405742",
 | 
        
           |  |  | 704 |                 "%e %b %Y",
 | 
        
           |  |  | 705 |                 "20 Feb 2024",
 | 
        
           |  |  | 706 |             ],
 | 
        
           | 1 | efrain | 707 |             'numeric_c' => [
 | 
        
           |  |  | 708 |                 1708405742,
 | 
        
           |  |  | 709 |                 "%c",
 | 
        
           |  |  | 710 |                 "20 February 2024 at 1:09 pm",
 | 
        
           |  |  | 711 |             ],
 | 
        
           |  |  | 712 |             'string_strftimedatetime' => [
 | 
        
           |  |  | 713 |                 "1708405742",
 | 
        
           |  |  | 714 |                 get_string("strftimedatetime", 'langconfig'),
 | 
        
           |  |  | 715 |                 "20 February 2024, 01:09 PM",
 | 
        
           |  |  | 716 |             ],
 | 
        
           |  |  | 717 |             'numeric_strftimedatetime' => [
 | 
        
           |  |  | 718 |                 1708405742,
 | 
        
           |  |  | 719 |                 get_string("strftimedatetime", 'langconfig'),
 | 
        
           |  |  | 720 |                 "20 February 2024, 01:09 PM",
 | 
        
           |  |  | 721 |             ],
 | 
        
           |  |  | 722 |             'string_strftimedatetimeshortaccurate' => [
 | 
        
           |  |  | 723 |                 "1708405742",
 | 
        
           |  |  | 724 |                 get_string("strftimedatetimeshortaccurate", 'langconfig'),
 | 
        
           |  |  | 725 |                 "20/02/24, 13:09:02",
 | 
        
           |  |  | 726 |             ],
 | 
        
           |  |  | 727 |             'numeric_strftimedatetimeshortaccurate' => [
 | 
        
           |  |  | 728 |                 1708405742,
 | 
        
           |  |  | 729 |                 get_string("strftimedatetimeshortaccurate", 'langconfig'),
 | 
        
           |  |  | 730 |                 "20/02/24, 13:09:02",
 | 
        
           |  |  | 731 |             ],
 | 
        
           |  |  | 732 |         ];
 | 
        
           |  |  | 733 |     }
 | 
        
           |  |  | 734 |   | 
        
           |  |  | 735 |     /**
 | 
        
           |  |  | 736 |      * Test \core_date::strftime function.
 | 
        
           |  |  | 737 |      *
 | 
        
           |  |  | 738 |      * @dataProvider get_strftime_provider
 | 
        
           |  |  | 739 |      * @param mixed $input Input passed to strftime
 | 
        
           |  |  | 740 |      * @param string $format The date format to pass to strftime, falls back to '%c' if null
 | 
        
           |  |  | 741 |      * @param string $expected The output generated by strftime
 | 
        
           |  |  | 742 |      */
 | 
        
           |  |  | 743 |     public function test_strftime(mixed $input, string $format, string $expected): void {
 | 
        
           |  |  | 744 |         $this->assertEqualsIgnoringWhitespace($expected, core_date::strftime($format, $input));
 | 
        
           |  |  | 745 |     }
 | 
        
           | 1441 | ariadna | 746 |   | 
        
           |  |  | 747 |     /**
 | 
        
           |  |  | 748 |      * Data provider for ::test_strftime_locale.
 | 
        
           |  |  | 749 |      *
 | 
        
           |  |  | 750 |      * @return array[]
 | 
        
           |  |  | 751 |      */
 | 
        
           |  |  | 752 |     public static function get_strftime_locale_provider(): array {
 | 
        
           |  |  | 753 |         return [
 | 
        
           |  |  | 754 |             'Month Year only' => [
 | 
        
           |  |  | 755 |                 "1728487000",
 | 
        
           |  |  | 756 |                 'ru_RU.UTF-8',
 | 
        
           |  |  | 757 |                 "%B %Y",
 | 
        
           |  |  | 758 |                 "октябрь 2024",
 | 
        
           |  |  | 759 |             ],
 | 
        
           |  |  | 760 |             'DD Month Year' => [
 | 
        
           |  |  | 761 |                 "1728487000",
 | 
        
           |  |  | 762 |                 'ru_RU.UTF-8',
 | 
        
           |  |  | 763 |                 "%d %B %Y",
 | 
        
           |  |  | 764 |                 "09 октября 2024",
 | 
        
           |  |  | 765 |             ],
 | 
        
           |  |  | 766 |             'D Month Year' => [
 | 
        
           |  |  | 767 |                 "1728487000",
 | 
        
           |  |  | 768 |                 'ru_RU.UTF-8',
 | 
        
           |  |  | 769 |                 "%e %B %Y",
 | 
        
           |  |  | 770 |                 " 9 октября 2024",
 | 
        
           |  |  | 771 |             ],
 | 
        
           |  |  | 772 |             'Abbreviated Month Year only' => [
 | 
        
           |  |  | 773 |                 "1728487000",
 | 
        
           |  |  | 774 |                 'ru_RU.UTF-8',
 | 
        
           |  |  | 775 |                 "%b %Y",
 | 
        
           |  |  | 776 |                 "окт. 2024",
 | 
        
           |  |  | 777 |             ],
 | 
        
           |  |  | 778 |             'Abbreviated DD Month Year' => [
 | 
        
           |  |  | 779 |                 "1728487000",
 | 
        
           |  |  | 780 |                 'ru_RU.UTF-8',
 | 
        
           |  |  | 781 |                 "%d %b %Y",
 | 
        
           |  |  | 782 |                 "09 окт. 2024",
 | 
        
           |  |  | 783 |             ],
 | 
        
           |  |  | 784 |             'Abbreviated D Month Year' => [
 | 
        
           |  |  | 785 |                 "1728487000",
 | 
        
           |  |  | 786 |                 'ru_RU.UTF-8',
 | 
        
           |  |  | 787 |                 "%e %b %Y",
 | 
        
           |  |  | 788 |                 " 9 окт. 2024",
 | 
        
           |  |  | 789 |             ],
 | 
        
           |  |  | 790 |             'Invalid locale' => [
 | 
        
           |  |  | 791 |                 1728487000,
 | 
        
           |  |  | 792 |                 'xx',
 | 
        
           |  |  | 793 |                 '%B %Y',
 | 
        
           |  |  | 794 |                 'October 2024',
 | 
        
           |  |  | 795 |             ],
 | 
        
           |  |  | 796 |         ];
 | 
        
           |  |  | 797 |     }
 | 
        
           |  |  | 798 |   | 
        
           |  |  | 799 |     /**
 | 
        
           |  |  | 800 |      * Test \core_date::strftime function with alternate languages.
 | 
        
           |  |  | 801 |      *
 | 
        
           |  |  | 802 |      * @dataProvider get_strftime_locale_provider
 | 
        
           |  |  | 803 |      * @param mixed $input Input passed to strftime
 | 
        
           |  |  | 804 |      * @param string $locale The locale
 | 
        
           |  |  | 805 |      * @param string $format The date format to pass to strftime, falls back to '%c' if null
 | 
        
           |  |  | 806 |      * @param string $expected The output generated by strftime
 | 
        
           |  |  | 807 |      */
 | 
        
           |  |  | 808 |     public function test_strftime_locale(
 | 
        
           |  |  | 809 |         mixed $input,
 | 
        
           |  |  | 810 |         string $locale,
 | 
        
           |  |  | 811 |         string $format,
 | 
        
           |  |  | 812 |         string $expected,
 | 
        
           |  |  | 813 |     ): void {
 | 
        
           |  |  | 814 |         $this->assertEqualsIgnoringWhitespace(
 | 
        
           |  |  | 815 |             $expected,
 | 
        
           |  |  | 816 |             core_date::strftime($format, $input, $locale));
 | 
        
           |  |  | 817 |     }
 | 
        
           | 1 | efrain | 818 | }
 |