TimeTest.php 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865
  1. <?php
  2. /**
  3. * TimeTest file
  4. *
  5. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  6. * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  7. *
  8. * Licensed under The MIT License
  9. * For full copyright and license information, please see the LICENSE.txt
  10. * Redistributions of files must retain the above copyright notice
  11. *
  12. * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  13. * @link http://cakephp.org CakePHP(tm) Project
  14. * @since 1.2.0
  15. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  16. */
  17. namespace Cake\Test\TestCase\I18n;
  18. use Cake\I18n\Time;
  19. use Cake\TestSuite\TestCase;
  20. /**
  21. * TimeTest class
  22. *
  23. */
  24. class TimeTest extends TestCase
  25. {
  26. /**
  27. * setUp method
  28. *
  29. * @return void
  30. */
  31. public function setUp()
  32. {
  33. parent::setUp();
  34. $this->now = Time::getTestNow();
  35. $this->locale = Time::$defaultLocale;
  36. Time::$defaultLocale = 'en_US';
  37. }
  38. /**
  39. * tearDown method
  40. *
  41. * @return void
  42. */
  43. public function tearDown()
  44. {
  45. parent::tearDown();
  46. Time::setTestNow($this->now);
  47. Time::$defaultLocale = $this->locale;
  48. Time::resetToStringFormat();
  49. date_default_timezone_set('UTC');
  50. }
  51. /**
  52. * Restored the original system timezone
  53. *
  54. * @return void
  55. */
  56. protected function _restoreSystemTimezone()
  57. {
  58. date_default_timezone_set($this->_systemTimezoneIdentifier);
  59. }
  60. /**
  61. * Provides values and expectations for the toQuarter method
  62. *
  63. * @return array
  64. */
  65. public function toQuarterProvider()
  66. {
  67. return [
  68. ['2007-12-25', 4],
  69. ['2007-9-25', 3],
  70. ['2007-3-25', 1],
  71. ['2007-3-25', ['2007-01-01', '2007-03-31'], true],
  72. ['2007-5-25', ['2007-04-01', '2007-06-30'], true],
  73. ['2007-8-25', ['2007-07-01', '2007-09-30'], true],
  74. ['2007-12-25', ['2007-10-01', '2007-12-31'], true],
  75. ];
  76. }
  77. /**
  78. * testToQuarter method
  79. *
  80. * @dataProvider toQuarterProvider
  81. * @return void
  82. */
  83. public function testToQuarter($date, $expected, $range = false)
  84. {
  85. $this->assertEquals($expected, (new Time($date))->toQuarter($range));
  86. }
  87. /**
  88. * provider for timeAgoInWords() tests
  89. *
  90. * @return array
  91. */
  92. public static function timeAgoProvider()
  93. {
  94. return [
  95. ['-12 seconds', '12 seconds ago'],
  96. ['-12 minutes', '12 minutes ago'],
  97. ['-2 hours', '2 hours ago'],
  98. ['-1 day', '1 day ago'],
  99. ['-2 days', '2 days ago'],
  100. ['-2 days -3 hours', '2 days, 3 hours ago'],
  101. ['-1 week', '1 week ago'],
  102. ['-2 weeks -2 days', '2 weeks, 2 days ago'],
  103. ['+1 week', '1 week'],
  104. ['+1 week 1 day', '1 week, 1 day'],
  105. ['+2 weeks 2 day', '2 weeks, 2 days'],
  106. ['2007-9-24', 'on 9/24/07'],
  107. ['now', 'just now'],
  108. ];
  109. }
  110. /**
  111. * testTimeAgoInWords method
  112. *
  113. * @dataProvider timeAgoProvider
  114. * @return void
  115. */
  116. public function testTimeAgoInWords($input, $expected)
  117. {
  118. $time = new Time($input);
  119. $result = $time->timeAgoInWords();
  120. $this->assertEquals($expected, $result);
  121. }
  122. /**
  123. * provider for timeAgo with an end date.
  124. *
  125. * @return void
  126. */
  127. public function timeAgoEndProvider()
  128. {
  129. return [
  130. [
  131. '+4 months +2 weeks +3 days',
  132. '4 months, 2 weeks, 3 days',
  133. '8 years'
  134. ],
  135. [
  136. '+4 months +2 weeks +1 day',
  137. '4 months, 2 weeks, 1 day',
  138. '8 years'
  139. ],
  140. [
  141. '+3 months +2 weeks',
  142. '3 months, 2 weeks',
  143. '8 years'
  144. ],
  145. [
  146. '+3 months +2 weeks +1 day',
  147. '3 months, 2 weeks, 1 day',
  148. '8 years'
  149. ],
  150. [
  151. '+1 months +1 week +1 day',
  152. '1 month, 1 week, 1 day',
  153. '8 years'
  154. ],
  155. [
  156. '+2 months +2 days',
  157. '2 months, 2 days',
  158. '+2 months +2 days'
  159. ],
  160. [
  161. '+2 months +12 days',
  162. '2 months, 1 week, 5 days',
  163. '3 months'
  164. ],
  165. ];
  166. }
  167. /**
  168. * test the timezone option for timeAgoInWords
  169. *
  170. * @return void
  171. */
  172. public function testTimeAgoInWordsTimezone()
  173. {
  174. $time = new Time('1990-07-31 20:33:00 UTC');
  175. $result = $time->timeAgoInWords(
  176. [
  177. 'timezone' => 'America/Vancouver',
  178. 'end' => '+1month',
  179. 'format' => 'dd-MM-YYYY HH:mm:ss'
  180. ]
  181. );
  182. $this->assertEquals('on 31-07-1990 13:33:00', $result);
  183. }
  184. /**
  185. * test the end option for timeAgoInWords
  186. *
  187. * @dataProvider timeAgoEndProvider
  188. * @return void
  189. */
  190. public function testTimeAgoInWordsEnd($input, $expected, $end)
  191. {
  192. $time = new Time($input);
  193. $result = $time->timeAgoInWords(['end' => $end]);
  194. $this->assertEquals($expected, $result);
  195. }
  196. /**
  197. * test the custom string options for timeAgoInWords
  198. *
  199. * @return void
  200. */
  201. public function testTimeAgoInWordsCustomStrings()
  202. {
  203. $time = new Time('-8 years -4 months -2 weeks -3 days');
  204. $result = $time->timeAgoInWords([
  205. 'relativeString' => 'at least %s ago',
  206. 'accuracy' => ['year' => 'year'],
  207. 'end' => '+10 years'
  208. ]);
  209. $expected = 'at least 8 years ago';
  210. $this->assertEquals($expected, $result);
  211. $time = new Time('+4 months +2 weeks +3 days');
  212. $result = $time->timeAgoInWords([
  213. 'absoluteString' => 'exactly on %s',
  214. 'accuracy' => ['year' => 'year'],
  215. 'end' => '+2 months'
  216. ]);
  217. $expected = 'exactly on ' . date('n/j/y', strtotime('+4 months +2 weeks +3 days'));
  218. $this->assertEquals($expected, $result);
  219. }
  220. /**
  221. * Test the accuracy option for timeAgoInWords()
  222. *
  223. * @return void
  224. */
  225. public function testTimeAgoInWordsAccuracy()
  226. {
  227. $time = new Time('+8 years +4 months +2 weeks +3 days');
  228. $result = $time->timeAgoInWords([
  229. 'accuracy' => ['year' => 'year'],
  230. 'end' => '+10 years'
  231. ]);
  232. $expected = '8 years';
  233. $this->assertEquals($expected, $result);
  234. $time = new Time('+8 years +4 months +2 weeks +3 days');
  235. $result = $time->timeAgoInWords([
  236. 'accuracy' => ['year' => 'month'],
  237. 'end' => '+10 years'
  238. ]);
  239. $expected = '8 years, 4 months';
  240. $this->assertEquals($expected, $result);
  241. $time = new Time('+8 years +4 months +2 weeks +3 days');
  242. $result = $time->timeAgoInWords([
  243. 'accuracy' => ['year' => 'week'],
  244. 'end' => '+10 years'
  245. ]);
  246. $expected = '8 years, 4 months, 2 weeks';
  247. $this->assertEquals($expected, $result);
  248. $time = new Time('+8 years +4 months +2 weeks +3 days');
  249. $result = $time->timeAgoInWords([
  250. 'accuracy' => ['year' => 'day'],
  251. 'end' => '+10 years'
  252. ]);
  253. $expected = '8 years, 4 months, 2 weeks, 3 days';
  254. $this->assertEquals($expected, $result);
  255. $time = new Time('+1 years +5 weeks');
  256. $result = $time->timeAgoInWords([
  257. 'accuracy' => ['year' => 'year'],
  258. 'end' => '+10 years'
  259. ]);
  260. $expected = '1 year';
  261. $this->assertEquals($expected, $result);
  262. $time = new Time('+58 minutes');
  263. $result = $time->timeAgoInWords([
  264. 'accuracy' => 'hour'
  265. ]);
  266. $expected = 'in about an hour';
  267. $this->assertEquals($expected, $result);
  268. $time = new Time('+23 hours');
  269. $result = $time->timeAgoInWords([
  270. 'accuracy' => 'day'
  271. ]);
  272. $expected = 'in about a day';
  273. $this->assertEquals($expected, $result);
  274. }
  275. /**
  276. * Test the format option of timeAgoInWords()
  277. *
  278. * @return void
  279. */
  280. public function testTimeAgoInWordsWithFormat()
  281. {
  282. $time = new Time('2007-9-25');
  283. $result = $time->timeAgoInWords(['format' => 'yyyy-MM-dd']);
  284. $this->assertEquals('on 2007-09-25', $result);
  285. $time = new Time('2007-9-25');
  286. $result = $time->timeAgoInWords(['format' => 'yyyy-MM-dd']);
  287. $this->assertEquals('on 2007-09-25', $result);
  288. $time = new Time('+2 weeks +2 days');
  289. $result = $time->timeAgoInWords(['format' => 'yyyy-MM-dd']);
  290. $this->assertRegExp('/^2 weeks, [1|2] day(s)?$/', $result);
  291. $time = new Time('+2 months +2 days');
  292. $result = $time->timeAgoInWords(['end' => '1 month', 'format' => 'yyyy-MM-dd']);
  293. $this->assertEquals('on ' . date('Y-m-d', strtotime('+2 months +2 days')), $result);
  294. }
  295. /**
  296. * test timeAgoInWords() with negative values.
  297. *
  298. * @return void
  299. */
  300. public function testTimeAgoInWordsNegativeValues()
  301. {
  302. $time = new Time('-2 months -2 days');
  303. $result = $time->timeAgoInWords(['end' => '3 month']);
  304. $this->assertEquals('2 months, 2 days ago', $result);
  305. $time = new Time('-2 months -2 days');
  306. $result = $time->timeAgoInWords(['end' => '3 month']);
  307. $this->assertEquals('2 months, 2 days ago', $result);
  308. $time = new Time('-2 months -2 days');
  309. $result = $time->timeAgoInWords(['end' => '1 month', 'format' => 'yyyy-MM-dd']);
  310. $this->assertEquals('on ' . date('Y-m-d', strtotime('-2 months -2 days')), $result);
  311. $time = new Time('-2 years -5 months -2 days');
  312. $result = $time->timeAgoInWords(['end' => '3 years']);
  313. $this->assertEquals('2 years, 5 months, 2 days ago', $result);
  314. $time = new Time('-2 weeks -2 days');
  315. $result = $time->timeAgoInWords(['format' => 'yyyy-MM-dd']);
  316. $this->assertEquals('2 weeks, 2 days ago', $result);
  317. $time = new Time('-3 years -12 months');
  318. $result = $time->timeAgoInWords();
  319. $expected = 'on ' . $time->format('n/j/y');
  320. $this->assertEquals($expected, $result);
  321. $time = new Time('-1 month -1 week -6 days');
  322. $result = $time->timeAgoInWords(
  323. ['end' => '1 year', 'accuracy' => ['month' => 'month']]
  324. );
  325. $this->assertEquals('1 month ago', $result);
  326. $time = new Time('-1 years -2 weeks -3 days');
  327. $result = $time->timeAgoInWords(
  328. ['accuracy' => ['year' => 'year']]
  329. );
  330. $expected = 'on ' . $time->format('n/j/y');
  331. $this->assertEquals($expected, $result);
  332. $time = new Time('-13 months -5 days');
  333. $result = $time->timeAgoInWords(['end' => '2 years']);
  334. $this->assertEquals('1 year, 1 month, 5 days ago', $result);
  335. $time = new Time('-58 minutes');
  336. $result = $time->timeAgoInWords(['accuracy' => 'hour']);
  337. $this->assertEquals('about an hour ago', $result);
  338. $time = new Time('-23 hours');
  339. $result = $time->timeAgoInWords(['accuracy' => 'day']);
  340. $this->assertEquals('about a day ago', $result);
  341. }
  342. /**
  343. * testNice method
  344. *
  345. * @return void
  346. */
  347. public function testNice()
  348. {
  349. $time = new Time('2014-04-20 20:00', 'UTC');
  350. $this->assertTimeFormat('Apr 20, 2014, 8:00 PM', $time->nice());
  351. $result = $time->nice('America/New_York');
  352. $this->assertTimeFormat('Apr 20, 2014, 4:00 PM', $result);
  353. $this->assertEquals('UTC', $time->getTimezone()->getName());
  354. $this->assertTimeFormat('20 avr. 2014 20:00', $time->nice(null, 'fr-FR'));
  355. $this->assertTimeFormat('20 avr. 2014 16:00', $time->nice('America/New_York', 'fr-FR'));
  356. }
  357. /**
  358. * testToUnix method
  359. *
  360. * @return void
  361. */
  362. public function testToUnix()
  363. {
  364. $time = new Time('2014-04-20 08:00:00');
  365. $this->assertEquals('1397980800', $time->toUnixString());
  366. $time = new Time('2021-12-11 07:00:01');
  367. $this->assertEquals('1639206001', $time->toUnixString());
  368. }
  369. /**
  370. * testIsThisWeek method
  371. *
  372. * @return void
  373. */
  374. public function testIsThisWeek()
  375. {
  376. $time = new Time('this sunday');
  377. $this->assertTrue($time->isThisWeek());
  378. $this->assertTrue($time->modify('-1 day')->isThisWeek());
  379. $this->assertFalse($time->modify('-6 days')->isThisWeek());
  380. $time = new Time();
  381. $time->year = $time->year - 1;
  382. $this->assertFalse($time->isThisWeek());
  383. }
  384. /**
  385. * testIsThisMonth method
  386. *
  387. * @return void
  388. */
  389. public function testIsThisMonth()
  390. {
  391. $time = new Time();
  392. $this->assertTrue($time->isThisMonth());
  393. $time->year = $time->year + 1;
  394. $this->assertFalse($time->isThisMonth());
  395. $time = new Time();
  396. $this->assertFalse($time->modify('next month')->isThisMonth());
  397. }
  398. /**
  399. * testIsThisYear method
  400. *
  401. * @return void
  402. */
  403. public function testIsThisYear()
  404. {
  405. $time = new Time();
  406. $this->assertTrue($time->isThisYear());
  407. $time->year = $time->year + 1;
  408. $this->assertFalse($time->isThisYear());
  409. $thisYear = date('Y');
  410. $time = new Time("$thisYear-01-01 00:00", 'Australia/Sydney');
  411. $now = clone $time;
  412. $now->timezone('UTC');
  413. Time::setTestNow($now);
  414. $this->assertFalse($time->isThisYear());
  415. }
  416. /**
  417. * testWasWithinLast method
  418. *
  419. * @return void
  420. */
  421. public function testWasWithinLast()
  422. {
  423. $this->assertTrue((new Time('-1 day'))->wasWithinLast('1 day'));
  424. $this->assertTrue((new Time('-1 week'))->wasWithinLast('1 week'));
  425. $this->assertTrue((new Time('-1 year'))->wasWithinLast('1 year'));
  426. $this->assertTrue((new Time('-1 second'))->wasWithinLast('1 second'));
  427. $this->assertTrue((new Time('-1 day'))->wasWithinLast('1 week'));
  428. $this->assertTrue((new Time('-1 week'))->wasWithinLast('2 week'));
  429. $this->assertTrue((new Time('-1 second'))->wasWithinLast('10 minutes'));
  430. $this->assertTrue((new Time('-1 month'))->wasWithinLast('13 month'));
  431. $this->assertTrue((new Time('-1 seconds'))->wasWithinLast('1 hour'));
  432. $this->assertFalse((new Time('-1 year'))->wasWithinLast('1 second'));
  433. $this->assertFalse((new Time('-1 year'))->wasWithinLast('0 year'));
  434. $this->assertFalse((new Time('-1 weeks'))->wasWithinLast('1 day'));
  435. $this->assertTrue((new Time('-3 days'))->wasWithinLast('5'));
  436. }
  437. /**
  438. * testWasWithinLast method
  439. *
  440. * @return void
  441. */
  442. public function testIsWithinNext()
  443. {
  444. $this->assertFalse((new Time('-1 day'))->isWithinNext('1 day'));
  445. $this->assertFalse((new Time('-1 week'))->isWithinNext('1 week'));
  446. $this->assertFalse((new Time('-1 year'))->isWithinNext('1 year'));
  447. $this->assertFalse((new Time('-1 second'))->isWithinNext('1 second'));
  448. $this->assertFalse((new Time('-1 day'))->isWithinNext('1 week'));
  449. $this->assertFalse((new Time('-1 week'))->isWithinNext('2 week'));
  450. $this->assertFalse((new Time('-1 second'))->isWithinNext('10 minutes'));
  451. $this->assertFalse((new Time('-1 month'))->isWithinNext('13 month'));
  452. $this->assertFalse((new Time('-1 seconds'))->isWithinNext('1 hour'));
  453. $this->assertTrue((new Time('+1 day'))->isWithinNext('1 day'));
  454. $this->assertTrue((new Time('+1 week'))->isWithinNext('7 day'));
  455. $this->assertTrue((new Time('+1 second'))->isWithinNext('1 minute'));
  456. $this->assertTrue((new Time('+1 month'))->isWithinNext('1 month'));
  457. }
  458. /**
  459. * test formatting dates taking in account preferred i18n locale file
  460. *
  461. * @return void
  462. */
  463. public function testI18nFormat()
  464. {
  465. $time = new Time('Thu Jan 14 13:59:28 2010');
  466. $result = $time->i18nFormat();
  467. $expected = '1/14/10, 1:59 PM';
  468. $this->assertTimeFormat($expected, $result);
  469. $result = $time->i18nFormat(\IntlDateFormatter::FULL, null, 'es-ES');
  470. $expected = 'jueves, 14 de enero de 2010, 13:59:28 (GMT)';
  471. $this->assertTimeFormat($expected, $result);
  472. $format = [\IntlDateFormatter::NONE, \IntlDateFormatter::SHORT];
  473. $result = $time->i18nFormat($format);
  474. $expected = '1:59 PM';
  475. $this->assertTimeFormat($expected, $result);
  476. $result = $time->i18nFormat('HH:mm:ss', 'Australia/Sydney');
  477. $expected = '00:59:28';
  478. $this->assertTimeFormat($expected, $result);
  479. Time::$defaultLocale = 'fr-FR';
  480. $result = $time->i18nFormat(\IntlDateFormatter::FULL);
  481. $expected = 'jeudi 14 janvier 2010 13:59:28 UTC';
  482. $this->assertTimeFormat($expected, $result);
  483. $result = $time->i18nFormat(\IntlDateFormatter::FULL, null, 'es-ES');
  484. $expected = 'jueves, 14 de enero de 2010, 13:59:28 (GMT)';
  485. $this->assertTimeFormat($expected, $result, 'Default locale should not be used');
  486. $result = $time->i18nFormat(\IntlDateFormatter::FULL, null, 'fa-SA');
  487. $expected = 'پنجشنبه ۱۴ ژانویهٔ ۲۰۱۰، ساعت ۱۳:۵۹:۲۸ (GMT)';
  488. $this->assertTimeFormat($expected, $result, 'fa-SA locale should be used');
  489. $result = $time->i18nFormat(\IntlDateFormatter::FULL, null, 'en-IR@calendar=persian');
  490. $expected = 'Thursday, Dey 24, 1388 at 1:59:28 PM GMT';
  491. $this->assertTimeFormat($expected, $result);
  492. $result = $time->i18nFormat(\IntlDateFormatter::FULL, null, 'ps-IR@calendar=persian');
  493. $expected = 'پنجشنبه د ۱۳۸۸ د مرغومی ۲۴ ۱۳:۵۹:۲۸ (GMT)';
  494. $this->assertTimeFormat($expected, $result);
  495. $result = $time->i18nFormat(\IntlDateFormatter::FULL, null, 'en-KW@calendar=islamic');
  496. $expected = 'Thursday, Muharram 29, 1431 at 1:59:28 PM GMT';
  497. $this->assertTimeFormat($expected, $result);
  498. $result = $time->i18nFormat(\IntlDateFormatter::FULL, 'Asia/Tokyo', 'ja-JP@calendar=japanese');
  499. $expected = '平成22年1月14日木曜日 22時59分28秒 日本標準時';
  500. $this->assertTimeFormat($expected, $result);
  501. $result = $time->i18nFormat(\IntlDateFormatter::FULL, 'Asia/Tokyo', 'ja-JP@calendar=japanese');
  502. $expected = '平成22年1月14日木曜日 22時59分28秒 日本標準時';
  503. $this->assertTimeFormat($expected, $result);
  504. }
  505. /**
  506. * test formatting dates with offset style timezone
  507. *
  508. * @see https://github.com/facebook/hhvm/issues/3637
  509. * @return void
  510. */
  511. public function testI18nFormatWithOffsetTimezone()
  512. {
  513. $time = new Time('2014-01-01T00:00:00+00');
  514. $result = $time->i18nFormat(\IntlDateFormatter::FULL);
  515. $expected = 'Wednesday January 1 2014 12:00:00 AM GMT';
  516. $this->assertTimeFormat($expected, $result);
  517. $time = new Time('2014-01-01T00:00:00+09');
  518. $result = $time->i18nFormat(\IntlDateFormatter::FULL);
  519. $expected = 'Wednesday January 1 2014 12:00:00 AM GMT+09:00';
  520. $this->assertTimeFormat($expected, $result);
  521. $time = new Time('2014-01-01T00:00:00-01:30');
  522. $result = $time->i18nFormat(\IntlDateFormatter::FULL);
  523. $expected = 'Wednesday January 1 2014 12:00:00 AM GMT-01:30';
  524. $this->assertTimeFormat($expected, $result);
  525. }
  526. /**
  527. * testListTimezones
  528. *
  529. * @return void
  530. */
  531. public function testListTimezones()
  532. {
  533. $return = Time::listTimezones();
  534. $this->assertTrue(isset($return['Asia']['Asia/Bangkok']));
  535. $this->assertEquals('Bangkok', $return['Asia']['Asia/Bangkok']);
  536. $this->assertTrue(isset($return['America']['America/Argentina/Buenos_Aires']));
  537. $this->assertEquals('Argentina/Buenos_Aires', $return['America']['America/Argentina/Buenos_Aires']);
  538. $this->assertTrue(isset($return['UTC']['UTC']));
  539. $this->assertFalse(isset($return['Cuba']));
  540. $this->assertFalse(isset($return['US']));
  541. $return = Time::listTimezones('#^Asia/#');
  542. $this->assertTrue(isset($return['Asia']['Asia/Bangkok']));
  543. $this->assertFalse(isset($return['Pacific']));
  544. $return = Time::listTimezones(null, null, ['abbr' => true]);
  545. $this->assertTrue(isset($return['Asia']['Asia/Jakarta']));
  546. $this->assertEquals('Jakarta - WIB', $return['Asia']['Asia/Jakarta']);
  547. $this->assertEquals('Regina - CST', $return['America']['America/Regina']);
  548. $return = Time::listTimezones(null, null, [
  549. 'abbr' => true,
  550. 'before' => ' (',
  551. 'after' => ')',
  552. ]);
  553. $this->assertEquals('Jayapura (WIT)', $return['Asia']['Asia/Jayapura']);
  554. $this->assertEquals('Regina (CST)', $return['America']['America/Regina']);
  555. $return = Time::listTimezones('#^(America|Pacific)/#', null, false);
  556. $this->assertTrue(isset($return['America/Argentina/Buenos_Aires']));
  557. $this->assertTrue(isset($return['Pacific/Tahiti']));
  558. $return = Time::listTimezones(\DateTimeZone::ASIA);
  559. $this->assertTrue(isset($return['Asia']['Asia/Bangkok']));
  560. $this->assertFalse(isset($return['Pacific']));
  561. $return = Time::listTimezones(\DateTimeZone::PER_COUNTRY, 'US', false);
  562. $this->assertTrue(isset($return['Pacific/Honolulu']));
  563. $this->assertFalse(isset($return['Asia/Bangkok']));
  564. }
  565. /**
  566. * Tests that __toString uses the i18n formatter
  567. *
  568. * @return void
  569. */
  570. public function testToString()
  571. {
  572. $time = new Time('2014-04-20 22:10');
  573. Time::$defaultLocale = 'fr-FR';
  574. Time::setToStringFormat(\IntlDateFormatter::FULL);
  575. $this->assertTimeFormat('dimanche 20 avril 2014 22:10:00 UTC', (string)$time);
  576. }
  577. /**
  578. * Data provider for invalid values.
  579. *
  580. * @return array
  581. */
  582. public function invalidDataProvider()
  583. {
  584. return [
  585. [null],
  586. [false],
  587. [''],
  588. ];
  589. }
  590. /**
  591. * Test that invalid datetime values do not trigger errors.
  592. *
  593. * @dataProvider invalidDataProvider
  594. * @return void
  595. */
  596. public function testToStringInvalid($value)
  597. {
  598. $time = new Time($value);
  599. $this->assertInternalType('string', (string)$time);
  600. $this->assertNotEmpty((string)$time);
  601. }
  602. /**
  603. * These invalid values are not invalid on windows :(
  604. *
  605. * @return void
  606. */
  607. public function testToStringInvalidZeros()
  608. {
  609. $this->skipIf(DS === '\\', 'All zeros are valid on windows.');
  610. $this->skipIf(PHP_INT_SIZE === 4, 'IntlDateFormatter throws exceptions on 32-bit systems');
  611. $time = new Time('0000-00-00');
  612. $this->assertInternalType('string', (string)$time);
  613. $this->assertNotEmpty((string)$time);
  614. $time = new Time('0000-00-00 00:00:00');
  615. $this->assertInternalType('string', (string)$time);
  616. $this->assertNotEmpty((string)$time);
  617. }
  618. /**
  619. * Tests diffForHumans
  620. *
  621. * @return void
  622. */
  623. public function testDiffForHumans()
  624. {
  625. $time = new Time('2014-04-20 10:10:10');
  626. $other = new Time('2014-04-27 10:10:10');
  627. $this->assertEquals('1 week ago', $time->diffForHumans($other));
  628. $other = new Time('2014-04-21 09:10:10');
  629. $this->assertEquals('23 hours ago', $time->diffForHumans($other));
  630. $other = new Time('2014-04-13 09:10:10');
  631. $this->assertEquals('1 week', $time->diffForHumans($other));
  632. }
  633. /**
  634. * Tests encoding a Time object as json
  635. *
  636. * @return void
  637. */
  638. public function testJsonEnconde()
  639. {
  640. $time = new Time('2014-04-20 10:10:10');
  641. $this->assertEquals('"2014-04-20T10:10:10+0000"', json_encode($time));
  642. Time::setJsonEncodeFormat('yyyy-MM-dd HH:mm:ss');
  643. $this->assertEquals('"2014-04-20 10:10:10"', json_encode($time));
  644. }
  645. /**
  646. * Tests debugInfo
  647. *
  648. * @return void
  649. */
  650. public function testDebugInfo()
  651. {
  652. $time = new Time('2014-04-20 10:10:10');
  653. $expected = [
  654. 'time' => '2014-04-20T10:10:10+0000',
  655. 'timezone' => 'UTC',
  656. 'fixedNowTime' => Time::getTestNow()->toISO8601String()
  657. ];
  658. $this->assertEquals($expected, $time->__debugInfo());
  659. }
  660. /**
  661. * Tests parsing a string into a Time object based on the locale format.
  662. *
  663. * @return void
  664. */
  665. public function testParseDateTime()
  666. {
  667. $time = Time::parseDateTime('10/13/2013 12:54am');
  668. $this->assertNotNull($time);
  669. $this->assertEquals('2013-10-13 00:54', $time->format('Y-m-d H:i'));
  670. Time::$defaultLocale = 'fr-FR';
  671. $time = Time::parseDateTime('13 10, 2013 12:54');
  672. $this->assertNotNull($time);
  673. $this->assertEquals('2013-10-13 12:54', $time->format('Y-m-d H:i'));
  674. $time = Time::parseDateTime('13 foo 10 2013 12:54');
  675. $this->assertNull($time);
  676. }
  677. /**
  678. * Tests parsing a string into a Time object based on the locale format.
  679. *
  680. * @return void
  681. */
  682. public function testParseDate()
  683. {
  684. $time = Time::parseDate('10/13/2013 12:54am');
  685. $this->assertNotNull($time);
  686. $this->assertEquals('2013-10-13 00:00', $time->format('Y-m-d H:i'));
  687. $time = Time::parseDate('10/13/2013');
  688. $this->assertNotNull($time);
  689. $this->assertEquals('2013-10-13 00:00', $time->format('Y-m-d H:i'));
  690. Time::$defaultLocale = 'fr-FR';
  691. $time = Time::parseDate('13 10, 2013 12:54');
  692. $this->assertNotNull($time);
  693. $this->assertEquals('2013-10-13 00:00', $time->format('Y-m-d H:i'));
  694. $time = Time::parseDate('13 foo 10 2013 12:54');
  695. $this->assertNull($time);
  696. $time = Time::parseDate('13 10, 2013', 'dd M, y');
  697. $this->assertNotNull($time);
  698. $this->assertEquals('2013-10-13', $time->format('Y-m-d'));
  699. }
  700. /**
  701. * Tests parsing times using the parseTime function
  702. *
  703. * @return void
  704. */
  705. public function testParseTime()
  706. {
  707. $time = Time::parseTime('12:54am');
  708. $this->assertNotNull($time);
  709. $this->assertEquals('00:54:00', $time->format('H:i:s'));
  710. Time::$defaultLocale = 'fr-FR';
  711. $time = Time::parseTime('23:54');
  712. $this->assertNotNull($time);
  713. $this->assertEquals('23:54:00', $time->format('H:i:s'));
  714. $time = Time::parseTime('31c2:54');
  715. $this->assertNull($time);
  716. }
  717. /**
  718. * Tests that parsing a date respects de default timezone in PHP.
  719. *
  720. * @return void
  721. */
  722. public function testParseDateDifferentTimezone()
  723. {
  724. date_default_timezone_set('Europe/Paris');
  725. Time::$defaultLocale = 'fr-FR';
  726. $result = Time::parseDate('12/03/2015');
  727. $this->assertEquals('2015-03-12', $result->format('Y-m-d'));
  728. $this->assertEquals(new \DateTimeZone('Europe/Paris'), $result->tz);
  729. }
  730. /**
  731. * Tests the "from now" time calculation.
  732. *
  733. * @return void
  734. */
  735. public function testFromNow()
  736. {
  737. $date = clone $this->now;
  738. $date->modify('-1 year');
  739. $date->modify('-6 days');
  740. $date->modify('-51 seconds');
  741. $interval = Time::fromNow($date);
  742. $result = $interval->format("%y %m %d %H %i %s");
  743. $this->assertEquals($result, '1 0 6 00 0 51');
  744. }
  745. /**
  746. * Custom assert to allow for variation in the version of the intl library, where
  747. * some translations contain a few extra commas.
  748. *
  749. * @param string $expected
  750. * @param string $result
  751. * @return void
  752. */
  753. public function assertTimeFormat($expected, $result, $message = "")
  754. {
  755. $expected = str_replace([',', '(', ')', ' at', ' م.', ' ه‍.ش.', ' AP', ' AH', ' SAKA', 'à '], '', $expected);
  756. $expected = str_replace([' '], ' ', $expected);
  757. $result = str_replace([',', '(', ')', ' at', ' م.', ' ه‍.ش.', ' AP', ' AH', ' SAKA', 'à '], '', $result);
  758. $result = str_replace(['گرینویچ'], 'GMT', $result);
  759. $result = str_replace([' '], ' ', $result);
  760. return $this->assertSame($expected, $result, $message);
  761. }
  762. }