TimeTest.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585
  1. <?php
  2. /**
  3. * TimeTest file
  4. *
  5. * CakePHP(tm) Tests <http://book.cakephp.org/2.0/en/development/testing.html>
  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://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests
  14. * @since 1.2.0
  15. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  16. */
  17. namespace Cake\Test\TestCase\Utility;
  18. use Cake\TestSuite\TestCase;
  19. use Cake\Utility\Time;
  20. /**
  21. * TimeTest class
  22. *
  23. */
  24. class TimeTest extends TestCase {
  25. /**
  26. * setUp method
  27. *
  28. * @return void
  29. */
  30. public function setUp() {
  31. parent::setUp();
  32. $this->now = Time::getTestNow();
  33. $this->locale = Time::$defaultLocale;
  34. }
  35. /**
  36. * tearDown method
  37. *
  38. * @return void
  39. */
  40. public function tearDown() {
  41. parent::tearDown();
  42. Time::setTestNow($this->now);
  43. Time::$defaultLocale = $this->locale;
  44. Time::resetToStringFormat();
  45. }
  46. /**
  47. * Restored the original system timezone
  48. *
  49. * @return void
  50. */
  51. protected function _restoreSystemTimezone() {
  52. date_default_timezone_set($this->_systemTimezoneIdentifier);
  53. }
  54. /**
  55. * Provides values and expectations for the toQuarter method
  56. *
  57. * @return array
  58. */
  59. public function toQuarterProvider() {
  60. return [
  61. ['2007-12-25', 4],
  62. ['2007-9-25', 3],
  63. ['2007-3-25', 1],
  64. ['2007-3-25', ['2007-01-01', '2007-03-31'], true],
  65. ['2007-5-25', ['2007-04-01', '2007-06-30'], true],
  66. ['2007-8-25', ['2007-07-01', '2007-09-30'], true],
  67. ['2007-12-25', ['2007-10-01', '2007-12-31'], true],
  68. ];
  69. }
  70. /**
  71. * testToQuarter method
  72. *
  73. * @dataProvider toQuarterProvider
  74. * @return void
  75. */
  76. public function testToQuarter($date, $expected, $range = false) {
  77. $this->assertEquals($expected, (new Time($date))->toQuarter($range));
  78. }
  79. /**
  80. * provider for timeAgoInWords() tests
  81. *
  82. * @return array
  83. */
  84. public static function timeAgoProvider() {
  85. return array(
  86. array('-12 seconds', '12 seconds ago'),
  87. array('-12 minutes', '12 minutes ago'),
  88. array('-2 hours', '2 hours ago'),
  89. array('-1 day', '1 day ago'),
  90. array('-2 days', '2 days ago'),
  91. array('-2 days -3 hours', '2 days, 3 hours ago'),
  92. array('-1 week', '1 week ago'),
  93. array('-2 weeks -2 days', '2 weeks, 2 days ago'),
  94. array('+1 week', '1 week'),
  95. array('+1 week 1 day', '1 week, 1 day'),
  96. array('+2 weeks 2 day', '2 weeks, 2 days'),
  97. array('2007-9-24', 'on 24/9/07'),
  98. array('now', 'just now'),
  99. );
  100. }
  101. /**
  102. * testTimeAgoInWords method
  103. *
  104. * @dataProvider timeAgoProvider
  105. * @return void
  106. */
  107. public function testTimeAgoInWords($input, $expected) {
  108. $time = new Time($input);
  109. $result = $time->timeAgoInWords();
  110. $this->assertEquals($expected, $result);
  111. }
  112. /**
  113. * provider for timeAgo with an end date.
  114. *
  115. * @return void
  116. */
  117. public function timeAgoEndProvider() {
  118. return array(
  119. array(
  120. '+4 months +2 weeks +3 days',
  121. '4 months, 2 weeks, 3 days',
  122. '8 years'
  123. ),
  124. array(
  125. '+4 months +2 weeks +1 day',
  126. '4 months, 2 weeks, 1 day',
  127. '8 years'
  128. ),
  129. array(
  130. '+3 months +2 weeks',
  131. '3 months, 2 weeks',
  132. '8 years'
  133. ),
  134. array(
  135. '+3 months +2 weeks +1 day',
  136. '3 months, 2 weeks, 1 day',
  137. '8 years'
  138. ),
  139. array(
  140. '+1 months +1 week +1 day',
  141. '1 month, 1 week, 1 day',
  142. '8 years'
  143. ),
  144. array(
  145. '+2 months +2 days',
  146. '2 months, 2 days',
  147. '+2 months +2 days'
  148. ),
  149. array(
  150. '+2 months +12 days',
  151. '2 months, 1 week, 5 days',
  152. '3 months'
  153. ),
  154. );
  155. }
  156. /**
  157. * test the end option for timeAgoInWords
  158. *
  159. * @dataProvider timeAgoEndProvider
  160. * @return void
  161. */
  162. public function testTimeAgoInWordsEnd($input, $expected, $end) {
  163. $time = new Time($input);
  164. $result = $time->timeAgoInWords(array('end' => $end));
  165. $this->assertEquals($expected, $result);
  166. }
  167. /**
  168. * test the custom string options for timeAgoInWords
  169. *
  170. * @return void
  171. */
  172. public function testTimeAgoInWordsCustomStrings() {
  173. $time = new Time('-8 years -4 months -2 weeks -3 days');
  174. $result = $time->timeAgoInWords(array(
  175. 'relativeString' => 'at least %s ago',
  176. 'accuracy' => array('year' => 'year'),
  177. 'end' => '+10 years'
  178. ));
  179. $expected = 'at least 8 years ago';
  180. $this->assertEquals($expected, $result);
  181. $time = new Time('+4 months +2 weeks +3 days');
  182. $result = $time->timeAgoInWords(array(
  183. 'absoluteString' => 'exactly on %s',
  184. 'accuracy' => array('year' => 'year'),
  185. 'end' => '+2 months'
  186. ));
  187. $expected = 'exactly on ' . date('j/n/y', strtotime('+4 months +2 weeks +3 days'));
  188. $this->assertEquals($expected, $result);
  189. }
  190. /**
  191. * Test the accuracy option for timeAgoInWords()
  192. *
  193. * @return void
  194. */
  195. public function testTimeAgoInWordsAccuracy() {
  196. $time = new Time('+8 years +4 months +2 weeks +3 days');
  197. $result = $time->timeAgoInWords(array(
  198. 'accuracy' => array('year' => 'year'),
  199. 'end' => '+10 years'
  200. ));
  201. $expected = '8 years';
  202. $this->assertEquals($expected, $result);
  203. $time = new Time('+8 years +4 months +2 weeks +3 days');
  204. $result = $time->timeAgoInWords(array(
  205. 'accuracy' => array('year' => 'month'),
  206. 'end' => '+10 years'
  207. ));
  208. $expected = '8 years, 4 months';
  209. $this->assertEquals($expected, $result);
  210. $time = new Time('+8 years +4 months +2 weeks +3 days');
  211. $result = $time->timeAgoInWords(array(
  212. 'accuracy' => array('year' => 'week'),
  213. 'end' => '+10 years'
  214. ));
  215. $expected = '8 years, 4 months, 2 weeks';
  216. $this->assertEquals($expected, $result);
  217. $time = new Time('+8 years +4 months +2 weeks +3 days');
  218. $result = $time->timeAgoInWords(array(
  219. 'accuracy' => array('year' => 'day'),
  220. 'end' => '+10 years'
  221. ));
  222. $expected = '8 years, 4 months, 2 weeks, 3 days';
  223. $this->assertEquals($expected, $result);
  224. $time = new Time('+1 years +5 weeks');
  225. $result = $time->timeAgoInWords(array(
  226. 'accuracy' => array('year' => 'year'),
  227. 'end' => '+10 years'
  228. ));
  229. $expected = '1 year';
  230. $this->assertEquals($expected, $result);
  231. $time = new Time('+58 minutes');
  232. $result = $time->timeAgoInWords(array(
  233. 'accuracy' => 'hour'
  234. ));
  235. $expected = 'in about an hour';
  236. $this->assertEquals($expected, $result);
  237. $time = new Time('+23 hours');
  238. $result = $time->timeAgoInWords(array(
  239. 'accuracy' => 'day'
  240. ));
  241. $expected = 'in about a day';
  242. $this->assertEquals($expected, $result);
  243. }
  244. /**
  245. * Test the format option of timeAgoInWords()
  246. *
  247. * @return void
  248. */
  249. public function testTimeAgoInWordsWithFormat() {
  250. $time = new Time('2007-9-25');
  251. $result = $time->timeAgoInWords(array('format' => 'YYYY-MM-dd'));
  252. $this->assertEquals('on 2007-09-25', $result);
  253. $time = new Time('2007-9-25');
  254. $result = $time->timeAgoInWords(array('format' => 'YYYY-MM-dd'));
  255. $this->assertEquals('on 2007-09-25', $result);
  256. $time = new Time('+2 weeks +2 days');
  257. $result = $time->timeAgoInWords(array('format' => 'YYYY-MM-dd'));
  258. $this->assertRegExp('/^2 weeks, [1|2] day(s)?$/', $result);
  259. $time = new Time('+2 months +2 days');
  260. $result = $time->timeAgoInWords(array('end' => '1 month', 'format' => 'YYYY-MM-dd'));
  261. $this->assertEquals('on ' . date('Y-m-d', strtotime('+2 months +2 days')), $result);
  262. }
  263. /**
  264. * test timeAgoInWords() with negative values.
  265. *
  266. * @return void
  267. */
  268. public function testTimeAgoInWordsNegativeValues() {
  269. $time = new Time('-2 months -2 days');
  270. $result = $time->timeAgoInWords(array('end' => '3 month'));
  271. $this->assertEquals('2 months, 2 days ago', $result);
  272. $time = new Time('-2 months -2 days');
  273. $result = $time->timeAgoInWords(array('end' => '3 month'));
  274. $this->assertEquals('2 months, 2 days ago', $result);
  275. $time = new Time('-2 months -2 days');
  276. $result = $time->timeAgoInWords(array('end' => '1 month', 'format' => 'YYYY-MM-dd'));
  277. $this->assertEquals('on ' . date('Y-m-d', strtotime('-2 months -2 days')), $result);
  278. $time = new Time('-2 years -5 months -2 days');
  279. $result = $time->timeAgoInWords(array('end' => '3 years'));
  280. $this->assertEquals('2 years, 5 months, 2 days ago', $result);
  281. $time = new Time('-2 weeks -2 days');
  282. $result = $time->timeAgoInWords(array('format' => 'YYYY-MM-dd'));
  283. $this->assertEquals('2 weeks, 2 days ago', $result);
  284. $time = new Time('-3 years -12 months');
  285. $result = $time->timeAgoInWords();
  286. $expected = 'on ' . $time->format('j/n/y');
  287. $this->assertEquals($expected, $result);
  288. $time = new Time('-1 month -1 week -6 days');
  289. $result = $time->timeAgoInWords(
  290. array('end' => '1 year', 'accuracy' => array('month' => 'month'))
  291. );
  292. $this->assertEquals('1 month ago', $result);
  293. $time = new Time('-1 years -2 weeks -3 days');
  294. $result = $time->timeAgoInWords(
  295. array('accuracy' => array('year' => 'year'))
  296. );
  297. $expected = 'on ' . $time->format('j/n/y');
  298. $this->assertEquals($expected, $result);
  299. $time = new Time('-13 months -5 days');
  300. $result = $time->timeAgoInWords(array('end' => '2 years'));
  301. $this->assertEquals('1 year, 1 month, 5 days ago', $result);
  302. $time = new Time('-58 minutes');
  303. $result = $time->timeAgoInWords(array('accuracy' => 'hour'));
  304. $this->assertEquals('about an hour ago', $result);
  305. $time = new Time('-23 hours');
  306. $result = $time->timeAgoInWords(array('accuracy' => 'day'));
  307. $this->assertEquals('about a day ago', $result);
  308. }
  309. /**
  310. * testNice method
  311. *
  312. * @return void
  313. */
  314. public function testNice() {
  315. $time = new Time('2014-04-20 20:00', 'UTC');
  316. $this->assertTimeFormat('Apr 20, 2014, 8:00 PM', $time->nice());
  317. $result = $time->nice('America/New_York');
  318. $this->assertTimeFormat('Apr 20, 2014, 4:00 PM', $result);
  319. $this->assertEquals('UTC', $time->getTimezone()->getName());
  320. $this->assertTimeFormat('20 avr. 2014 20:00', $time->nice(null, 'fr-FR'));
  321. $this->assertTimeFormat('20 avr. 2014 16:00', $time->nice('America/New_York', 'fr-FR'));
  322. }
  323. /**
  324. * testToUnix method
  325. *
  326. * @return void
  327. */
  328. public function testToUnix() {
  329. $time = new Time('2014-04-20 08:00:00');
  330. $this->assertEquals('1397980800', $time->toUnixString());
  331. $time = new Time('2021-12-11 07:00:01');
  332. $this->assertEquals('1639206001', $time->toUnixString());
  333. }
  334. /**
  335. * testIsThisWeek method
  336. *
  337. * @return void
  338. */
  339. public function testIsThisWeek() {
  340. $time = new Time('this sunday');
  341. $this->assertTrue($time->isThisWeek());
  342. $this->assertTrue($time->modify('-1 day')->isThisWeek());
  343. $this->assertFalse($time->modify('-6 days')->isThisWeek());
  344. $time = new Time();
  345. $time->year = $time->year - 1;
  346. $this->assertFalse($time->isThisWeek());
  347. }
  348. /**
  349. * testIsThisMonth method
  350. *
  351. * @return void
  352. */
  353. public function testIsThisMonth() {
  354. $time = new Time();
  355. $this->assertTrue($time->isThisMonth());
  356. $time->year = $time->year + 1;
  357. $this->assertFalse($time->isThisMonth());
  358. $time = new Time();
  359. $this->assertFalse($time->modify('next month')->isThisMonth());
  360. }
  361. /**
  362. * testIsThisYear method
  363. *
  364. * @return void
  365. */
  366. public function testIsThisYear() {
  367. $time = new Time();
  368. $this->assertTrue($time->isThisYear());
  369. $time->year = $time->year + 1;
  370. $this->assertFalse($time->isThisYear());
  371. $thisYear = date('Y');
  372. $time = new Time("$thisYear-01-01 00:00", 'Australia/Sydney');
  373. $now = clone $time;
  374. $now->timezone('UTC');
  375. Time::setTestNow($now);
  376. $this->assertFalse($time->isThisYear());
  377. }
  378. /**
  379. * testWasWithinLast method
  380. *
  381. * @return void
  382. */
  383. public function testWasWithinLast() {
  384. $this->assertTrue((new Time('-1 day'))->wasWithinLast('1 day'));
  385. $this->assertTrue((new Time('-1 week'))->wasWithinLast('1 week'));
  386. $this->assertTrue((new Time('-1 year'))->wasWithinLast('1 year'));
  387. $this->assertTrue((new Time('-1 second'))->wasWithinLast('1 second'));
  388. $this->assertTrue((new Time('-1 day'))->wasWithinLast('1 week'));
  389. $this->assertTrue((new Time('-1 week'))->wasWithinLast('2 week'));
  390. $this->assertTrue((new Time('-1 second'))->wasWithinLast('10 minutes'));
  391. $this->assertTrue((new Time('-1 month'))->wasWithinLast('13 month'));
  392. $this->assertTrue((new Time('-1 seconds'))->wasWithinLast('1 hour'));
  393. $this->assertFalse((new Time('-1 year'))->wasWithinLast('1 second'));
  394. $this->assertFalse((new Time('-1 year'))->wasWithinLast('0 year'));
  395. $this->assertFalse((new Time('-1 weeks'))->wasWithinLast('1 day'));
  396. $this->assertTrue((new Time('-3 days'))->wasWithinLast('5'));
  397. }
  398. /**
  399. * testWasWithinLast method
  400. *
  401. * @return void
  402. */
  403. public function testIsWithinNext() {
  404. $this->assertFalse((new Time('-1 day'))->isWithinNext('1 day'));
  405. $this->assertFalse((new Time('-1 week'))->isWithinNext('1 week'));
  406. $this->assertFalse((new Time('-1 year'))->isWithinNext('1 year'));
  407. $this->assertFalse((new Time('-1 second'))->isWithinNext('1 second'));
  408. $this->assertFalse((new Time('-1 day'))->isWithinNext('1 week'));
  409. $this->assertFalse((new Time('-1 week'))->isWithinNext('2 week'));
  410. $this->assertFalse((new Time('-1 second'))->isWithinNext('10 minutes'));
  411. $this->assertFalse((new Time('-1 month'))->isWithinNext('13 month'));
  412. $this->assertFalse((new Time('-1 seconds'))->isWithinNext('1 hour'));
  413. $this->assertTrue((new Time('+1 day'))->isWithinNext('1 day'));
  414. $this->assertTrue((new Time('+1 week'))->isWithinNext('7 day'));
  415. $this->assertTrue((new Time('+1 second'))->isWithinNext('1 minute'));
  416. $this->assertTrue((new Time('+1 month'))->isWithinNext('1 month'));
  417. }
  418. /**
  419. * test formatting dates taking in account preferred i18n locale file
  420. *
  421. * @return void
  422. */
  423. public function testI18nFormat() {
  424. $time = new Time('Thu Jan 14 13:59:28 2010');
  425. $result = $time->i18nFormat();
  426. $expected = '1/14/10, 1:59 PM';
  427. $this->assertTimeFormat($expected, $result);
  428. $result = $time->i18nFormat(\IntlDateFormatter::FULL, null, 'es-ES');
  429. $expected = 'jueves, 14 de enero de 2010, 13:59:28 (GMT)';
  430. $this->assertTimeFormat($expected, $result);
  431. $format = [\IntlDateFormatter::NONE, \IntlDateFormatter::SHORT];
  432. $result = $time->i18nFormat($format);
  433. $expected = '1:59 PM';
  434. $this->assertTimeFormat($expected, $result);
  435. $result = $time->i18nFormat('HH:mm:ss', 'Australia/Sydney');
  436. $expected = '00:59:28';
  437. $this->assertTimeFormat($expected, $result);
  438. Time::$defaultLocale = 'fr-FR';
  439. $result = $time->i18nFormat(\IntlDateFormatter::FULL);
  440. $expected = 'jeudi 14 janvier 2010 13:59:28 UTC';
  441. $this->assertTimeFormat($expected, $result);
  442. $result = $time->i18nFormat(\IntlDateFormatter::FULL, null, 'es-ES');
  443. $expected = 'jueves, 14 de enero de 2010, 13:59:28 (GMT)';
  444. $this->assertTimeFormat($expected, $result, 'DEfault locale should not be used');
  445. }
  446. /**
  447. * testListTimezones
  448. *
  449. * @return void
  450. */
  451. public function testListTimezones() {
  452. $return = Time::listTimezones();
  453. $this->assertTrue(isset($return['Asia']['Asia/Bangkok']));
  454. $this->assertEquals('Bangkok', $return['Asia']['Asia/Bangkok']);
  455. $this->assertTrue(isset($return['America']['America/Argentina/Buenos_Aires']));
  456. $this->assertEquals('Argentina/Buenos_Aires', $return['America']['America/Argentina/Buenos_Aires']);
  457. $this->assertTrue(isset($return['UTC']['UTC']));
  458. $this->assertFalse(isset($return['Cuba']));
  459. $this->assertFalse(isset($return['US']));
  460. $return = Time::listTimezones('#^Asia/#');
  461. $this->assertTrue(isset($return['Asia']['Asia/Bangkok']));
  462. $this->assertFalse(isset($return['Pacific']));
  463. $return = Time::listTimezones('#^(America|Pacific)/#', null, false);
  464. $this->assertTrue(isset($return['America/Argentina/Buenos_Aires']));
  465. $this->assertTrue(isset($return['Pacific/Tahiti']));
  466. $return = Time::listTimezones(\DateTimeZone::ASIA);
  467. $this->assertTrue(isset($return['Asia']['Asia/Bangkok']));
  468. $this->assertFalse(isset($return['Pacific']));
  469. $return = Time::listTimezones(\DateTimeZone::PER_COUNTRY, 'US', false);
  470. $this->assertTrue(isset($return['Pacific/Honolulu']));
  471. $this->assertFalse(isset($return['Asia/Bangkok']));
  472. }
  473. /**
  474. * Tests that __toString uses the i18n formatter
  475. *
  476. * @return void
  477. */
  478. public function testToString() {
  479. $time = new Time('2014-04-20 22:10');
  480. $this->assertTimeFormat('4/20/14, 10:10 PM', (string)$time);
  481. Time::$defaultLocale = 'fr-FR';
  482. $this->assertTimeFormat('20/04/2014 22:10', (string)$time);
  483. Time::setToStringFormat(\IntlDateFormatter::FULL);
  484. $this->assertTimeFormat('dimanche 20 avril 2014 22:10:00 UTC', (string)$time);
  485. }
  486. /**
  487. * Tests diffForHumans
  488. *
  489. * @return void
  490. */
  491. public function testDiffForHumans() {
  492. $time = new Time('2014-04-20 10:10:10');
  493. $other = new Time('2014-04-27 10:10:10');
  494. $this->assertEquals('1 week ago', $time->diffForHumans($other));
  495. $other = new Time('2014-04-21 09:10:10');
  496. $this->assertEquals('23 hours ago', $time->diffForHumans($other));
  497. $other = new Time('2014-04-13 09:10:10');
  498. $this->assertEquals('1 week', $time->diffForHumans($other));
  499. }
  500. /**
  501. * Cusotm assert to allow for variation in the version of the intl library, where
  502. * some translations contain a few extra commas.
  503. *
  504. * @param string $expected
  505. * @param string $result
  506. * @return void
  507. */
  508. public function assertTimeFormat($expected, $result) {
  509. return $this->assertEquals(str_replace(',', '', $expected), str_replace(',', '',$result));
  510. }
  511. }