StubIntlDateFormatterTest.php 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Tests\Component\Locale\Stub;
  11. require_once __DIR__.'/../TestCase.php';
  12. use Symfony\Component\Locale\Locale;
  13. use Symfony\Component\Locale\Stub\StubIntlDateFormatter;
  14. use Symfony\Tests\Component\Locale\TestCase as LocaleTestCase;
  15. class StubIntlDateFormatterTest extends LocaleTestCase
  16. {
  17. /**
  18. * @expectedException Symfony\Component\Locale\Exception\MethodArgumentValueNotImplementedException
  19. */
  20. public function testConstructorWithUnsupportedLocale()
  21. {
  22. $formatter = new StubIntlDateFormatter('pt_BR', StubIntlDateFormatter::MEDIUM, StubIntlDateFormatter::SHORT);
  23. }
  24. public function testConstructor()
  25. {
  26. $formatter = new StubIntlDateFormatter('en', StubIntlDateFormatter::MEDIUM, StubIntlDateFormatter::SHORT, 'UTC', StubIntlDateFormatter::GREGORIAN, 'y-M-d');
  27. $this->assertEquals('y-M-d', $formatter->getPattern());
  28. }
  29. /**
  30. * When a time zone is not specified, it uses the system default however it returns null in the getter method
  31. * @covers Symfony\Component\Locale\Stub\StubIntlDateFormatter::getTimeZoneId
  32. * @covers Symfony\Component\Locale\Stub\StubIntlDateFormatter::setTimeZoneId
  33. * @see StubIntlDateFormatterTest::testDefaultTimeZoneIntl()
  34. */
  35. public function testConstructorDefaultTimeZoneStub()
  36. {
  37. $formatter = new StubIntlDateFormatter('en', StubIntlDateFormatter::MEDIUM, StubIntlDateFormatter::SHORT);
  38. $this->assertNull($formatter->getTimeZoneId());
  39. }
  40. public function testConstructorDefaultTimeZoneIntl()
  41. {
  42. $this->skipIfIntlExtensionIsNotLoaded();
  43. $formatter = new \IntlDateFormatter('en', StubIntlDateFormatter::MEDIUM, StubIntlDateFormatter::SHORT);
  44. $this->assertNull($formatter->getTimeZoneId());
  45. }
  46. /**
  47. * @dataProvider formatProvider
  48. */
  49. public function testFormatStub($pattern, $timestamp, $expected)
  50. {
  51. $formatter = $this->createStubFormatter($pattern);
  52. $this->assertSame($expected, $formatter->format($timestamp));
  53. }
  54. /**
  55. * @dataProvider formatProvider
  56. */
  57. public function testFormatIntl($pattern, $timestamp, $expected)
  58. {
  59. $this->skipIfIntlExtensionIsNotLoaded();
  60. $this->skipIfICUVersionIsTooOld();
  61. $formatter = $this->createIntlFormatter($pattern);
  62. $this->assertSame($expected, $formatter->format($timestamp));
  63. }
  64. public function formatProvider()
  65. {
  66. $formatData = array(
  67. /* general */
  68. array('y-M-d', 0, '1970-1-1'),
  69. array("yyyy.MM.dd 'at' HH:mm:ss zzz", 0, '1970.01.01 at 00:00:00 GMT+00:00'),
  70. array("EEE, MMM d, ''yy", 0, "Thu, Jan 1, '70"),
  71. array('h:mm a', 0, '12:00 AM'),
  72. array('K:mm a, z', 0, '0:00 AM, GMT+00:00'),
  73. array('yyyyy.MMMM.dd hh:mm aaa', 0, '01970.January.01 12:00 AM'),
  74. /* escaping */
  75. array("'M'", 0, 'M'),
  76. array("'yy'", 0, 'yy'),
  77. array("'''yy'", 0, "'yy"),
  78. array("''y", 0, "'1970"),
  79. array("''yy", 0, "'70"),
  80. array("H 'o'' clock'", 0, "0 o' clock"),
  81. /* month */
  82. array('M', 0, '1'),
  83. array('MM', 0, '01'),
  84. array('MMM', 0, 'Jan'),
  85. array('MMMM', 0, 'January'),
  86. array('MMMMM', 0, 'J'),
  87. array('MMMMMM', 0, '000001'),
  88. array('L', 0, '1'),
  89. array('LL', 0, '01'),
  90. array('LLL', 0, 'Jan'),
  91. array('LLLL', 0, 'January'),
  92. array('LLLLL', 0, 'J'),
  93. array('LLLLLL', 0, '000001'),
  94. /* year */
  95. array('y', 0, '1970'),
  96. array('yy', 0, '70'),
  97. array('yyy', 0, '1970'),
  98. array('yyyy', 0, '1970'),
  99. array('yyyyy', 0, '01970'),
  100. array('yyyyyy', 0, '001970'),
  101. /* day */
  102. array('d', 0, '1'),
  103. array('dd', 0, '01'),
  104. array('ddd', 0, '001'),
  105. /* quarter */
  106. array('Q', 0, '1'),
  107. array('QQ', 0, '01'),
  108. array('QQQ', 0, 'Q1'),
  109. array('QQQQ', 0, '1st quarter'),
  110. array('QQQQQ', 0, '1st quarter'),
  111. array('q', 0, '1'),
  112. array('qq', 0, '01'),
  113. array('qqq', 0, 'Q1'),
  114. array('qqqq', 0, '1st quarter'),
  115. array('qqqqq', 0, '1st quarter'),
  116. // 4 months
  117. array('Q', 7776000, '2'),
  118. array('QQ', 7776000, '02'),
  119. array('QQQ', 7776000, 'Q2'),
  120. array('QQQQ', 7776000, '2nd quarter'),
  121. // 7 months
  122. array('QQQQ', 15638400, '3rd quarter'),
  123. // 10 months
  124. array('QQQQ', 23587200, '4th quarter'),
  125. /* 12-hour (1-12) */
  126. array('h', 0, '12'),
  127. array('hh', 0, '12'),
  128. array('hhh', 0, '012'),
  129. array('h', 1, '12'),
  130. array('h', 3600, '1'),
  131. array('h', 43200, '12'), // 12 hours
  132. /* day of year */
  133. array('D', 0, '1'),
  134. array('D', 86400, '2'), // 1 day
  135. array('D', 31536000, '1'), // 1 year
  136. array('D', 31622400, '2'), // 1 year + 1 day
  137. /* day of week */
  138. array('E', 0, 'Thu'),
  139. array('EE', 0, 'Thu'),
  140. array('EEE', 0, 'Thu'),
  141. array('EEEE', 0, 'Thursday'),
  142. array('EEEEE', 0, 'T'),
  143. array('EEEEEE', 0, 'Thu'),
  144. array('E', 1296540000, 'Tue'), // 2011-02-01
  145. array('E', 1296950400, 'Sun'), // 2011-02-06
  146. /* am/pm marker */
  147. array('a', 0, 'AM'),
  148. array('aa', 0, 'AM'),
  149. array('aaa', 0, 'AM'),
  150. array('aaaa', 0, 'AM'),
  151. // 12 hours
  152. array('a', 43200, 'PM'),
  153. array('aa', 43200, 'PM'),
  154. array('aaa', 43200, 'PM'),
  155. array('aaaa', 43200, 'PM'),
  156. /* 24-hour (0-23) */
  157. array('H', 0, '0'),
  158. array('HH', 0, '00'),
  159. array('HHH', 0, '000'),
  160. array('H', 1, '0'),
  161. array('H', 3600, '1'),
  162. array('H', 43200, '12'),
  163. array('H', 46800, '13'),
  164. /* 24-hour (1-24) */
  165. array('k', 0, '24'),
  166. array('kk', 0, '24'),
  167. array('kkk', 0, '024'),
  168. array('k', 1, '24'),
  169. array('k', 3600, '1'),
  170. array('k', 43200, '12'),
  171. array('k', 46800, '13'),
  172. /* 12-hour (0-11) */
  173. array('K', 0, '0'),
  174. array('KK', 0, '00'),
  175. array('KKK', 0, '000'),
  176. array('K', 1, '0'),
  177. array('K', 3600, '1'),
  178. array('K', 43200, '0'), // 12 hours
  179. /* minute */
  180. array('m', 0, '0'),
  181. array('mm', 0, '00'),
  182. array('mmm', 0, '000'),
  183. array('m', 1, '0'),
  184. array('m', 60, '1'),
  185. array('m', 120, '2'),
  186. array('m', 180, '3'),
  187. array('m', 3600, '0'),
  188. array('m', 3660, '1'),
  189. array('m', 43200, '0'), // 12 hours
  190. /* second */
  191. array('s', 0, '0'),
  192. array('ss', 0, '00'),
  193. array('sss', 0, '000'),
  194. array('s', 1, '1'),
  195. array('s', 2, '2'),
  196. array('s', 5, '5'),
  197. array('s', 30, '30'),
  198. array('s', 59, '59'),
  199. array('s', 60, '0'),
  200. array('s', 120, '0'),
  201. array('s', 180, '0'),
  202. array('s', 3600, '0'),
  203. array('s', 3601, '1'),
  204. array('s', 3630, '30'),
  205. array('s', 43200, '0'), // 12 hours
  206. /* timezone */
  207. array('z', 0, 'GMT+00:00'),
  208. array('zz', 0, 'GMT+00:00'),
  209. array('zzz', 0, 'GMT+00:00'),
  210. array('zzzz', 0, 'GMT+00:00'),
  211. array('zzzzz', 0, 'GMT+00:00'),
  212. );
  213. return $formatData;
  214. }
  215. /**
  216. * @dataProvider formatWithTimezoneProvider
  217. */
  218. public function testFormatWithTimezoneStub($timestamp, $timezone, $expected)
  219. {
  220. $pattern = 'yyyy-MM-dd HH:mm:ss';
  221. $formatter = new StubIntlDateFormatter('en', StubIntlDateFormatter::MEDIUM, StubIntlDateFormatter::SHORT, $timezone, StubIntlDateFormatter::GREGORIAN, $pattern);
  222. $this->assertSame($expected, $formatter->format($timestamp));
  223. }
  224. /**
  225. * @dataProvider formatWithTimezoneProvider
  226. */
  227. public function testFormatWithTimezoneIntl($timestamp, $timezone, $expected)
  228. {
  229. $this->skipIfIntlExtensionIsNotLoaded();
  230. $pattern = 'yyyy-MM-dd HH:mm:ss';
  231. $formatter = new \IntlDateFormatter('en', \IntlDateFormatter::MEDIUM, \IntlDateFormatter::SHORT, $timezone, \IntlDateFormatter::GREGORIAN, $pattern);
  232. $this->assertSame($expected, $formatter->format($timestamp));
  233. }
  234. public function formatWithTimezoneProvider()
  235. {
  236. return array(
  237. array(0, 'UTC', '1970-01-01 00:00:00'),
  238. array(0, 'GMT', '1970-01-01 00:00:00'),
  239. array(0, 'GMT-03:00', '1969-12-31 21:00:00'),
  240. array(0, 'GMT+03:00', '1970-01-01 03:00:00'),
  241. array(0, 'Europe/Zurich', '1970-01-01 01:00:00'),
  242. array(0, 'Europe/Paris', '1970-01-01 01:00:00'),
  243. array(0, 'Africa/Cairo', '1970-01-01 02:00:00'),
  244. array(0, 'Africa/Casablanca', '1970-01-01 00:00:00'),
  245. array(0, 'Africa/Djibouti', '1970-01-01 03:00:00'),
  246. array(0, 'Africa/Johannesburg', '1970-01-01 02:00:00'),
  247. array(0, 'America/Antigua', '1969-12-31 20:00:00'),
  248. array(0, 'America/Toronto', '1969-12-31 19:00:00'),
  249. array(0, 'America/Vancouver', '1969-12-31 16:00:00'),
  250. array(0, 'Asia/Aqtau', '1970-01-01 05:00:00'),
  251. array(0, 'Asia/Bangkok', '1970-01-01 07:00:00'),
  252. array(0, 'Asia/Dubai', '1970-01-01 04:00:00'),
  253. array(0, 'Australia/Brisbane', '1970-01-01 10:00:00'),
  254. array(0, 'Australia/Eucla', '1970-01-01 08:45:00'),
  255. array(0, 'Australia/Melbourne', '1970-01-01 10:00:00'),
  256. array(0, 'Europe/Berlin', '1970-01-01 01:00:00'),
  257. array(0, 'Europe/Dublin', '1970-01-01 01:00:00'),
  258. array(0, 'Europe/Warsaw', '1970-01-01 01:00:00'),
  259. array(0, 'Pacific/Fiji', '1970-01-01 12:00:00'),
  260. // When time zone not exists, uses UTC by default
  261. array(0, 'Foo/Bar', '1970-01-01 00:00:00'),
  262. array(0, 'UTC+04:30', '1970-01-01 00:00:00'),
  263. array(0, 'UTC+04:AA', '1970-01-01 00:00:00'),
  264. );
  265. }
  266. /**
  267. * @expectedException Symfony\Component\Locale\Exception\NotImplementedException
  268. */
  269. public function testFormatWithTimezoneFormatOptionAndDifferentThanUtcStub()
  270. {
  271. $formatter = $this->createStubFormatter('zzzz');
  272. $formatter->setTimeZoneId('Pacific/Fiji');
  273. $formatter->format(0);
  274. }
  275. public function testFormatWithTimezoneFormatOptionAndDifferentThanUtcIntl()
  276. {
  277. $this->skipIfIntlExtensionIsNotLoaded();
  278. $formatter = $this->createIntlFormatter('zzzz');
  279. $formatter->setTimeZoneId('Pacific/Fiji');
  280. $this->assertEquals('Fiji Time', $formatter->format(0));
  281. }
  282. public function testFormatWithGmtTimezoneStub()
  283. {
  284. $formatter = $this->createStubFormatter('zzzz');
  285. $formatter->setTimeZoneId('GMT+03:00');
  286. $this->assertEquals('GMT+03:00', $formatter->format(0));
  287. }
  288. public function testFormatWithGmtTimezoneIntl()
  289. {
  290. $this->skipIfIntlExtensionIsNotLoaded();
  291. $formatter = $this->createIntlFormatter('zzzz');
  292. $formatter->setTimeZoneId('GMT+03:00');
  293. $this->assertEquals('GMT+03:00', $formatter->format(0));
  294. }
  295. public function testFormatWithDefaultTimezoneStub()
  296. {
  297. $formatter = new StubIntlDateFormatter('en', StubIntlDateFormatter::MEDIUM, StubIntlDateFormatter::SHORT);
  298. $formatter->setPattern('yyyy-MM-dd HH:mm:ss');
  299. $this->assertEquals(
  300. $this->createDateTime(0)->format('Y-m-d H:i:s'),
  301. $formatter->format(0)
  302. );
  303. }
  304. public function testFormatWithDefaultTimezoneIntl()
  305. {
  306. $this->skipIfIntlExtensionIsNotLoaded();
  307. $this->skipIfICUVersionIsTooOld();
  308. $formatter = new \IntlDateFormatter('en', StubIntlDateFormatter::MEDIUM, StubIntlDateFormatter::SHORT);
  309. $formatter->setPattern('yyyy-MM-dd HH:mm:ss');
  310. $this->assertEquals(
  311. $this->createDateTime(0)->format('Y-m-d H:i:s'),
  312. $formatter->format(0)
  313. );
  314. }
  315. /**
  316. * @expectedException Symfony\Component\Locale\Exception\NotImplementedException
  317. */
  318. public function testFormatWithUnimplementedCharsStub()
  319. {
  320. $pattern = 'Y';
  321. $formatter = new StubIntlDateFormatter('en', StubIntlDateFormatter::MEDIUM, StubIntlDateFormatter::SHORT, 'UTC', StubIntlDateFormatter::GREGORIAN, $pattern);
  322. $formatter->format(0);
  323. }
  324. /**
  325. * @expectedException Symfony\Component\Locale\Exception\NotImplementedException
  326. */
  327. public function testFormatWithNonIntegerTimestamp()
  328. {
  329. $formatter = $this->createStubFormatter();
  330. $formatter->format(array());
  331. }
  332. /**
  333. * @dataProvider dateAndTimeTypeProvider
  334. */
  335. public function testDateAndTimeTypeStub($timestamp, $datetype, $timetype, $expected)
  336. {
  337. $formatter = new StubIntlDateFormatter('en', $datetype, $timetype, 'UTC');
  338. $this->assertSame($expected, $formatter->format($timestamp));
  339. }
  340. /**
  341. * @dataProvider dateAndTimeTypeProvider
  342. */
  343. public function testDateAndTimeTypeIntl($timestamp, $datetype, $timetype, $expected)
  344. {
  345. $this->skipIfIntlExtensionIsNotLoaded();
  346. $formatter = new \IntlDateFormatter('en', $datetype, $timetype, 'UTC');
  347. $this->assertSame($expected, $formatter->format($timestamp));
  348. }
  349. public function dateAndTimeTypeProvider()
  350. {
  351. return array(
  352. array(0, StubIntlDateFormatter::FULL, StubIntlDateFormatter::NONE, 'Thursday, January 1, 1970'),
  353. array(0, StubIntlDateFormatter::LONG, StubIntlDateFormatter::NONE, 'January 1, 1970'),
  354. array(0, StubIntlDateFormatter::MEDIUM, StubIntlDateFormatter::NONE, 'Jan 1, 1970'),
  355. array(0, StubIntlDateFormatter::SHORT, StubIntlDateFormatter::NONE, '1/1/70'),
  356. array(0, StubIntlDateFormatter::NONE, StubIntlDateFormatter::FULL, '12:00:00 AM GMT+00:00'),
  357. array(0, StubIntlDateFormatter::NONE, StubIntlDateFormatter::LONG, '12:00:00 AM GMT+00:00'),
  358. array(0, StubIntlDateFormatter::NONE, StubIntlDateFormatter::MEDIUM, '12:00:00 AM'),
  359. array(0, StubIntlDateFormatter::NONE, StubIntlDateFormatter::SHORT, '12:00 AM'),
  360. );
  361. }
  362. public function testGetCalendar()
  363. {
  364. $formatter = $this->createStubFormatter();
  365. $this->assertEquals(StubIntlDateFormatter::GREGORIAN, $formatter->getCalendar());
  366. }
  367. public function testGetDateType()
  368. {
  369. $formatter = new StubIntlDateFormatter('en', StubIntlDateFormatter::FULL, StubIntlDateFormatter::NONE);
  370. $this->assertEquals(StubIntlDateFormatter::FULL, $formatter->getDateType());
  371. }
  372. public function testGetErrorCode()
  373. {
  374. $formatter = $this->createStubFormatter();
  375. $this->assertEquals(StubIntlDateFormatter::U_ZERO_ERROR, $formatter->getErrorCode());
  376. }
  377. public function testGetErrorMessage()
  378. {
  379. $formatter = $this->createStubFormatter();
  380. $this->assertEquals(StubIntlDateFormatter::U_ZERO_ERROR_MESSAGE, $formatter->getErrorMessage());
  381. }
  382. public function testGetLocale()
  383. {
  384. $formatter = $this->createStubFormatter();
  385. $this->assertEquals('en', $formatter->getLocale());
  386. }
  387. public function testGetPattern()
  388. {
  389. $formatter = new StubIntlDateFormatter('en', StubIntlDateFormatter::FULL, StubIntlDateFormatter::NONE, 'UTC', StubIntlDateFormatter::GREGORIAN, 'yyyy-MM-dd');
  390. $this->assertEquals('yyyy-MM-dd', $formatter->getPattern());
  391. }
  392. public function testGetTimeType()
  393. {
  394. $formatter = new StubIntlDateFormatter('en', StubIntlDateFormatter::NONE, StubIntlDateFormatter::FULL);
  395. $this->assertEquals(StubIntlDateFormatter::FULL, $formatter->getTimeType());
  396. }
  397. /**
  398. * @expectedException Symfony\Component\Locale\Exception\MethodNotImplementedException
  399. */
  400. public function testIsLenient()
  401. {
  402. $formatter = $this->createStubFormatter();
  403. $formatter->isLenient();
  404. }
  405. /**
  406. * @expectedException Symfony\Component\Locale\Exception\MethodNotImplementedException
  407. */
  408. public function testLocaltime()
  409. {
  410. $formatter = $this->createStubFormatter();
  411. $formatter->localtime('Wednesday, December 31, 1969 4:00:00 PM PT');
  412. }
  413. /**
  414. * @dataProvider parseProvider
  415. */
  416. public function testParseIntl($pattern, $value, $expected)
  417. {
  418. $this->skipIfIntlExtensionIsNotLoaded();
  419. $formatter = $this->createIntlFormatter($pattern);
  420. $this->assertSame($expected, $formatter->parse($value));
  421. }
  422. /**
  423. * @dataProvider parseProvider
  424. */
  425. public function testParseStub($pattern, $value, $expected)
  426. {
  427. $formatter = $this->createStubFormatter($pattern);
  428. $this->assertSame($expected, $formatter->parse($value));
  429. }
  430. public function parseProvider()
  431. {
  432. return array(
  433. // years
  434. array('y-M-d', '1970-1-1', 0),
  435. // TODO: review to support or not this variant
  436. // array('yy-M-d', '70-1-1', 0),
  437. // months
  438. array('y-M-d', '1970-1-1', 0),
  439. array('y-MMM-d', '1970-Jan-1', 0),
  440. array('y-MMMM-d', '1970-January-1', 0),
  441. // 1 char month
  442. array('y-MMMMM-d', '1970-J-1', false),
  443. array('y-MMMMM-d', '1970-S-1', false),
  444. // standalone months
  445. array('y-L-d', '1970-1-1', 0),
  446. array('y-LLL-d', '1970-Jan-1', 0),
  447. array('y-LLLL-d', '1970-January-1', 0),
  448. // standalone 1 char month
  449. array('y-LLLLL-d', '1970-J-1', false),
  450. array('y-LLLLL-d', '1970-S-1', false),
  451. // days
  452. array('y-M-d', '1970-1-1', 0),
  453. array('y-M-dd', '1970-1-01', 0),
  454. array('y-M-ddd', '1970-1-001', 0),
  455. // 12 hours (1-12)
  456. array('y-M-d h', '1970-1-1 1', 3600),
  457. array('y-M-d h', '1970-1-1 10', 36000),
  458. array('y-M-d hh', '1970-1-1 11', 39600),
  459. array('y-M-d hh', '1970-1-1 12', 0),
  460. array('y-M-d hh a', '1970-1-1 0 AM', 0),
  461. array('y-M-d hh a', '1970-1-1 1 AM', 3600),
  462. array('y-M-d hh a', '1970-1-1 10 AM', 36000),
  463. array('y-M-d hh a', '1970-1-1 11 AM', 39600),
  464. array('y-M-d hh a', '1970-1-1 12 AM', 0),
  465. array('y-M-d hh a', '1970-1-1 23 AM', 82800),
  466. array('y-M-d hh a', '1970-1-1 24 AM', 86400),
  467. array('y-M-d hh a', '1970-1-1 0 PM', 43200),
  468. array('y-M-d hh a', '1970-1-1 1 PM', 46800),
  469. array('y-M-d hh a', '1970-1-1 10 PM', 79200),
  470. array('y-M-d hh a', '1970-1-1 11 PM', 82800),
  471. array('y-M-d hh a', '1970-1-1 12 PM', 43200),
  472. array('y-M-d hh a', '1970-1-1 23 PM', 126000),
  473. array('y-M-d hh a', '1970-1-1 24 PM', 129600),
  474. // 12 hours (0-11)
  475. array('y-M-d K', '1970-1-1 1', 3600),
  476. array('y-M-d K', '1970-1-1 10', 36000),
  477. array('y-M-d KK', '1970-1-1 11', 39600),
  478. array('y-M-d KK', '1970-1-1 12', 43200),
  479. array('y-M-d KK a', '1970-1-1 0 AM', 0),
  480. array('y-M-d KK a', '1970-1-1 1 AM', 3600),
  481. array('y-M-d KK a', '1970-1-1 10 AM', 36000),
  482. array('y-M-d KK a', '1970-1-1 11 AM', 39600),
  483. array('y-M-d KK a', '1970-1-1 12 AM', 43200),
  484. array('y-M-d KK a', '1970-1-1 23 AM', 82800),
  485. array('y-M-d KK a', '1970-1-1 24 AM', 86400),
  486. array('y-M-d KK a', '1970-1-1 0 PM', 43200),
  487. array('y-M-d KK a', '1970-1-1 1 PM', 46800),
  488. array('y-M-d KK a', '1970-1-1 10 PM', 79200),
  489. array('y-M-d KK a', '1970-1-1 11 PM', 82800),
  490. array('y-M-d KK a', '1970-1-1 12 PM', 86400),
  491. array('y-M-d KK a', '1970-1-1 23 PM', 126000),
  492. array('y-M-d KK a', '1970-1-1 24 PM', 129600),
  493. // 24 hours (0-23)
  494. array('y-M-d H', '1970-1-1 0', 0),
  495. array('y-M-d H', '1970-1-1 1', 3600),
  496. array('y-M-d H', '1970-1-1 10', 36000),
  497. array('y-M-d HH', '1970-1-1 11', 39600),
  498. array('y-M-d HH', '1970-1-1 12', 43200),
  499. array('y-M-d HH', '1970-1-1 23', 82800),
  500. array('y-M-d HH a', '1970-1-1 0 AM', 0),
  501. array('y-M-d HH a', '1970-1-1 1 AM', 0),
  502. array('y-M-d HH a', '1970-1-1 10 AM', 0),
  503. array('y-M-d HH a', '1970-1-1 11 AM', 0),
  504. array('y-M-d HH a', '1970-1-1 12 AM', 0),
  505. array('y-M-d HH a', '1970-1-1 23 AM', 0),
  506. array('y-M-d HH a', '1970-1-1 24 AM', 0),
  507. array('y-M-d HH a', '1970-1-1 0 PM', 43200),
  508. array('y-M-d HH a', '1970-1-1 1 PM', 43200),
  509. array('y-M-d HH a', '1970-1-1 10 PM', 43200),
  510. array('y-M-d HH a', '1970-1-1 11 PM', 43200),
  511. array('y-M-d HH a', '1970-1-1 12 PM', 43200),
  512. array('y-M-d HH a', '1970-1-1 23 PM', 43200),
  513. array('y-M-d HH a', '1970-1-1 24 PM', 43200),
  514. // 24 hours (1-24)
  515. array('y-M-d k', '1970-1-1 1', 3600),
  516. array('y-M-d k', '1970-1-1 10', 36000),
  517. array('y-M-d kk', '1970-1-1 11', 39600),
  518. array('y-M-d kk', '1970-1-1 12', 43200),
  519. array('y-M-d kk', '1970-1-1 23', 82800),
  520. array('y-M-d kk', '1970-1-1 24', 0),
  521. array('y-M-d kk a', '1970-1-1 0 AM', 0),
  522. array('y-M-d kk a', '1970-1-1 1 AM', 0),
  523. array('y-M-d kk a', '1970-1-1 10 AM', 0),
  524. array('y-M-d kk a', '1970-1-1 11 AM', 0),
  525. array('y-M-d kk a', '1970-1-1 12 AM', 0),
  526. array('y-M-d kk a', '1970-1-1 23 AM', 0),
  527. array('y-M-d kk a', '1970-1-1 24 AM', 0),
  528. array('y-M-d kk a', '1970-1-1 0 PM', 43200),
  529. array('y-M-d kk a', '1970-1-1 1 PM', 43200),
  530. array('y-M-d kk a', '1970-1-1 10 PM', 43200),
  531. array('y-M-d kk a', '1970-1-1 11 PM', 43200),
  532. array('y-M-d kk a', '1970-1-1 12 PM', 43200),
  533. array('y-M-d kk a', '1970-1-1 23 PM', 43200),
  534. array('y-M-d kk a', '1970-1-1 24 PM', 43200),
  535. // minutes
  536. array('y-M-d HH:m', '1970-1-1 0:1', 60),
  537. array('y-M-d HH:mm', '1970-1-1 0:10', 600),
  538. // seconds
  539. array('y-M-d HH:mm:s', '1970-1-1 00:01:1', 61),
  540. array('y-M-d HH:mm:ss', '1970-1-1 00:01:10', 70),
  541. // timezone
  542. array('y-M-d HH:mm:ss zzzz', '1970-1-1 00:00:00 GMT-03:00', 10800),
  543. array('y-M-d HH:mm:ss zzzz', '1970-1-1 00:00:00 GMT-04:00', 14400),
  544. array('y-M-d HH:mm:ss zzzz', '1970-1-1 00:00:00 GMT-00:00', 0),
  545. array('y-M-d HH:mm:ss zzzz', '1970-1-1 00:00:00 GMT+03:00', -10800),
  546. array('y-M-d HH:mm:ss zzzz', '1970-1-1 00:00:00 GMT+04:00', -14400),
  547. array('y-M-d HH:mm:ss zzzz', '1970-1-1 00:00:00 GMT-0300', 10800),
  548. array('y-M-d HH:mm:ss zzzz', '1970-1-1 00:00:00 GMT+0300', -10800),
  549. // a previous timezoned parsing should not change the timezone for the next parsing
  550. array('y-M-d HH:mm:ss', '1970-1-1 00:00:00', 0),
  551. // AM/PM (already covered by hours tests)
  552. array('y-M-d HH:mm:ss a', '1970-1-1 00:00:00 AM', 0),
  553. array('y-M-d HH:mm:ss a', '1970-1-1 00:00:00 PM', 43200),
  554. // regExp metachars in the pattern string
  555. array('y[M-d', '1970[1-1', 0),
  556. array('y[M/d', '1970[1/1', 0),
  557. // quote characters
  558. array("'M'", 'M', 0),
  559. array("'yy'", 'yy', 0),
  560. array("'''yy'", "'yy", 0),
  561. array("''y", "'1970", 0),
  562. array("H 'o'' clock'", "0 o' clock", 0),
  563. );
  564. }
  565. /**
  566. * Just to document the differences between the stub and the intl implementations. The intl can parse
  567. * any of the tested formats alone. The stub does not implement them as it would be needed to add more
  568. * abstraction, passing more context to the transformers objects. Any of the formats are ignored alone
  569. * or with date/time data (years, months, days, hours, minutes and seconds).
  570. *
  571. * Also in intl, format like 'ss E' for '10 2' (2nd day of year + 10 seconds) are added, then we have
  572. * 86,400 seconds (24h * 60min * 60s) + 10 seconds
  573. *
  574. * @dataProvider parseDifferences()
  575. */
  576. public function testParseDifferencesStub($pattern, $value, $stubExpected, $intlExpected)
  577. {
  578. $formatter = $this->createStubFormatter($pattern);
  579. $this->assertSame($stubExpected, $formatter->parse($value));
  580. }
  581. /**
  582. * @dataProvider parseDifferences()
  583. */
  584. public function testParseDifferencesIntl($pattern, $value, $stubExpected, $intlExpected)
  585. {
  586. $this->skipIfIntlExtensionIsNotLoaded();
  587. $this->skipIfICUVersionIsTooOld();
  588. $formatter = $this->createIntlFormatter($pattern);
  589. $this->assertSame($intlExpected, $formatter->parse($value));
  590. }
  591. public function parseDifferences()
  592. {
  593. return array(
  594. // AM/PM, ignored if alone
  595. array('a', 'AM', 0, 0),
  596. array('a', 'PM', 0, 43200),
  597. // day of week
  598. array('E', 'Thu', 0, 0),
  599. array('EE', 'Thu', 0, 0),
  600. array('EEE', 'Thu', 0, 0),
  601. array('EEEE', 'Thursday', 0, 0),
  602. array('EEEEE', 'T', 0, 432000),
  603. array('EEEEEE', 'Thu', 0, 0),
  604. // day of year
  605. array('D', '1', 0, 0),
  606. array('D', '2', 0, 86400),
  607. // quarter
  608. array('Q', '1', 0, 0),
  609. array('QQ', '01', 0, 0),
  610. array('QQQ', 'Q1', 0, 0),
  611. array('QQQQ', '1st quarter', 0, 0),
  612. array('QQQQQ', '1st quarter', 0, 0),
  613. array('Q', '2', 0, 7776000),
  614. array('QQ', '02', 0, 7776000),
  615. array('QQQ', 'Q2', 0, 7776000),
  616. array('QQQQ', '2nd quarter', 0, 7776000),
  617. array('QQQQQ', '2nd quarter', 0, 7776000),
  618. array('q', '1', 0, 0),
  619. array('qq', '01', 0, 0),
  620. array('qqq', 'Q1', 0, 0),
  621. array('qqqq', '1st quarter', 0, 0),
  622. array('qqqqq', '1st quarter', 0, 0),
  623. );
  624. }
  625. public function testParseWithNullPositionValueStub()
  626. {
  627. $position = null;
  628. $formatter = $this->createStubFormatter('y');
  629. $this->assertSame(0, $formatter->parse('1970', $position));
  630. $this->assertNull($position);
  631. }
  632. /**
  633. * @expectedException Symfony\Component\Locale\Exception\MethodArgumentNotImplementedException
  634. */
  635. public function testParseWithNotNullPositionValueStub()
  636. {
  637. $position = 0;
  638. $formatter = $this->createStubFormatter('y');
  639. $this->assertSame(0, $formatter->parse('1970', $position));
  640. }
  641. /**
  642. * @expectedException Symfony\Component\Locale\Exception\MethodNotImplementedException
  643. */
  644. public function testSetCalendar()
  645. {
  646. $formatter = $this->createStubFormatter();
  647. $formatter->setCalendar(StubIntlDateFormatter::GREGORIAN);
  648. }
  649. /**
  650. * @expectedException Symfony\Component\Locale\Exception\MethodNotImplementedException
  651. */
  652. public function testSetLenient()
  653. {
  654. $formatter = $this->createStubFormatter();
  655. $formatter->setLenient(true);
  656. }
  657. public function testSetPattern()
  658. {
  659. $formatter = $this->createStubFormatter();
  660. $formatter->setPattern('yyyy-MM-dd');
  661. $this->assertEquals('yyyy-MM-dd', $formatter->getPattern());
  662. }
  663. /**
  664. * @covers Symfony\Component\Locale\Stub\StubIntlDateFormatter::getTimeZoneId
  665. * @dataProvider setTimeZoneIdProvider()
  666. */
  667. public function testSetTimeZoneIdStub($timeZoneId)
  668. {
  669. $formatter = $this->createStubFormatter();
  670. $formatter->setTimeZoneId($timeZoneId);
  671. $this->assertEquals($timeZoneId, $formatter->getTimeZoneId());
  672. }
  673. /**
  674. * @dataProvider setTimeZoneIdProvider()
  675. */
  676. public function testSetTimeZoneIdIntl($timeZoneId)
  677. {
  678. $this->skipIfIntlExtensionIsNotLoaded();
  679. $formatter = $this->createIntlFormatter();
  680. $formatter->setTimeZoneId($timeZoneId);
  681. $this->assertEquals($timeZoneId, $formatter->getTimeZoneId());
  682. }
  683. public function setTimeZoneIdProvider()
  684. {
  685. return array(
  686. array('UTC'),
  687. array('GMT'),
  688. array('GMT-03:00'),
  689. array('GMT-0300'),
  690. array('Europe/Zurich'),
  691. // When time zone not exists, uses UTC by default
  692. array('Foo/Bar'),
  693. array('GMT+00:AA'),
  694. array('GMT+00AA'),
  695. );
  696. }
  697. /**
  698. * @expectedException Symfony\Component\Locale\Exception\NotImplementedException
  699. */
  700. public function testSetTimeZoneIdWithGmtTimeZoneWithMinutesOffsetStub()
  701. {
  702. $formatter = $this->createStubFormatter();
  703. $formatter->setTimeZoneId('GMT+00:30');
  704. }
  705. public function testSetTimeZoneIdWithGmtTimeZoneWithMinutesOffsetIntl()
  706. {
  707. $this->skipIfIntlExtensionIsNotLoaded();
  708. $formatter = $this->createIntlFormatter();
  709. $formatter->setTimeZoneId('GMT+00:30');
  710. $this->assertEquals('GMT+00:30', $formatter->getTimeZoneId());
  711. }
  712. public function testStaticCreate()
  713. {
  714. $formatter = StubIntlDateFormatter::create('en', StubIntlDateFormatter::MEDIUM, StubIntlDateFormatter::SHORT);
  715. $this->assertInstanceOf('Symfony\Component\Locale\Stub\StubIntlDateFormatter', $formatter);
  716. }
  717. protected function createStubFormatter($pattern = null)
  718. {
  719. return new StubIntlDateFormatter('en', StubIntlDateFormatter::MEDIUM, StubIntlDateFormatter::SHORT, 'UTC', StubIntlDateFormatter::GREGORIAN, $pattern);
  720. }
  721. protected function createIntlFormatter($pattern = null)
  722. {
  723. return new \IntlDateFormatter('en', \IntlDateFormatter::MEDIUM, \IntlDateFormatter::SHORT, 'UTC', \IntlDateFormatter::GREGORIAN, $pattern);
  724. }
  725. protected function createDateTime($timestamp = null, $timeZone = null)
  726. {
  727. $dateTime = new \DateTime();
  728. $dateTime->setTimestamp(null === $timestamp ? time() : $timestamp);
  729. $dateTime->setTimeZone(new \DateTimeZone(null === $timeZone ? date_default_timezone_get() : $timeZone));
  730. return $dateTime;
  731. }
  732. }