]>
Commit | Line | Data |
---|---|---|
4f5b44bd NL |
1 | <?php |
2 | ||
3 | /* | |
4 | * This file is part of the Symfony package. | |
5 | * | |
6 | * (c) Fabien Potencier <fabien@symfony.com> | |
7 | * | |
8 | * For the full copyright and license information, please view the LICENSE | |
9 | * file that was distributed with this source code. | |
10 | */ | |
11 | ||
12 | namespace Symfony\Component\Intl\Tests\DateFormatter; | |
13 | ||
14 | use Symfony\Component\Intl\DateFormatter\IntlDateFormatter; | |
15 | use Symfony\Component\Intl\Globals\IntlGlobals; | |
16 | use Symfony\Component\Intl\Intl; | |
17 | ||
18 | /** | |
19 | * Test case for IntlDateFormatter implementations. | |
20 | * | |
21 | * @author Bernhard Schussek <bschussek@gmail.com> | |
22 | */ | |
23 | abstract class AbstractIntlDateFormatterTest extends \PHPUnit_Framework_TestCase | |
24 | { | |
25 | /** | |
26 | * When a time zone is not specified, it uses the system default however it returns null in the getter method | |
27 | * @covers Symfony\Component\Intl\DateFormatter\IntlDateFormatter::getTimeZoneId | |
28 | * @see StubIntlDateFormatterTest::testDefaultTimeZoneIntl() | |
29 | */ | |
30 | public function testConstructorDefaultTimeZone() | |
31 | { | |
32 | $formatter = $this->getDateFormatter('en', IntlDateFormatter::MEDIUM, IntlDateFormatter::SHORT); | |
33 | ||
34 | // In PHP 5.5 default timezone depends on `date_default_timezone_get()` method | |
35 | if (version_compare(PHP_VERSION, '5.5.0-dev', '>=')) { | |
36 | $this->assertEquals(date_default_timezone_get(), $formatter->getTimeZoneId()); | |
37 | } else { | |
38 | $this->assertNull($formatter->getTimeZoneId()); | |
39 | } | |
40 | } | |
41 | ||
42 | /** | |
43 | * @dataProvider formatProvider | |
44 | */ | |
45 | public function testFormat($pattern, $timestamp, $expected) | |
46 | { | |
47 | $errorCode = IntlGlobals::U_ZERO_ERROR; | |
48 | $errorMessage = 'U_ZERO_ERROR'; | |
49 | ||
50 | $formatter = $this->getDefaultDateFormatter($pattern); | |
51 | $this->assertSame($expected, $formatter->format($timestamp)); | |
52 | $this->assertIsIntlSuccess($formatter, $errorMessage, $errorCode); | |
53 | } | |
54 | ||
55 | public function formatProvider() | |
56 | { | |
57 | $formatData = array( | |
58 | /* general */ | |
59 | array('y-M-d', 0, '1970-1-1'), | |
60 | array("EEE, MMM d, ''yy", 0, "Thu, Jan 1, '70"), | |
61 | array('h:mm a', 0, '12:00 AM'), | |
62 | array('yyyyy.MMMM.dd hh:mm aaa', 0, '01970.January.01 12:00 AM'), | |
63 | ||
64 | /* escaping */ | |
65 | array("'M'", 0, 'M'), | |
66 | array("'yy'", 0, 'yy'), | |
67 | array("'''yy'", 0, "'yy"), | |
68 | array("''y", 0, "'1970"), | |
69 | array("''yy", 0, "'70"), | |
70 | array("H 'o'' clock'", 0, "0 o' clock"), | |
71 | ||
72 | /* month */ | |
73 | array('M', 0, '1'), | |
74 | array('MM', 0, '01'), | |
75 | array('MMM', 0, 'Jan'), | |
76 | array('MMMM', 0, 'January'), | |
77 | array('MMMMM', 0, 'J'), | |
78 | array('MMMMMM', 0, '000001'), | |
79 | ||
80 | array('L', 0, '1'), | |
81 | array('LL', 0, '01'), | |
82 | array('LLL', 0, 'Jan'), | |
83 | array('LLLL', 0, 'January'), | |
84 | array('LLLLL', 0, 'J'), | |
85 | array('LLLLLL', 0, '000001'), | |
86 | ||
87 | /* year */ | |
88 | array('y', 0, '1970'), | |
89 | array('yy', 0, '70'), | |
90 | array('yyy', 0, '1970'), | |
91 | array('yyyy', 0, '1970'), | |
92 | array('yyyyy', 0, '01970'), | |
93 | array('yyyyyy', 0, '001970'), | |
94 | ||
95 | /* day */ | |
96 | array('d', 0, '1'), | |
97 | array('dd', 0, '01'), | |
98 | array('ddd', 0, '001'), | |
99 | ||
100 | /* quarter */ | |
101 | array('Q', 0, '1'), | |
102 | array('QQ', 0, '01'), | |
103 | array('QQQ', 0, 'Q1'), | |
104 | array('QQQQ', 0, '1st quarter'), | |
105 | array('QQQQQ', 0, '1st quarter'), | |
106 | ||
107 | array('q', 0, '1'), | |
108 | array('qq', 0, '01'), | |
109 | array('qqq', 0, 'Q1'), | |
110 | array('qqqq', 0, '1st quarter'), | |
111 | array('qqqqq', 0, '1st quarter'), | |
112 | ||
113 | // 4 months | |
114 | array('Q', 7776000, '2'), | |
115 | array('QQ', 7776000, '02'), | |
116 | array('QQQ', 7776000, 'Q2'), | |
117 | array('QQQQ', 7776000, '2nd quarter'), | |
118 | ||
119 | // 7 months | |
120 | array('QQQQ', 15638400, '3rd quarter'), | |
121 | ||
122 | // 10 months | |
123 | array('QQQQ', 23587200, '4th quarter'), | |
124 | ||
125 | /* 12-hour (1-12) */ | |
126 | array('h', 0, '12'), | |
127 | array('hh', 0, '12'), | |
128 | array('hhh', 0, '012'), | |
129 | ||
130 | array('h', 1, '12'), | |
131 | array('h', 3600, '1'), | |
132 | array('h', 43200, '12'), // 12 hours | |
133 | ||
134 | /* day of year */ | |
135 | array('D', 0, '1'), | |
136 | array('D', 86400, '2'), // 1 day | |
137 | array('D', 31536000, '1'), // 1 year | |
138 | array('D', 31622400, '2'), // 1 year + 1 day | |
139 | ||
140 | /* day of week */ | |
141 | array('E', 0, 'Thu'), | |
142 | array('EE', 0, 'Thu'), | |
143 | array('EEE', 0, 'Thu'), | |
144 | array('EEEE', 0, 'Thursday'), | |
145 | array('EEEEE', 0, 'T'), | |
146 | array('EEEEEE', 0, 'Thu'), | |
147 | ||
148 | array('E', 1296540000, 'Tue'), // 2011-02-01 | |
149 | array('E', 1296950400, 'Sun'), // 2011-02-06 | |
150 | ||
151 | /* am/pm marker */ | |
152 | array('a', 0, 'AM'), | |
153 | array('aa', 0, 'AM'), | |
154 | array('aaa', 0, 'AM'), | |
155 | array('aaaa', 0, 'AM'), | |
156 | ||
157 | // 12 hours | |
158 | array('a', 43200, 'PM'), | |
159 | array('aa', 43200, 'PM'), | |
160 | array('aaa', 43200, 'PM'), | |
161 | array('aaaa', 43200, 'PM'), | |
162 | ||
163 | /* 24-hour (0-23) */ | |
164 | array('H', 0, '0'), | |
165 | array('HH', 0, '00'), | |
166 | array('HHH', 0, '000'), | |
167 | ||
168 | array('H', 1, '0'), | |
169 | array('H', 3600, '1'), | |
170 | array('H', 43200, '12'), | |
171 | array('H', 46800, '13'), | |
172 | ||
173 | /* 24-hour (1-24) */ | |
174 | array('k', 0, '24'), | |
175 | array('kk', 0, '24'), | |
176 | array('kkk', 0, '024'), | |
177 | ||
178 | array('k', 1, '24'), | |
179 | array('k', 3600, '1'), | |
180 | array('k', 43200, '12'), | |
181 | array('k', 46800, '13'), | |
182 | ||
183 | /* 12-hour (0-11) */ | |
184 | array('K', 0, '0'), | |
185 | array('KK', 0, '00'), | |
186 | array('KKK', 0, '000'), | |
187 | ||
188 | array('K', 1, '0'), | |
189 | array('K', 3600, '1'), | |
190 | array('K', 43200, '0'), // 12 hours | |
191 | ||
192 | /* minute */ | |
193 | array('m', 0, '0'), | |
194 | array('mm', 0, '00'), | |
195 | array('mmm', 0, '000'), | |
196 | ||
197 | array('m', 1, '0'), | |
198 | array('m', 60, '1'), | |
199 | array('m', 120, '2'), | |
200 | array('m', 180, '3'), | |
201 | array('m', 3600, '0'), | |
202 | array('m', 3660, '1'), | |
203 | array('m', 43200, '0'), // 12 hours | |
204 | ||
205 | /* second */ | |
206 | array('s', 0, '0'), | |
207 | array('ss', 0, '00'), | |
208 | array('sss', 0, '000'), | |
209 | ||
210 | array('s', 1, '1'), | |
211 | array('s', 2, '2'), | |
212 | array('s', 5, '5'), | |
213 | array('s', 30, '30'), | |
214 | array('s', 59, '59'), | |
215 | array('s', 60, '0'), | |
216 | array('s', 120, '0'), | |
217 | array('s', 180, '0'), | |
218 | array('s', 3600, '0'), | |
219 | array('s', 3601, '1'), | |
220 | array('s', 3630, '30'), | |
221 | array('s', 43200, '0'), // 12 hours | |
222 | ||
223 | // general | |
224 | array("yyyy.MM.dd 'at' HH:mm:ss zzz", 0, '1970.01.01 at 00:00:00 GMT'), | |
225 | array('K:mm a, z', 0, '0:00 AM, GMT'), | |
226 | ||
227 | // timezone | |
228 | array('z', 0, 'GMT'), | |
229 | array('zz', 0, 'GMT'), | |
230 | array('zzz', 0, 'GMT'), | |
231 | array('zzzz', 0, 'GMT'), | |
232 | array('zzzzz', 0, 'GMT'), | |
233 | ); | |
234 | ||
235 | // As of PHP 5.3.4, IntlDateFormatter::format() accepts DateTime instances | |
236 | if (version_compare(PHP_VERSION, '5.3.4', '>=')) { | |
237 | $dateTime = new \DateTime('@0'); | |
238 | ||
239 | /* general, DateTime */ | |
240 | $formatData[] = array('y-M-d', $dateTime, '1970-1-1'); | |
241 | $formatData[] = array("EEE, MMM d, ''yy", $dateTime, "Thu, Jan 1, '70"); | |
242 | $formatData[] = array('h:mm a', $dateTime, '12:00 AM'); | |
243 | $formatData[] = array('yyyyy.MMMM.dd hh:mm aaa', $dateTime, '01970.January.01 12:00 AM'); | |
244 | ||
245 | $formatData[] = array("yyyy.MM.dd 'at' HH:mm:ss zzz", $dateTime, '1970.01.01 at 00:00:00 GMT'); | |
246 | $formatData[] = array('K:mm a, z', $dateTime, '0:00 AM, GMT'); | |
247 | } | |
248 | ||
249 | return $formatData; | |
250 | } | |
251 | ||
252 | /** | |
253 | * @dataProvider formatErrorProvider | |
254 | */ | |
255 | public function testFormatIllegalArgumentError($pattern, $timestamp, $errorMessage) | |
256 | { | |
257 | $errorCode = IntlGlobals::U_ILLEGAL_ARGUMENT_ERROR; | |
258 | ||
259 | $formatter = $this->getDefaultDateFormatter($pattern); | |
260 | $this->assertFalse($formatter->format($timestamp)); | |
261 | $this->assertIsIntlFailure($formatter, $errorMessage, $errorCode); | |
262 | } | |
263 | ||
264 | public function formatErrorProvider() | |
265 | { | |
266 | // With PHP 5.5 IntlDateFormatter accepts empty values ('0') | |
267 | if (version_compare(PHP_VERSION, '5.5.0-dev', '>=')) { | |
268 | return array( | |
269 | array('y-M-d', 'foobar', 'datefmt_format: string \'foobar\' is not numeric, which would be required for it to be a valid date: U_ILLEGAL_ARGUMENT_ERROR') | |
270 | ); | |
271 | } | |
272 | ||
273 | $message = 'datefmt_format: takes either an array or an integer timestamp value : U_ILLEGAL_ARGUMENT_ERROR'; | |
274 | ||
275 | if (version_compare(PHP_VERSION, '5.3.4', '>=')) { | |
276 | $message = 'datefmt_format: takes either an array or an integer timestamp value or a DateTime object: U_ILLEGAL_ARGUMENT_ERROR'; | |
277 | } | |
278 | ||
279 | return array( | |
280 | array('y-M-d', '0', $message), | |
281 | array('y-M-d', 'foobar', $message), | |
282 | ); | |
283 | } | |
284 | ||
285 | /** | |
286 | * @dataProvider formatWithTimezoneProvider | |
287 | */ | |
288 | public function testFormatWithTimezone($timestamp, $timezone, $expected) | |
289 | { | |
290 | $pattern = 'yyyy-MM-dd HH:mm:ss'; | |
291 | $formatter = $this->getDateFormatter('en', IntlDateFormatter::MEDIUM, IntlDateFormatter::SHORT, $timezone, IntlDateFormatter::GREGORIAN, $pattern); | |
292 | $this->assertSame($expected, $formatter->format($timestamp)); | |
293 | } | |
294 | ||
295 | public function formatWithTimezoneProvider() | |
296 | { | |
297 | $data = array( | |
298 | array(0, 'UTC', '1970-01-01 00:00:00'), | |
299 | array(0, 'GMT', '1970-01-01 00:00:00'), | |
300 | array(0, 'GMT-03:00', '1969-12-31 21:00:00'), | |
301 | array(0, 'GMT+03:00', '1970-01-01 03:00:00'), | |
302 | array(0, 'Europe/Zurich', '1970-01-01 01:00:00'), | |
303 | array(0, 'Europe/Paris', '1970-01-01 01:00:00'), | |
304 | array(0, 'Africa/Cairo', '1970-01-01 02:00:00'), | |
305 | array(0, 'Africa/Casablanca', '1970-01-01 00:00:00'), | |
306 | array(0, 'Africa/Djibouti', '1970-01-01 03:00:00'), | |
307 | array(0, 'Africa/Johannesburg', '1970-01-01 02:00:00'), | |
308 | array(0, 'America/Antigua', '1969-12-31 20:00:00'), | |
309 | array(0, 'America/Toronto', '1969-12-31 19:00:00'), | |
310 | array(0, 'America/Vancouver', '1969-12-31 16:00:00'), | |
311 | array(0, 'Asia/Aqtau', '1970-01-01 05:00:00'), | |
312 | array(0, 'Asia/Bangkok', '1970-01-01 07:00:00'), | |
313 | array(0, 'Asia/Dubai', '1970-01-01 04:00:00'), | |
314 | array(0, 'Australia/Brisbane', '1970-01-01 10:00:00'), | |
315 | array(0, 'Australia/Eucla', '1970-01-01 08:45:00'), | |
316 | array(0, 'Australia/Melbourne', '1970-01-01 10:00:00'), | |
317 | array(0, 'Europe/Berlin', '1970-01-01 01:00:00'), | |
318 | array(0, 'Europe/Dublin', '1970-01-01 01:00:00'), | |
319 | array(0, 'Europe/Warsaw', '1970-01-01 01:00:00'), | |
320 | array(0, 'Pacific/Fiji', '1970-01-01 12:00:00'), | |
321 | ); | |
322 | ||
323 | // As of PHP 5.5, intl ext no longer fallbacks invalid time zones to UTC | |
324 | if (!version_compare(PHP_VERSION, '5.5.0-dev', '>=')) { | |
325 | // When time zone not exists, uses UTC by default | |
326 | $data[] = array(0, 'Foo/Bar', '1970-01-01 00:00:00'); | |
327 | $data[] = array(0, 'UTC+04:30', '1970-01-01 00:00:00'); | |
328 | $data[] = array(0, 'UTC+04:AA', '1970-01-01 00:00:00'); | |
329 | } | |
330 | ||
331 | return $data; | |
332 | } | |
333 | ||
334 | public function testFormatWithGmtTimezone() | |
335 | { | |
336 | $formatter = $this->getDefaultDateFormatter('zzzz'); | |
337 | ||
338 | if (version_compare(PHP_VERSION, '5.5.0-dev', '>=')) { | |
339 | $formatter->setTimeZone('GMT+03:00'); | |
340 | } else { | |
341 | $formatter->setTimeZoneId('GMT+03:00'); | |
342 | } | |
343 | ||
344 | $this->assertEquals('GMT+03:00', $formatter->format(0)); | |
345 | } | |
346 | ||
347 | public function testFormatWithGmtTimeZoneAndMinutesOffset() | |
348 | { | |
349 | $formatter = $this->getDefaultDateFormatter('zzzz'); | |
350 | ||
351 | if (version_compare(PHP_VERSION, '5.5.0-dev', '>=')) { | |
352 | $formatter->setTimeZone('GMT+00:30'); | |
353 | } else { | |
354 | $formatter->setTimeZoneId('GMT+00:30'); | |
355 | } | |
356 | ||
357 | $this->assertEquals('GMT+00:30', $formatter->format(0)); | |
358 | } | |
359 | ||
360 | public function testFormatWithNonStandardTimezone() | |
361 | { | |
362 | $formatter = $this->getDefaultDateFormatter('zzzz'); | |
363 | ||
364 | if (version_compare(PHP_VERSION, '5.5.0-dev', '>=')) { | |
365 | $formatter->setTimeZone('Pacific/Fiji'); | |
366 | } else { | |
367 | $formatter->setTimeZoneId('Pacific/Fiji'); | |
368 | } | |
369 | ||
370 | $this->assertEquals('Fiji Standard Time', $formatter->format(0)); | |
371 | } | |
372 | ||
373 | public function testFormatWithConstructorTimezone() | |
374 | { | |
375 | $formatter = $this->getDateFormatter('en', IntlDateFormatter::MEDIUM, IntlDateFormatter::SHORT, 'UTC'); | |
376 | $formatter->setPattern('yyyy-MM-dd HH:mm:ss'); | |
377 | ||
378 | $this->assertEquals( | |
379 | $this->getDateTime(0)->format('Y-m-d H:i:s'), | |
380 | $formatter->format(0) | |
381 | ); | |
382 | } | |
383 | ||
384 | public function testFormatWithTimezoneFromEnvironmentVariable() | |
385 | { | |
386 | if (version_compare(PHP_VERSION, '5.5.0-dev', '>=')) { | |
387 | $this->markTestSkipped('IntlDateFormatter in PHP 5.5 no longer depends on TZ environment.'); | |
388 | } | |
389 | ||
390 | $tz = getenv('TZ'); | |
391 | putenv('TZ=Europe/London'); | |
392 | ||
393 | $formatter = $this->getDateFormatter('en', IntlDateFormatter::MEDIUM, IntlDateFormatter::SHORT); | |
394 | $formatter->setPattern('yyyy-MM-dd HH:mm:ss'); | |
395 | ||
396 | $this->assertEquals( | |
397 | $this->getDateTime(0)->format('Y-m-d H:i:s'), | |
398 | $formatter->format(0) | |
399 | ); | |
400 | ||
401 | $this->assertEquals('Europe/London', getenv('TZ')); | |
402 | ||
403 | // Restores TZ. | |
404 | putenv('TZ='.$tz); | |
405 | } | |
406 | ||
407 | public function testFormatWithTimezoneFromPhp() | |
408 | { | |
409 | if (!version_compare(PHP_VERSION, '5.5.0-dev', '>=')) { | |
410 | $this->markTestSkipped('Only in PHP 5.5 IntlDateFormatter depends on default timezone (`date_default_timezone_get()`).'); | |
411 | } | |
412 | ||
413 | $tz = date_default_timezone_get(); | |
414 | date_default_timezone_set('Europe/London'); | |
415 | ||
416 | $formatter = $this->getDateFormatter('en', IntlDateFormatter::MEDIUM, IntlDateFormatter::SHORT); | |
417 | $formatter->setPattern('yyyy-MM-dd HH:mm:ss'); | |
418 | ||
419 | $this->assertEquals( | |
420 | $this->getDateTime(0)->format('Y-m-d H:i:s'), | |
421 | $formatter->format(0) | |
422 | ); | |
423 | ||
424 | $this->assertEquals('Europe/London', date_default_timezone_get()); | |
425 | ||
426 | // Restores TZ. | |
427 | date_default_timezone_set($tz); | |
428 | } | |
429 | ||
430 | /** | |
431 | * @dataProvider dateAndTimeTypeProvider | |
432 | */ | |
433 | public function testDateAndTimeType($timestamp, $datetype, $timetype, $expected) | |
434 | { | |
435 | $formatter = $this->getDateFormatter('en', $datetype, $timetype, 'UTC'); | |
436 | $this->assertSame($expected, $formatter->format($timestamp)); | |
437 | } | |
438 | ||
439 | public function dateAndTimeTypeProvider() | |
440 | { | |
441 | return array( | |
442 | array(0, IntlDateFormatter::FULL, IntlDateFormatter::NONE, 'Thursday, January 1, 1970'), | |
443 | array(0, IntlDateFormatter::LONG, IntlDateFormatter::NONE, 'January 1, 1970'), | |
444 | array(0, IntlDateFormatter::MEDIUM, IntlDateFormatter::NONE, 'Jan 1, 1970'), | |
445 | array(0, IntlDateFormatter::SHORT, IntlDateFormatter::NONE, '1/1/70'), | |
446 | array(0, IntlDateFormatter::NONE, IntlDateFormatter::FULL, '12:00:00 AM GMT'), | |
447 | array(0, IntlDateFormatter::NONE, IntlDateFormatter::LONG, '12:00:00 AM GMT'), | |
448 | array(0, IntlDateFormatter::NONE, IntlDateFormatter::MEDIUM, '12:00:00 AM'), | |
449 | array(0, IntlDateFormatter::NONE, IntlDateFormatter::SHORT, '12:00 AM'), | |
450 | ); | |
451 | } | |
452 | ||
453 | public function testGetCalendar() | |
454 | { | |
455 | $formatter = $this->getDefaultDateFormatter(); | |
456 | $this->assertEquals(IntlDateFormatter::GREGORIAN, $formatter->getCalendar()); | |
457 | } | |
458 | ||
459 | public function testGetDateType() | |
460 | { | |
461 | $formatter = $this->getDateFormatter('en', IntlDateFormatter::FULL, IntlDateFormatter::NONE); | |
462 | $this->assertEquals(IntlDateFormatter::FULL, $formatter->getDateType()); | |
463 | } | |
464 | ||
465 | public function testGetLocale() | |
466 | { | |
467 | $formatter = $this->getDefaultDateFormatter(); | |
468 | $this->assertEquals('en', $formatter->getLocale()); | |
469 | } | |
470 | ||
471 | public function testGetPattern() | |
472 | { | |
473 | $formatter = $this->getDateFormatter('en', IntlDateFormatter::FULL, IntlDateFormatter::NONE, 'UTC', IntlDateFormatter::GREGORIAN, 'yyyy-MM-dd'); | |
474 | $this->assertEquals('yyyy-MM-dd', $formatter->getPattern()); | |
475 | } | |
476 | ||
477 | public function testGetTimeType() | |
478 | { | |
479 | $formatter = $this->getDateFormatter('en', IntlDateFormatter::NONE, IntlDateFormatter::FULL); | |
480 | $this->assertEquals(IntlDateFormatter::FULL, $formatter->getTimeType()); | |
481 | } | |
482 | ||
483 | /** | |
484 | * @dataProvider parseProvider | |
485 | */ | |
486 | public function testParse($pattern, $value, $expected) | |
487 | { | |
488 | $errorCode = IntlGlobals::U_ZERO_ERROR; | |
489 | $errorMessage = 'U_ZERO_ERROR'; | |
490 | ||
491 | $formatter = $this->getDefaultDateFormatter($pattern); | |
492 | $this->assertSame($expected, $formatter->parse($value)); | |
493 | $this->assertIsIntlSuccess($formatter, $errorMessage, $errorCode); | |
494 | } | |
495 | ||
496 | public function parseProvider() | |
497 | { | |
498 | return array_merge( | |
499 | $this->parseYearProvider(), | |
500 | $this->parseQuarterProvider(), | |
501 | $this->parseMonthProvider(), | |
502 | $this->parseStandaloneMonthProvider(), | |
503 | $this->parseDayProvider(), | |
504 | $this->parseDayOfWeekProvider(), | |
505 | $this->parseDayOfYearProvider(), | |
506 | $this->parseHour12ClockOneBasedProvider(), | |
507 | $this->parseHour12ClockZeroBasedProvider(), | |
508 | $this->parseHour24ClockOneBasedProvider(), | |
509 | $this->parseHour24ClockZeroBasedProvider(), | |
510 | $this->parseMinuteProvider(), | |
511 | $this->parseSecondProvider(), | |
512 | $this->parseTimezoneProvider(), | |
513 | $this->parseAmPmProvider(), | |
514 | $this->parseStandaloneAmPmProvider(), | |
515 | $this->parseRegexMetaCharsProvider(), | |
516 | $this->parseQuoteCharsProvider(), | |
517 | $this->parseDashSlashProvider() | |
518 | ); | |
519 | } | |
520 | ||
521 | public function parseYearProvider() | |
522 | { | |
523 | return array( | |
524 | array('y-M-d', '1970-1-1', 0), | |
525 | array('yy-M-d', '70-1-1', 0), | |
526 | ); | |
527 | } | |
528 | ||
529 | public function parseQuarterProvider() | |
530 | { | |
531 | return array( | |
532 | array('Q', '1', 0), | |
533 | array('QQ', '01', 0), | |
534 | array('QQQ', 'Q1', 0), | |
535 | array('QQQQ', '1st quarter', 0), | |
536 | array('QQQQQ', '1st quarter', 0), | |
537 | ||
538 | array('Q', '2', 7776000), | |
539 | array('QQ', '02', 7776000), | |
540 | array('QQQ', 'Q2', 7776000), | |
541 | array('QQQQ', '2nd quarter', 7776000), | |
542 | array('QQQQQ', '2nd quarter', 7776000), | |
543 | ||
544 | array('q', '1', 0), | |
545 | array('qq', '01', 0), | |
546 | array('qqq', 'Q1', 0), | |
547 | array('qqqq', '1st quarter', 0), | |
548 | array('qqqqq', '1st quarter', 0), | |
549 | ); | |
550 | } | |
551 | ||
552 | public function parseMonthProvider() | |
553 | { | |
554 | return array( | |
555 | array('y-M-d', '1970-1-1', 0), | |
556 | array('y-MMM-d', '1970-Jan-1', 0), | |
557 | array('y-MMMM-d', '1970-January-1', 0), | |
558 | ); | |
559 | } | |
560 | ||
561 | public function parseStandaloneMonthProvider() | |
562 | { | |
563 | return array( | |
564 | array('y-L-d', '1970-1-1', 0), | |
565 | array('y-LLL-d', '1970-Jan-1', 0), | |
566 | array('y-LLLL-d', '1970-January-1', 0), | |
567 | ); | |
568 | } | |
569 | ||
570 | public function parseDayProvider() | |
571 | { | |
572 | return array( | |
573 | array('y-M-d', '1970-1-1', 0), | |
574 | array('y-M-dd', '1970-1-01', 0), | |
575 | array('y-M-ddd', '1970-1-001', 0), | |
576 | ); | |
577 | } | |
578 | ||
579 | public function parseDayOfWeekProvider() | |
580 | { | |
581 | return array( | |
582 | array('E', 'Thu', 0), | |
583 | array('EE', 'Thu', 0), | |
584 | array('EEE', 'Thu', 0), | |
585 | array('EEEE', 'Thursday', 0), | |
586 | array('EEEEE', 'T', 432000), | |
587 | array('EEEEEE', 'Thu', 0), | |
588 | ); | |
589 | } | |
590 | ||
591 | public function parseDayOfYearProvider() | |
592 | { | |
593 | return array( | |
594 | array('D', '1', 0), | |
595 | array('D', '2', 86400), | |
596 | ); | |
597 | } | |
598 | ||
599 | public function parseHour12ClockOneBasedProvider() | |
600 | { | |
601 | return array( | |
602 | // 12 hours (1-12) | |
603 | array('y-M-d h', '1970-1-1 1', 3600), | |
604 | array('y-M-d h', '1970-1-1 10', 36000), | |
605 | array('y-M-d hh', '1970-1-1 11', 39600), | |
606 | array('y-M-d hh', '1970-1-1 12', 0), | |
607 | array('y-M-d hh a', '1970-1-1 0 AM', 0), | |
608 | array('y-M-d hh a', '1970-1-1 1 AM', 3600), | |
609 | array('y-M-d hh a', '1970-1-1 10 AM', 36000), | |
610 | array('y-M-d hh a', '1970-1-1 11 AM', 39600), | |
611 | array('y-M-d hh a', '1970-1-1 12 AM', 0), | |
612 | array('y-M-d hh a', '1970-1-1 23 AM', 82800), | |
613 | array('y-M-d hh a', '1970-1-1 24 AM', 86400), | |
614 | array('y-M-d hh a', '1970-1-1 0 PM', 43200), | |
615 | array('y-M-d hh a', '1970-1-1 1 PM', 46800), | |
616 | array('y-M-d hh a', '1970-1-1 10 PM', 79200), | |
617 | array('y-M-d hh a', '1970-1-1 11 PM', 82800), | |
618 | array('y-M-d hh a', '1970-1-1 12 PM', 43200), | |
619 | array('y-M-d hh a', '1970-1-1 23 PM', 126000), | |
620 | array('y-M-d hh a', '1970-1-1 24 PM', 129600), | |
621 | ); | |
622 | } | |
623 | ||
624 | public function parseHour12ClockZeroBasedProvider() | |
625 | { | |
626 | return array( | |
627 | // 12 hours (0-11) | |
628 | array('y-M-d K', '1970-1-1 1', 3600), | |
629 | array('y-M-d K', '1970-1-1 10', 36000), | |
630 | array('y-M-d KK', '1970-1-1 11', 39600), | |
631 | array('y-M-d KK', '1970-1-1 12', 43200), | |
632 | array('y-M-d KK a', '1970-1-1 0 AM', 0), | |
633 | array('y-M-d KK a', '1970-1-1 1 AM', 3600), | |
634 | array('y-M-d KK a', '1970-1-1 10 AM', 36000), | |
635 | array('y-M-d KK a', '1970-1-1 11 AM', 39600), | |
636 | array('y-M-d KK a', '1970-1-1 12 AM', 43200), | |
637 | array('y-M-d KK a', '1970-1-1 23 AM', 82800), | |
638 | array('y-M-d KK a', '1970-1-1 24 AM', 86400), | |
639 | array('y-M-d KK a', '1970-1-1 0 PM', 43200), | |
640 | array('y-M-d KK a', '1970-1-1 1 PM', 46800), | |
641 | array('y-M-d KK a', '1970-1-1 10 PM', 79200), | |
642 | array('y-M-d KK a', '1970-1-1 11 PM', 82800), | |
643 | array('y-M-d KK a', '1970-1-1 12 PM', 86400), | |
644 | array('y-M-d KK a', '1970-1-1 23 PM', 126000), | |
645 | array('y-M-d KK a', '1970-1-1 24 PM', 129600), | |
646 | ); | |
647 | } | |
648 | ||
649 | public function parseHour24ClockOneBasedProvider() | |
650 | { | |
651 | return array( | |
652 | // 24 hours (1-24) | |
653 | array('y-M-d k', '1970-1-1 1', 3600), | |
654 | array('y-M-d k', '1970-1-1 10', 36000), | |
655 | array('y-M-d kk', '1970-1-1 11', 39600), | |
656 | array('y-M-d kk', '1970-1-1 12', 43200), | |
657 | array('y-M-d kk', '1970-1-1 23', 82800), | |
658 | array('y-M-d kk', '1970-1-1 24', 0), | |
659 | array('y-M-d kk a', '1970-1-1 0 AM', 0), | |
660 | array('y-M-d kk a', '1970-1-1 1 AM', 0), | |
661 | array('y-M-d kk a', '1970-1-1 10 AM', 0), | |
662 | array('y-M-d kk a', '1970-1-1 11 AM', 0), | |
663 | array('y-M-d kk a', '1970-1-1 12 AM', 0), | |
664 | array('y-M-d kk a', '1970-1-1 23 AM', 0), | |
665 | array('y-M-d kk a', '1970-1-1 24 AM', 0), | |
666 | array('y-M-d kk a', '1970-1-1 0 PM', 43200), | |
667 | array('y-M-d kk a', '1970-1-1 1 PM', 43200), | |
668 | array('y-M-d kk a', '1970-1-1 10 PM', 43200), | |
669 | array('y-M-d kk a', '1970-1-1 11 PM', 43200), | |
670 | array('y-M-d kk a', '1970-1-1 12 PM', 43200), | |
671 | array('y-M-d kk a', '1970-1-1 23 PM', 43200), | |
672 | array('y-M-d kk a', '1970-1-1 24 PM', 43200), | |
673 | ); | |
674 | } | |
675 | ||
676 | public function parseHour24ClockZeroBasedProvider() | |
677 | { | |
678 | return array( | |
679 | // 24 hours (0-23) | |
680 | array('y-M-d H', '1970-1-1 0', 0), | |
681 | array('y-M-d H', '1970-1-1 1', 3600), | |
682 | array('y-M-d H', '1970-1-1 10', 36000), | |
683 | array('y-M-d HH', '1970-1-1 11', 39600), | |
684 | array('y-M-d HH', '1970-1-1 12', 43200), | |
685 | array('y-M-d HH', '1970-1-1 23', 82800), | |
686 | array('y-M-d HH a', '1970-1-1 0 AM', 0), | |
687 | array('y-M-d HH a', '1970-1-1 1 AM', 0), | |
688 | array('y-M-d HH a', '1970-1-1 10 AM', 0), | |
689 | array('y-M-d HH a', '1970-1-1 11 AM', 0), | |
690 | array('y-M-d HH a', '1970-1-1 12 AM', 0), | |
691 | array('y-M-d HH a', '1970-1-1 23 AM', 0), | |
692 | array('y-M-d HH a', '1970-1-1 24 AM', 0), | |
693 | array('y-M-d HH a', '1970-1-1 0 PM', 43200), | |
694 | array('y-M-d HH a', '1970-1-1 1 PM', 43200), | |
695 | array('y-M-d HH a', '1970-1-1 10 PM', 43200), | |
696 | array('y-M-d HH a', '1970-1-1 11 PM', 43200), | |
697 | array('y-M-d HH a', '1970-1-1 12 PM', 43200), | |
698 | array('y-M-d HH a', '1970-1-1 23 PM', 43200), | |
699 | array('y-M-d HH a', '1970-1-1 24 PM', 43200), | |
700 | ); | |
701 | } | |
702 | ||
703 | public function parseMinuteProvider() | |
704 | { | |
705 | return array( | |
706 | array('y-M-d HH:m', '1970-1-1 0:1', 60), | |
707 | array('y-M-d HH:mm', '1970-1-1 0:10', 600), | |
708 | ); | |
709 | } | |
710 | ||
711 | public function parseSecondProvider() | |
712 | { | |
713 | return array( | |
714 | array('y-M-d HH:mm:s', '1970-1-1 00:01:1', 61), | |
715 | array('y-M-d HH:mm:ss', '1970-1-1 00:01:10', 70), | |
716 | ); | |
717 | } | |
718 | ||
719 | public function parseTimezoneProvider() | |
720 | { | |
721 | return array( | |
722 | array('y-M-d HH:mm:ss zzzz', '1970-1-1 00:00:00 GMT-03:00', 10800), | |
723 | array('y-M-d HH:mm:ss zzzz', '1970-1-1 00:00:00 GMT-04:00', 14400), | |
724 | array('y-M-d HH:mm:ss zzzz', '1970-1-1 00:00:00 GMT-00:00', 0), | |
725 | array('y-M-d HH:mm:ss zzzz', '1970-1-1 00:00:00 GMT+03:00', -10800), | |
726 | array('y-M-d HH:mm:ss zzzz', '1970-1-1 00:00:00 GMT+04:00', -14400), | |
727 | array('y-M-d HH:mm:ss zzzz', '1970-1-1 00:00:00 GMT-0300', 10800), | |
728 | array('y-M-d HH:mm:ss zzzz', '1970-1-1 00:00:00 GMT+0300', -10800), | |
729 | ||
730 | // a previous timezone parsing should not change the timezone for the next parsing | |
731 | array('y-M-d HH:mm:ss', '1970-1-1 00:00:00', 0), | |
732 | ); | |
733 | } | |
734 | ||
735 | public function parseAmPmProvider() | |
736 | { | |
737 | return array( | |
738 | // AM/PM (already covered by hours tests) | |
739 | array('y-M-d HH:mm:ss a', '1970-1-1 00:00:00 AM', 0), | |
740 | array('y-M-d HH:mm:ss a', '1970-1-1 00:00:00 PM', 43200), | |
741 | ); | |
742 | } | |
743 | ||
744 | public function parseStandaloneAmPmProvider() | |
745 | { | |
746 | return array( | |
747 | array('a', 'AM', 0), | |
748 | array('a', 'PM', 43200), | |
749 | ); | |
750 | } | |
751 | ||
752 | public function parseRegexMetaCharsProvider() | |
753 | { | |
754 | return array( | |
755 | // regexp meta chars in the pattern string | |
756 | array('y[M-d', '1970[1-1', 0), | |
757 | array('y[M/d', '1970[1/1', 0), | |
758 | ); | |
759 | } | |
760 | ||
761 | public function parseQuoteCharsProvider() | |
762 | { | |
763 | return array( | |
764 | array("'M'", 'M', 0), | |
765 | array("'yy'", 'yy', 0), | |
766 | array("'''yy'", "'yy", 0), | |
767 | array("''y", "'1970", 0), | |
768 | array("H 'o'' clock'", "0 o' clock", 0), | |
769 | ); | |
770 | } | |
771 | ||
772 | public function parseDashSlashProvider() | |
773 | { | |
774 | return array( | |
775 | array('y-M-d', '1970/1/1', 0), | |
776 | array('yy-M-d', '70/1/1', 0), | |
777 | array('y/M/d', '1970-1-1', 0), | |
778 | array('yy/M/d', '70-1-1', 0), | |
779 | ); | |
780 | } | |
781 | ||
782 | /** | |
783 | * @dataProvider parseErrorProvider | |
784 | */ | |
785 | public function testParseError($pattern, $value) | |
786 | { | |
787 | $errorCode = IntlGlobals::U_PARSE_ERROR; | |
788 | $errorMessage = 'Date parsing failed: U_PARSE_ERROR'; | |
789 | ||
790 | $formatter = $this->getDefaultDateFormatter($pattern); | |
791 | $this->assertFalse($formatter->parse($value)); | |
792 | $this->assertIsIntlFailure($formatter, $errorMessage, $errorCode); | |
793 | } | |
794 | ||
795 | public function parseErrorProvider() | |
796 | { | |
797 | return array( | |
798 | // 1 char month | |
799 | array('y-MMMMM-d', '1970-J-1'), | |
800 | array('y-MMMMM-d', '1970-S-1'), | |
801 | ||
802 | // standalone 1 char month | |
803 | array('y-LLLLL-d', '1970-J-1'), | |
804 | array('y-LLLLL-d', '1970-S-1'), | |
805 | ); | |
806 | } | |
807 | ||
808 | /* | |
809 | * https://github.com/symfony/symfony/issues/4242 | |
810 | */ | |
811 | public function testParseAfterError() | |
812 | { | |
813 | $this->testParseError('y-MMMMM-d', '1970-J-1'); | |
814 | $this->testParse('y-M-d', '1970-1-1', 0); | |
815 | } | |
816 | ||
817 | public function testParseWithNullPositionValue() | |
818 | { | |
819 | $position = null; | |
820 | $formatter = $this->getDefaultDateFormatter('y'); | |
821 | $this->assertSame(0, $formatter->parse('1970', $position)); | |
822 | $this->assertNull($position); | |
823 | } | |
824 | ||
825 | public function testSetPattern() | |
826 | { | |
827 | $formatter = $this->getDefaultDateFormatter(); | |
828 | $formatter->setPattern('yyyy-MM-dd'); | |
829 | $this->assertEquals('yyyy-MM-dd', $formatter->getPattern()); | |
830 | } | |
831 | ||
832 | /** | |
833 | * @covers Symfony\Component\Intl\DateFormatter\IntlDateFormatter::getTimeZoneId | |
834 | * @dataProvider setTimeZoneIdProvider | |
835 | */ | |
836 | public function testSetTimeZoneId($timeZoneId, $expectedTimeZoneId) | |
837 | { | |
838 | $formatter = $this->getDefaultDateFormatter(); | |
839 | ||
840 | if (version_compare(PHP_VERSION, '5.5.0-dev', '>=')) { | |
841 | $formatter->setTimeZone($timeZoneId); | |
842 | } else { | |
843 | $formatter->setTimeZoneId($timeZoneId); | |
844 | } | |
845 | ||
846 | $this->assertEquals($expectedTimeZoneId, $formatter->getTimeZoneId()); | |
847 | } | |
848 | ||
849 | public function setTimeZoneIdProvider() | |
850 | { | |
851 | return array( | |
852 | array('UTC', 'UTC'), | |
853 | array('GMT', 'GMT'), | |
854 | array('GMT-03:00', 'GMT-03:00'), | |
855 | array('Europe/Zurich', 'Europe/Zurich'), | |
856 | array('GMT-0300', 'GMT-0300'), | |
857 | array('Foo/Bar', 'Foo/Bar'), | |
858 | array('GMT+00:AA', 'GMT+00:AA'), | |
859 | array('GMT+00AA', 'GMT+00AA'), | |
860 | ); | |
861 | } | |
862 | ||
863 | protected function getDefaultDateFormatter($pattern = null) | |
864 | { | |
865 | return $this->getDateFormatter('en', IntlDateFormatter::MEDIUM, IntlDateFormatter::SHORT, 'UTC', IntlDateFormatter::GREGORIAN, $pattern); | |
866 | } | |
867 | ||
868 | protected function getDateTime($timestamp = null) | |
869 | { | |
870 | if (version_compare(PHP_VERSION, '5.5.0-dev', '>=')) { | |
871 | $timeZone = date_default_timezone_get(); | |
872 | } else { | |
873 | $timeZone = getenv('TZ') ?: 'UTC'; | |
874 | } | |
875 | ||
876 | $dateTime = new \DateTime(); | |
877 | $dateTime->setTimestamp(null === $timestamp ? time() : $timestamp); | |
878 | $dateTime->setTimeZone(new \DateTimeZone($timeZone)); | |
879 | ||
880 | return $dateTime; | |
881 | } | |
882 | ||
883 | protected function assertIsIntlFailure($formatter, $errorMessage, $errorCode) | |
884 | { | |
885 | $this->assertSame($errorMessage, $this->getIntlErrorMessage()); | |
886 | $this->assertSame($errorCode, $this->getIntlErrorCode()); | |
887 | $this->assertTrue($this->isIntlFailure($this->getIntlErrorCode())); | |
888 | $this->assertSame($errorMessage, $formatter->getErrorMessage()); | |
889 | $this->assertSame($errorCode, $formatter->getErrorCode()); | |
890 | $this->assertTrue($this->isIntlFailure($formatter->getErrorCode())); | |
891 | } | |
892 | ||
893 | protected function assertIsIntlSuccess($formatter, $errorMessage, $errorCode) | |
894 | { | |
895 | /* @var IntlDateFormatter $formatter */ | |
896 | $this->assertSame($errorMessage, $this->getIntlErrorMessage()); | |
897 | $this->assertSame($errorCode, $this->getIntlErrorCode()); | |
898 | $this->assertFalse($this->isIntlFailure($this->getIntlErrorCode())); | |
899 | $this->assertSame($errorMessage, $formatter->getErrorMessage()); | |
900 | $this->assertSame($errorCode, $formatter->getErrorCode()); | |
901 | $this->assertFalse($this->isIntlFailure($formatter->getErrorCode())); | |
902 | } | |
903 | ||
904 | /** | |
905 | * @param $locale | |
906 | * @param $datetype | |
907 | * @param $timetype | |
908 | * @param null $timezone | |
909 | * @param int $calendar | |
910 | * @param null $pattern | |
911 | * | |
912 | * @return mixed | |
913 | */ | |
914 | abstract protected function getDateFormatter($locale, $datetype, $timetype, $timezone = null, $calendar = IntlDateFormatter::GREGORIAN, $pattern = null); | |
915 | ||
916 | /** | |
917 | * @return string | |
918 | */ | |
919 | abstract protected function getIntlErrorMessage(); | |
920 | ||
921 | /** | |
922 | * @return integer | |
923 | */ | |
924 | abstract protected function getIntlErrorCode(); | |
925 | ||
926 | /** | |
927 | * @param integer $errorCode | |
928 | * | |
929 | * @return Boolean | |
930 | */ | |
931 | abstract protected function isIntlFailure($errorCode); | |
932 | } |