ff5c2a4b40c4c6361f46cbe3a58e5499f8c21bf2
[moodle.git] / lib / tests / date_legacy_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 legacy Moodle date/time functions.
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 legacy Moodle date/time functions.
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_legacy_testcase extends advanced_testcase {
37     public function test_settings() {
38         global $CFG;
39         $this->resetAfterTest();
41         $this->assertNotEmpty($CFG->timezone);
43         $this->assertSame('99', $CFG->forcetimezone);
45         $user = $this->getDataGenerator()->create_user();
46         $this->assertSame('99', $user->timezone);
47     }
49     public function test_get_user_timezone() {
50         global $CFG, $USER;
52         $this->resetAfterTest();
54         $user = $this->getDataGenerator()->create_user();
55         $this->setUser($user);
57         // All set to something.
59         $this->setTimezone('Pacific/Auckland', 'Pacific/Auckland');
60         $USER->timezone = 'Europe/Prague';
62         $tz = get_user_timezone();
63         $this->assertSame('Europe/Prague', $tz);
65         $tz = get_user_timezone(99);
66         $this->assertSame('Europe/Prague', $tz);
67         $tz = get_user_timezone('99');
68         $this->assertSame('Europe/Prague', $tz);
70         $tz = get_user_timezone('Europe/Berlin');
71         $this->assertSame('Europe/Berlin', $tz);
73         // User timezone not set.
75         $this->setTimezone('Pacific/Auckland', 'Pacific/Auckland');
76         $USER->timezone = '99';
78         $tz = get_user_timezone();
79         $this->assertSame('Pacific/Auckland', $tz);
81         $tz = get_user_timezone(99);
82         $this->assertSame('Pacific/Auckland', $tz);
83         $tz = get_user_timezone('99');
84         $this->assertSame('Pacific/Auckland', $tz);
86         $tz = get_user_timezone('Europe/Berlin');
87         $this->assertSame('Europe/Berlin', $tz);
89         // Server timezone not set.
91         $this->setTimezone('99', 'Pacific/Auckland');
92         $USER->timezone = 'Europe/Prague';
94         $tz = get_user_timezone();
95         $this->assertSame('Europe/Prague', $tz);
97         $tz = get_user_timezone(99);
98         $this->assertSame('Europe/Prague', $tz);
99         $tz = get_user_timezone('99');
100         $this->assertSame('Europe/Prague', $tz);
102         $tz = get_user_timezone('Europe/Berlin');
103         $this->assertSame('Europe/Berlin', $tz);
105         // Server and user timezone not set.
107         $this->setTimezone('99', 'Pacific/Auckland');
108         $USER->timezone = '99';
110         $tz = get_user_timezone();
111         $this->assertSame(99.0, $tz);
113         $tz = get_user_timezone(99);
114         $this->assertSame(99.0, $tz);
115         $tz = get_user_timezone('99');
116         $this->assertSame(99.0, $tz);
118         $tz = get_user_timezone('Europe/Berlin');
119         $this->assertSame('Europe/Berlin', $tz);
120     }
122     public function test_dst_offset_on() {
123         $time = gmmktime(1, 1, 1, 3, 1, 2015);
124         $this->assertSame(3600, dst_offset_on($time, 'Pacific/Auckland'));
125         $this->assertSame(0, dst_offset_on($time, 'Australia/Perth'));
126         $this->assertSame(1800, dst_offset_on($time, 'Australia/Lord_Howe'));
127         $this->assertSame(0, dst_offset_on($time, 'Europe/Prague'));
128         $this->assertSame(0, dst_offset_on($time, 'America/New_York'));
130         $time = gmmktime(1, 1, 1, 5, 1, 2015);
131         $this->assertSame(0, dst_offset_on($time, 'Pacific/Auckland'));
132         $this->assertSame(0, dst_offset_on($time, 'Australia/Perth'));
133         $this->assertSame(0, dst_offset_on($time, 'Australia/Lord_Howe'));
134         $this->assertSame(3600, dst_offset_on($time, 'Europe/Prague'));
135         $this->assertSame(3600, dst_offset_on($time, 'America/New_York'));
136     }
138     public function test_make_timestamp() {
139         global $CFG;
141         $this->resetAfterTest();
143         // There are quite a lot of problems, let's pick some less problematic zones for now.
144         $timezones = array('Europe/Prague', 'Europe/London', 'Australia/Perth', 'Pacific/Auckland', 'America/New_York', '99');
146         $dates = array(
147             array(2, 1, 0, 40, 40),
148             array(4, 3, 0, 30, 22),
149             array(9, 5, 0, 20, 19),
150             array(11, 28, 0, 10, 45),
151         );
152         $years = array(1999, 2009, 2014, 2018);
154         $this->setTimezone('Pacific/Auckland', 'Pacific/Auckland');
155         foreach ($timezones as $tz) {
156             foreach ($years as $year) {
157                 foreach ($dates as $date) {
158                     $result = make_timestamp($year, $date[0], $date[1], $date[2], $date[3], $date[4], $tz, true);
159                     $expected = new DateTime('now', new DateTimeZone(($tz == 99 ? 'Pacific/Auckland' : $tz)));
160                     $expected->setDate($year, $date[0], $date[1]);
161                     $expected->setTime($date[2], $date[3], $date[4]);
162                     $this->assertSame($expected->getTimestamp(), $result,
163                         'Incorrect result for data ' . $expected->format("D, d M Y H:i:s O") . ' ' . $tz);
164                 }
165             }
166         }
168         $this->setTimezone('99', 'Pacific/Auckland');
169         foreach ($timezones as $tz) {
170             foreach ($years as $year) {
171                 foreach ($dates as $date) {
172                     $result = make_timestamp($year, $date[0], $date[1], $date[2], $date[3], $date[4], $tz, true);
173                     $expected = new DateTime('now', new DateTimeZone(($tz == 99 ? 'Pacific/Auckland' : $tz)));
174                     $expected->setDate($year, $date[0], $date[1]);
175                     $expected->setTime($date[2], $date[3], $date[4]);
176                     $this->assertSame($expected->getTimestamp(), $result,
177                         'Incorrect result for data ' . $expected->format("D, d M Y H:i:s O") . ' ' . $tz);
178                 }
179             }
180         }
181     }
183     public function test_usergetdate() {
184         global $CFG;
186         $this->resetAfterTest();
188         // There are quite a lot of problems, let's pick some less problematic zones for now.
189         $timezones = array('Europe/Prague', 'Europe/London', 'Australia/Perth', 'Pacific/Auckland', 'America/New_York', '99');
191         $dates = array(
192             array(2, 1, 0, 40, 40),
193             array(4, 3, 0, 30, 22),
194             array(9, 5, 0, 20, 19),
195             array(11, 28, 0, 10, 45),
196         );
197         $years = array(1999, 2009, 2014, 2018);
199         $this->setTimezone('Pacific/Auckland', 'Pacific/Auckland');
200         foreach ($timezones as $tz) {
201             foreach ($years as $year) {
202                 foreach ($dates as $date) {
203                     $expected = new DateTime('now', new DateTimeZone(($tz == 99 ? 'Pacific/Auckland' : $tz)));
204                     $expected->setDate($year, $date[0], $date[1]);
205                     $expected->setTime($date[2], $date[3], $date[4]);
206                     $result = usergetdate($expected->getTimestamp(), $tz);
207                     unset($result[0]); // Extra introduced by getdate().
208                     $ex = array(
209                         'seconds' => $date[4],
210                         'minutes' => $date[3],
211                         'hours' => $date[2],
212                         'mday' => $date[1],
213                         'wday' => (int)$expected->format('w'),
214                         'mon' => $date[0],
215                         'year' => $year,
216                         'yday' => (int)$expected->format('z'),
217                         'weekday' => $expected->format('l'),
218                         'month' => $expected->format('F'),
219                     );
220                     $this->assertSame($ex, $result,
221                         'Incorrect result for data ' . $expected->format("D, d M Y H:i:s O") . ' ' . $tz);
222                 }
223             }
224         }
226         $this->setTimezone('99', 'Pacific/Auckland');
227         foreach ($timezones as $tz) {
228             foreach ($years as $year) {
229                 foreach ($dates as $date) {
230                     $expected = new DateTime('now', new DateTimeZone(($tz == 99 ? 'Pacific/Auckland' : $tz)));
231                     $expected->setDate($year, $date[0], $date[1]);
232                     $expected->setTime($date[2], $date[3], $date[4]);
233                     $result = usergetdate($expected->getTimestamp(), $tz);
234                     unset($result[0]); // Extra introduced by getdate().
235                     $ex = array(
236                         'seconds' => $date[4],
237                         'minutes' => $date[3],
238                         'hours' => $date[2],
239                         'mday' => $date[1],
240                         'wday' => (int)$expected->format('w'),
241                         'mon' => $date[0],
242                         'year' => $year,
243                         'yday' => (int)$expected->format('z'),
244                         'weekday' => $expected->format('l'),
245                         'month' => $expected->format('F'),
246                     );
247                     $this->assertSame($ex, $result,
248                         'Incorrect result for data ' . $expected->format("D, d M Y H:i:s O") . ' ' . $tz);
249                 }
250             }
251         }
252     }
254     public function test_userdate() {
255         global $CFG;
257         $this->resetAfterTest();
259         $dates = array(
260             array(2, 1, 0, 40, 40),
261             array(4, 3, 0, 30, 22),
262             array(9, 5, 0, 20, 19),
263             array(11, 28, 0, 10, 45),
264         );
265         $years = array(1999, 2009, 2014, 2018);
267         $users = array();
268         $users[] = $this->getDataGenerator()->create_user(array('timezone' => 99));
269         $users[] = $this->getDataGenerator()->create_user(array('timezone' => 'Europe/Prague'));
270         $users[] = $this->getDataGenerator()->create_user(array('timezone' => 'Pacific/Auckland'));
271         $users[] = $this->getDataGenerator()->create_user(array('timezone' => 'Australia/Perth'));
272         $users[] = $this->getDataGenerator()->create_user(array('timezone' => 'America/New_York'));
274         $format = get_string('strftimedaydatetime', 'langconfig');
276         $this->setTimezone('Pacific/Auckland', 'Pacific/Auckland');
277         foreach ($years as $year) {
278             foreach ($dates as $date) {
279                 $expected = new DateTime('now', new DateTimeZone('UTC'));
280                 $expected->setDate($year, $date[0], $date[1]);
281                 $expected->setTime($date[2], $date[3], $date[4]);
283                 foreach ($users as $user) {
284                     $this->setUser($user);
285                     $expected->setTimezone(new DateTimeZone(($user->timezone == 99 ? 'Pacific/Auckland' : $user->timezone)));
286                     $result = userdate($expected->getTimestamp(), '', 99, false, false);
287                     date_default_timezone_set($expected->getTimezone()->getName());
288                     $ex = strftime($format, $expected->getTimestamp());
289                     date_default_timezone_set($CFG->timezone);
290                     $this->assertSame($ex, $result);
291                 }
292             }
293         }
294     }
296     public function test_usertime() {
297         // This is a useless bad hack, it needs to be completely eliminated.
299         $time = gmmktime(1, 1, 1, 3, 1, 2015);
300         $this->assertSame($time - (60 * 60 * 1), usertime($time, '1'));
301         $this->assertSame($time - (60 * 60 * -1), usertime($time, '-1'));
302         $this->assertSame($time - (60 * 60 * 1), usertime($time, 'Europe/Prague'));
303         $this->assertSame($time - (60 * 60 * 8), usertime($time, 'Australia/Perth'));
304         $this->assertSame($time - (60 * 60 * 12), usertime($time, 'Pacific/Auckland'));
305         $this->assertSame($time - (60 * 60 * -5), usertime($time, 'America/New_York'));
307         $time = gmmktime(1, 1, 1, 5, 1, 2015);
308         $this->assertSame($time - (60 * 60 * 1), usertime($time, '1'));
309         $this->assertSame($time - (60 * 60 * -1), usertime($time, '-1'));
310         $this->assertSame($time - (60 * 60 * 1), usertime($time, 'Europe/Prague'));
311         $this->assertSame($time - (60 * 60 * 8), usertime($time, 'Australia/Perth'));
312         $this->assertSame($time - (60 * 60 * 12), usertime($time, 'Pacific/Auckland'));
313         $this->assertSame($time - (60 * 60 * -5), usertime($time, 'America/New_York'));
314     }
316     public function test_usertimezone() {
317         global $USER;
318         $this->resetAfterTest();
320         $this->setTimezone('Pacific/Auckland', 'Pacific/Auckland');
322         $USER->timezone = 'Europe/Prague';
323         $this->assertSame('Europe/Prague', usertimezone());
325         $USER->timezone = '1';
326         $this->assertSame('UTC+1', usertimezone());
328         $USER->timezone = '0';
329         $this->assertSame('UTC', usertimezone());
331         $USER->timezone = '99';
332         $this->assertSame('Pacific/Auckland', usertimezone());
334         $USER->timezone = '99';
335         $this->assertSame('Europe/Berlin', usertimezone('Europe/Berlin'));
337         $USER->timezone = '99';
338         $this->assertSame('Pacific/Auckland', usertimezone('99'));
340         $USER->timezone = 'Europe/Prague';
341         $this->assertSame('Europe/Prague', usertimezone('99'));
343         // When passed an unknown non-whole hour TZ, verify we round to closest
344         // hour. (Possible for legacy reasons when old timezones go away).
345         $USER->timezone = '-9.23';
346         $this->assertSame('UTC-9', usertimezone('99'));
347     }