MDL-54008 timezone: Updating references to Caracas tz.
[moodle.git] / lib / tests / date_test.php
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/>.
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  */
26 defined('MOODLE_INTERNAL') || die();
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();
40         $origtz = core_date::get_default_php_timezone();
41         $this->assertNotEmpty($origtz);
43         $this->setTimezone('Pacific/Auckland', 'Europe/Prague');
44         $this->assertSame('Europe/Prague', core_date::get_default_php_timezone());
46         $this->setTimezone('Pacific/Auckland', 'UTC');
47         $this->assertSame('UTC', core_date::get_default_php_timezone());
49         $this->setTimezone('Pacific/Auckland', 'GMT');
50         $this->assertSame('GMT', core_date::get_default_php_timezone());
51     }
53     public function test_normalise_timezone() {
54         $this->resetAfterTest();
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('Pacific/Auckland', core_date::normalise_timezone(14));
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'));
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('Pacific/Auckland', core_date::normalise_timezone(14));
112         $this->setTimezone('Pacific/Auckland', 'Pacific/Auckland');
113         $tz = new DateTimeZone('Pacific/Auckland');
114         $this->assertSame('Pacific/Auckland', core_date::normalise_timezone($tz));
115     }
117     public function test_windows_conversion() {
118         $file = __DIR__ . '/fixtures/timezonewindows.xml';
120         $contents = file_get_contents($file);
121         preg_match_all('/<mapZone other="([^"]+)" territory="001" type="([^"]+)"\/>/', $contents, $matches, PREG_SET_ORDER);
123         $this->assertCount(104, $matches); // NOTE: If the file contents change edit the core_date class and update this.
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     }
139     /**
140      * Sanity test for PHP stuff.
141      */
142     public function test_php_gmt_offsets() {
143         $this->resetAfterTest();
145         $this->setTimezone('Pacific/Auckland', 'Pacific/Auckland');
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         }
156         $date = new DateTime('now', new DateTimeZone('Etc/GMT'));
157         $this->assertSame(0, $date->getOffset());
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     }
169     public function test_get_localised_timezone() {
170         $this->resetAfterTest();
172         $this->setTimezone('Pacific/Auckland', 'Pacific/Auckland');
174         $result = core_date::get_localised_timezone('Pacific/Auckland');
175         $this->assertSame('Pacific/Auckland', $result);
177         $result = core_date::get_localised_timezone('99');
178         $this->assertSame('Server timezone (Pacific/Auckland)', $result);
180         $result = core_date::get_localised_timezone(99);
181         $this->assertSame('Server timezone (Pacific/Auckland)', $result);
183         $result = core_date::get_localised_timezone('Etc/GMT-1');
184         $this->assertSame('UTC+1', $result);
186         $result = core_date::get_localised_timezone('Etc/GMT+2');
187         $this->assertSame('UTC-2', $result);
189         $result = core_date::get_localised_timezone('GMT');
190         $this->assertSame('UTC', $result);
192         $result = core_date::get_localised_timezone('Etc/GMT');
193         $this->assertSame('UTC', $result);
194     }
196     public function test_get_list_of_timezones() {
197         $this->resetAfterTest();
199         $this->setTimezone('Pacific/Auckland', 'Pacific/Auckland');
201         $phpzones = DateTimeZone::listIdentifiers();
203         $zones = core_date::get_list_of_timezones();
204         $this->assertSame(count($phpzones), count($zones));
205         foreach ($zones as $zone => $zonename) {
206             $this->assertSame($zone, $zonename); // The same in English!
207             $this->assertContains($zone, $phpzones); // No extras expected.
208         }
210         $this->assertSame($zones, core_date::get_list_of_timezones(null, false));
212         $nnzones = core_date::get_list_of_timezones(null, true);
213         $last = $nnzones['99'];
214         $this->assertSame('Server timezone (Pacific/Auckland)', $last);
215         unset($nnzones['99']);
216         $this->assertSame($zones, $nnzones);
218         $nnzones = core_date::get_list_of_timezones('99', false);
219         $last = $nnzones['99'];
220         $this->assertSame('Server timezone (Pacific/Auckland)', $last);
221         unset($nnzones['99']);
222         $this->assertSame($zones, $nnzones);
224         $xxzones = core_date::get_list_of_timezones('xx', false);
225         $xx = $xxzones['xx'];
226         $this->assertSame('Invalid timezone "xx"', $xx);
227         unset($xxzones['xx']);
228         $this->assertSame($zones, $xxzones);
230         $xxzones = core_date::get_list_of_timezones('1', false);
231         $xx = $xxzones['1'];
232         $this->assertSame('Invalid timezone "UTC+1.0"', $xx);
233         unset($xxzones['1']);
234         $this->assertSame($zones, $xxzones);
236         $xxzones = core_date::get_list_of_timezones('-1.5', false);
237         $xx = $xxzones['-1.5'];
238         $this->assertSame('Invalid timezone "UTC-1.5"', $xx);
239         unset($xxzones['-1.5']);
240         $this->assertSame($zones, $xxzones);
242     }
244     public function test_get_server_timezone() {
245         global $CFG;
246         $this->resetAfterTest();
248         $this->setTimezone('Pacific/Auckland', 'Pacific/Auckland');
249         $this->assertSame('Pacific/Auckland', core_date::get_server_timezone());
251         $this->setTimezone('Pacific/Auckland', 'Europe/Prague');
252         $this->assertSame('Pacific/Auckland', core_date::get_server_timezone());
254         $this->setTimezone('99', 'Pacific/Auckland');
255         $this->assertSame('Pacific/Auckland', core_date::get_server_timezone());
257         $this->setTimezone(99, 'Pacific/Auckland');
258         $this->assertSame('Pacific/Auckland', core_date::get_server_timezone());
260         $this->setTimezone('Pacific/Auckland', 'Pacific/Auckland');
261         unset($CFG->timezone);
262         $this->assertSame('Pacific/Auckland', core_date::get_server_timezone());
264         // Admin should fix the settings.
265         $this->setTimezone('xxx/zzzz', 'Europe/Prague');
266         $this->assertSame('Europe/Prague', core_date::get_server_timezone());
267     }
269     public function test_get_server_timezone_object() {
270         $this->resetAfterTest();
272         $zones = core_date::get_list_of_timezones();
273         foreach ($zones as $zone) {
274             $this->setTimezone($zone, 'Pacific/Auckland');
275             $tz = core_date::get_server_timezone_object();
276             $this->assertInstanceOf('DateTimeZone', $tz);
277             $this->assertSame($zone, $tz->getName());
278         }
279     }
281     public function test_set_default_server_timezone() {
282         global $CFG;
283         $this->resetAfterTest();
285         $this->setTimezone('Europe/Prague', 'Pacific/Auckland');
286         unset($CFG->timezone);
287         date_default_timezone_set('UTC');
288         core_date::set_default_server_timezone();
289         $this->assertSame('Pacific/Auckland', date_default_timezone_get());
291         $this->setTimezone('', 'Pacific/Auckland');
292         date_default_timezone_set('UTC');
293         core_date::set_default_server_timezone();
294         $this->assertSame('Pacific/Auckland', date_default_timezone_get());
296         $this->setTimezone('99', 'Pacific/Auckland');
297         date_default_timezone_set('UTC');
298         core_date::set_default_server_timezone();
299         $this->assertSame('Pacific/Auckland', date_default_timezone_get());
301         $this->setTimezone(99, 'Pacific/Auckland');
302         date_default_timezone_set('UTC');
303         core_date::set_default_server_timezone();
304         $this->assertSame('Pacific/Auckland', date_default_timezone_get());
306         $this->setTimezone('Europe/Prague', 'Pacific/Auckland');
307         $CFG->timezone = 'UTC';
308         core_date::set_default_server_timezone();
309         $this->assertSame('UTC', date_default_timezone_get());
311         $this->setTimezone('Europe/Prague', 'Pacific/Auckland');
312         $CFG->timezone = 'Australia/Perth';
313         core_date::set_default_server_timezone();
314         $this->assertSame('Australia/Perth', date_default_timezone_get());
316         $this->setTimezone('0', 'Pacific/Auckland');
317         date_default_timezone_set('UTC');
318         core_date::set_default_server_timezone();
319         $this->assertSame('Etc/GMT', date_default_timezone_get());
321         $this->setTimezone('1', 'Pacific/Auckland');
322         date_default_timezone_set('UTC');
323         core_date::set_default_server_timezone();
324         $this->assertSame('Etc/GMT-1', date_default_timezone_get());
326         $this->setTimezone(1, 'Pacific/Auckland');
327         date_default_timezone_set('UTC');
328         core_date::set_default_server_timezone();
329         $this->assertSame('Etc/GMT-1', date_default_timezone_get());
331         $this->setTimezone('1.0', 'Pacific/Auckland');
332         date_default_timezone_set('UTC');
333         core_date::set_default_server_timezone();
334         $this->assertSame('Etc/GMT-1', date_default_timezone_get());
335     }
337     public function test_get_user_timezone() {
338         global $CFG, $USER;
339         $this->resetAfterTest();
341         // Null parameter.
343         $this->setTimezone('Europe/Prague', 'Pacific/Auckland');
344         $USER->timezone = 'Pacific/Auckland';
345         $CFG->forcetimezone = '99';
346         $this->assertSame('Pacific/Auckland', core_date::get_user_timezone(null));
347         $this->assertSame('Pacific/Auckland', core_date::get_user_timezone());
349         $this->setTimezone('Europe/Prague', 'Pacific/Auckland');
350         $USER->timezone = 'Pacific/Auckland';
351         $CFG->forcetimezone = 'Europe/Berlin';
352         $this->assertSame('Europe/Berlin', core_date::get_user_timezone(null));
353         $this->assertSame('Europe/Berlin', core_date::get_user_timezone());
355         $this->setTimezone('Europe/Prague', 'Pacific/Auckland');
356         $USER->timezone = 'Pacific/Auckland';
357         $CFG->forcetimezone = 'xxx/yyy';
358         $this->assertSame('Europe/Prague', core_date::get_user_timezone(null));
359         $this->assertSame('Europe/Prague', core_date::get_user_timezone());
361         $this->setTimezone('Europe/Prague', 'Pacific/Auckland');
362         $USER->timezone = 'abc/def';
363         $CFG->forcetimezone = '99';
364         $this->assertSame('Europe/Prague', core_date::get_user_timezone(null));
365         $this->assertSame('Europe/Prague', core_date::get_user_timezone());
367         $this->setTimezone('xxx/yyy', 'Europe/London');
368         $USER->timezone = 'abc/def';
369         $CFG->forcetimezone = 'Europe/Berlin';
370         $this->assertSame('Europe/Berlin', core_date::get_user_timezone(null));
371         $this->assertSame('Europe/Berlin', core_date::get_user_timezone());
373         $this->setTimezone('xxx/yyy', 'Europe/London');
374         $USER->timezone = 'abc/def';
375         $CFG->forcetimezone = 99;
376         $this->assertSame('Europe/London', core_date::get_user_timezone(null));
377         $this->assertSame('Europe/London', core_date::get_user_timezone());
379         // User object parameter.
380         $admin = get_admin();
382         $this->setTimezone('Europe/London');
383         $USER->timezone = 'Pacific/Auckland';
384         $CFG->forcetimezone = '99';
385         $admin->timezone = 'Australia/Perth';
386         $this->assertSame('Australia/Perth', core_date::get_user_timezone($admin));
388         $this->setTimezone('Europe/Prague');
389         $USER->timezone = 'Pacific/Auckland';
390         $CFG->forcetimezone = '99';
391         $admin->timezone = '99';
392         $this->assertSame('Europe/Prague', core_date::get_user_timezone($admin));
394         $this->setTimezone('99', 'Europe/London');
395         $USER->timezone = 'Pacific/Auckland';
396         $CFG->forcetimezone = '99';
397         $admin->timezone = '99';
398         $this->assertSame('Europe/London', core_date::get_user_timezone($admin));
400         $this->setTimezone('Europe/Prague');
401         $USER->timezone = 'Pacific/Auckland';
402         $CFG->forcetimezone = '99';
403         $admin->timezone = 'xx/zz';
404         $this->assertSame('Europe/Prague', core_date::get_user_timezone($admin));
406         $this->setTimezone('Europe/Prague');
407         $USER->timezone = 'Pacific/Auckland';
408         $CFG->forcetimezone = '99';
409         unset($admin->timezone);
410         $this->assertSame('Europe/Prague', core_date::get_user_timezone($admin));
412         $this->setTimezone('Europe/Prague');
413         $USER->timezone = 'Pacific/Auckland';
414         $CFG->forcetimezone = 'Europe/Berlin';
415         $admin->timezone = 'Australia/Perth';
416         $this->assertSame('Europe/Berlin', core_date::get_user_timezone($admin));
418         // Other scalar parameter.
420         $this->setTimezone('Europe/Prague');
421         $CFG->forcetimezone = '99';
423         $USER->timezone = 'Pacific/Auckland';
424         $this->assertSame('Pacific/Auckland', core_date::get_user_timezone('99'));
425         $this->assertSame('Etc/GMT-1', core_date::get_user_timezone('1'));
426         $this->assertSame('Etc/GMT+1', core_date::get_user_timezone(-1));
427         $this->assertSame('Europe/London', core_date::get_user_timezone('Europe/London'));
428         $USER->timezone = '99';
429         $this->assertSame('Europe/Prague', core_date::get_user_timezone('99'));
430         $this->assertSame('Europe/London', core_date::get_user_timezone('Europe/London'));
431         $this->assertSame('Europe/Prague', core_date::get_user_timezone('xxx/zzz'));
432         $USER->timezone = 'xxz/zzz';
433         $this->assertSame('Europe/Prague', core_date::get_user_timezone('99'));
435         $this->setTimezone('99', 'Europe/Prague');
436         $CFG->forcetimezone = '99';
438         $USER->timezone = 'Pacific/Auckland';
439         $this->assertSame('Pacific/Auckland', core_date::get_user_timezone('99'));
440         $this->assertSame('Europe/London', core_date::get_user_timezone('Europe/London'));
441         $USER->timezone = '99';
442         $this->assertSame('Europe/Prague', core_date::get_user_timezone('99'));
443         $this->assertSame('Europe/London', core_date::get_user_timezone('Europe/London'));
444         $this->assertSame('Europe/Prague', core_date::get_user_timezone('xxx/zzz'));
445         $USER->timezone = 99;
446         $this->assertSame('Europe/London', core_date::get_user_timezone('Europe/London'));
447         $this->assertSame('Europe/Prague', core_date::get_user_timezone('xxx/zzz'));
448         $USER->timezone = 'xxz/zzz';
449         $this->assertSame('Europe/Prague', core_date::get_user_timezone('99'));
451         $this->setTimezone('xxx', 'Europe/Prague');
452         $CFG->forcetimezone = '99';
453         $USER->timezone = 'xxx';
454         $this->assertSame('Europe/Prague', core_date::get_user_timezone('99'));
455         $this->assertSame('Europe/Prague', core_date::get_user_timezone(99));
456         $this->assertSame('Etc/GMT-1', core_date::get_user_timezone(1));
458         $this->setTimezone('Europe/Prague');
459         $CFG->forcetimezone = 'Pacific/Auckland';
460         $USER->timezone = 'Europe/London';
461         $this->assertSame('Pacific/Auckland', core_date::get_user_timezone(99));
462         $this->assertSame('Europe/Berlin', core_date::get_user_timezone('Europe/Berlin'));
464         // TZ object param.
466         $this->setTimezone('UTC');
467         $USER->timezone = 'Europe/London';
468         $CFG->forcetimezone = 99;
469         $tz = new DateTimeZone('Pacific/Auckland');
470         $this->assertSame('Pacific/Auckland', core_date::get_user_timezone($tz));
471     }
473     public function test_get_user_timezone_object() {
474         global $CFG, $USER;
475         $this->resetAfterTest();
477         $this->setTimezone('Pacific/Auckland');
478         $CFG->forcetimezone = '99';
480         $zones = core_date::get_list_of_timezones();
481         foreach ($zones as $zone) {
482             $USER->timezone = $zone;
483             $tz = core_date::get_user_timezone_object();
484             $this->assertInstanceOf('DateTimeZone', $tz);
485             $this->assertSame($zone, $tz->getName());
486         }
487     }