DateTimeHelperTest.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. <?php
  2. namespace fphammerle\helpers\tests;
  3. use \DateInterval as DI;
  4. use \DatePeriod as DP;
  5. use \DateTime as DT;
  6. use \fphammerle\helpers\DateTimeHelper;
  7. class DateTimeHelperTest extends \PHPUnit_Framework_TestCase
  8. {
  9. public function timestampToDateTimeProvider()
  10. {
  11. return [
  12. [null, null],
  13. [0, new DT('1970-01-01 00:00:00', new \DateTimeZone('UTC'))],
  14. [0, new DT('1970-01-01 01:00:00', new \DateTimeZone('Europe/Vienna'))],
  15. [1234567890, new DT('2009-02-13 23:31:30', new \DateTimeZone('UTC'))],
  16. [1234567890, new DT('2009-02-14 00:31:30', new \DateTimeZone('Europe/Vienna'))],
  17. [-3600, new DT('1970-01-01 00:00:00', new \DateTimeZone('Europe/Vienna'))],
  18. ];
  19. }
  20. /**
  21. * @dataProvider timestampToDateTimeProvider
  22. */
  23. public function testTimestampToDateTime($timestamp, $expected_datetime)
  24. {
  25. $generated_datetime = DateTimeHelper::timestampToDateTime($timestamp);
  26. $this->assertEquals($expected_datetime, $generated_datetime);
  27. }
  28. public function timestampToDateTimeDefaultTimezoneProvider()
  29. {
  30. return [
  31. ['UTC', 100],
  32. ['Europe/Vienna', 0],
  33. ['Europe/Vienna', -100],
  34. ['Europe/Vienna', 100],
  35. ['Europe/London', 3600],
  36. ['US/Pacific', 3600],
  37. ];
  38. }
  39. /**
  40. * @dataProvider timestampToDateTimeDefaultTimezoneProvider
  41. */
  42. public function testTimestampToDateTimeDefaultTimezone($timezone, $timestamp)
  43. {
  44. date_default_timezone_set($timezone);
  45. $generated_datetime = DateTimeHelper::timestampToDateTime($timestamp);
  46. $this->assertSame($timestamp, $generated_datetime->getTimestamp());
  47. }
  48. public function parseProvider()
  49. {
  50. return [
  51. // null
  52. [null, 'UTC', null],
  53. [null, 'US/Pacific', null],
  54. // date
  55. ['2016-08-02', 'UTC', new DP(new DT('2016-08-02T00:00:00Z'), new DI('P1D'), 0)],
  56. ['2016-08-02', 'US/Pacific', new DP(new DT('2016-08-02T00:00:00-07:00'), new DI('P1D'), 0)],
  57. ['2016-08-02', 'US/Pacific', new DP(new DT('2016-08-02T07:00:00Z'), new DI('P1D'), 0)],
  58. ['2016-08-02+02:00', 'UTC', new DP(new DT('2016-08-02T00:00:00+02:00'), new DI('P1D'), 0)],
  59. ['2016-08-02+02:00', 'UTC', new DP(new DT('2016-08-01T22:00:00Z'), new DI('P1D'), 0)],
  60. // minute without timezone
  61. ['2016-08-02 15:52', 'UTC', new DP(new DT('2016-08-02T15:52:00Z'), new DI('PT1M'), 0)],
  62. ['2016-08-02T15:52', 'UTC', new DP(new DT('2016-08-02T15:52:00Z'), new DI('PT1M'), 0)],
  63. ['2016-08-02T15:52', 'Europe/Vienna', new DP(new DT('2016-08-02T15:52:00+02:00'), new DI('PT1M'), 0)],
  64. ['2016-01-02T15:52', 'US/Pacific', new DP(new DT('2016-01-02T15:52:00-08:00'), new DI('PT1M'), 0)],
  65. // minute with timezone
  66. ['2016-08-02 15:52Z', 'US/Pacific', new DP(new DT('2016-08-02T15:52:00Z'), new DI('PT1M'), 0)],
  67. ['2016-08-02T15:52Z', 'Europe/Vienna', new DP(new DT('2016-08-02T15:52:00Z'), new DI('PT1M'), 0)],
  68. ['2016-01-02T15:52+00:00', 'Europe/Vienna', new DP(new DT('2016-01-02T15:52:00Z'), new DI('PT1M'), 0)],
  69. ['2016-01-02T15:52+02:00', 'US/Pacific', new DP(new DT('2016-01-02T15:52:00+02:00'), new DI('PT1M'), 0)],
  70. ['2016-01-02T15:52-08:00', 'UTC', new DP(new DT('2016-01-02T15:52:00-08:00'), new DI('PT1M'), 0)],
  71. // second without timezone
  72. ['2016-08-02 15:52:13', 'UTC', new DP(new DT('2016-08-02T15:52:13Z'), new DI('PT1S'), 0)],
  73. ['2016-08-02T15:52:13', 'UTC', new DP(new DT('2016-08-02T15:52:13Z'), new DI('PT1S'), 0)],
  74. ['2016-08-02T15:52:13', 'Europe/Vienna', new DP(new DT('2016-08-02T15:52:13+02:00'), new DI('PT1S'), 0)],
  75. ['2016-01-02T15:52:00', 'US/Pacific', new DP(new DT('2016-01-02T15:52:00-08:00'), new DI('PT1S'), 0)],
  76. // second with timezone
  77. ['2016-08-02 15:52:13Z', 'US/Pacific', new DP(new DT('2016-08-02T15:52:13Z'), new DI('PT1S'), 0)],
  78. ['2016-08-02T15:52:13Z', 'Europe/Vienna', new DP(new DT('2016-08-02T15:52:13Z'), new DI('PT1S'), 0)],
  79. ['2016-01-02T15:52:13+00:00', 'Europe/Vienna', new DP(new DT('2016-01-02T15:52:13Z'), new DI('PT1S'), 0)],
  80. ['2016-01-02T15:52:13+02:00', 'US/Pacific', new DP(new DT('2016-01-02T15:52:13+02:00'), new DI('PT1S'), 0)],
  81. ['2016-01-02T15:52:13-08:00', 'UTC', new DP(new DT('2016-01-02T15:52:13-08:00'), new DI('PT1S'), 0)],
  82. ];
  83. }
  84. /**
  85. * @dataProvider parseProvider
  86. */
  87. public function testParse($text, $timezone, $expected)
  88. {
  89. date_default_timezone_set($timezone);
  90. $this->assertEquals($expected, DateTimeHelper::parse($text));
  91. }
  92. public function parseInvalidArgumentProvider()
  93. {
  94. return [
  95. [' '],
  96. [''],
  97. ['2016--12'],
  98. ['2016-10-12 08:20#01'],
  99. [1],
  100. [false],
  101. ];
  102. }
  103. /**
  104. * @dataProvider parseInvalidArgumentProvider
  105. * @expectedException \InvalidArgumentException
  106. */
  107. public function testParseInvalidArgument($text)
  108. {
  109. DateTimeHelper::parse($text);
  110. }
  111. public function parseGetStartProvider()
  112. {
  113. return [
  114. [null, 'UTC', null],
  115. [null, 'US/Pacific', null],
  116. ['2016-08-02', 'UTC', new DT('2016-08-02T00:00:00Z')],
  117. ['2016-08-02', 'Europe/Vienna', new DT('2016-08-02T00:00:00+02:00')],
  118. ['2016-08-02', 'Europe/Vienna', new DT('2016-08-01T22:00:00Z')],
  119. ['2016-08-02 15:52:13', 'UTC', new DT('2016-08-02T15:52:13Z')],
  120. ['2016-08-02 15:52:13', 'Europe/Vienna', new DT('2016-08-02T15:52:13+02:00')],
  121. ['2016-08-02 15:52:13', 'Europe/Vienna', new DT('2016-08-02T13:52:13Z')],
  122. ['2016-08-02T15:52:13', 'US/Pacific', new DT('2016-08-02T15:52:13-07:00')],
  123. ];
  124. }
  125. /**
  126. * @dataProvider parseGetStartProvider
  127. */
  128. public function testParseGetStart($text, $timezone, $expected)
  129. {
  130. date_default_timezone_set($timezone);
  131. $this->assertEquals($expected, DateTimeHelper::parseGetStart($text));
  132. }
  133. public function parseGetStartInvalidArgumentProvider()
  134. {
  135. return [
  136. [' '],
  137. [''],
  138. ['2016--12'],
  139. ['2016-10-12 08:20#01'],
  140. [1],
  141. [false],
  142. ];
  143. }
  144. /**
  145. * @dataProvider parseGetStartInvalidArgumentProvider
  146. * @expectedException \InvalidArgumentException
  147. */
  148. public function testParseGetStartInvalidArgument($text)
  149. {
  150. DateTimeHelper::parseGetStart($text);
  151. }
  152. public function deinvertIntervalProvider()
  153. {
  154. return [
  155. [
  156. DI::createFromDateString('-2 years'),
  157. ['y' => -2, 'm' => 0, 'd' => 0, 'h' => 0, 'i' => 0, 's' => 0],
  158. ],
  159. [
  160. DI::createFromDateString('-2 months'),
  161. ['y' => 0, 'm' => -2, 'd' => 0, 'h' => 0, 'i' => 0, 's' => 0],
  162. ],
  163. [
  164. DI::createFromDateString('-2 days'),
  165. ['y' => 0, 'm' => 0, 'd' => -2, 'h' => 0, 'i' => 0, 's' => 0],
  166. ],
  167. [
  168. DI::createFromDateString('-2 hours'),
  169. ['y' => 0, 'm' => 0, 'd' => 0, 'h' => -2, 'i' => 0, 's' => 0],
  170. ],
  171. [
  172. DI::createFromDateString('-2 minutes'),
  173. ['y' => 0, 'm' => 0, 'd' => 0, 'h' => 0, 'i' => -2, 's' => 0],
  174. ],
  175. [
  176. DI::createFromDateString('-2 seconds'),
  177. ['y' => 0, 'm' => 0, 'd' => 0, 'h' => 0, 'i' => 0, 's' => -2],
  178. ],
  179. [
  180. (new DT('2016-08'))->diff(new DT('2016-07')),
  181. ['y' => 0, 'm' => -1, 'd' => 0, 'h' => 0, 'i' => 0, 's' => 0],
  182. ],
  183. [
  184. (new DT('2016-08-03'))->diff(new DT('2016-07-03')),
  185. ['y' => 0, 'm' => -1, 'd' => 0, 'h' => 0, 'i' => 0, 's' => 0],
  186. ],
  187. [
  188. (new DT('2016-07-03'))->diff(new DT('2016-08-03')),
  189. ['y' => 0, 'm' => 1, 'd' => 0, 'h' => 0, 'i' => 0, 's' => 0],
  190. ],
  191. [
  192. (new DT('2016-08-04'))->diff(new DT('2016-07-03')),
  193. ['y' => 0, 'm' => -1, 'd' => -1, 'h' => 0, 'i' => 0, 's' => 0],
  194. ],
  195. [
  196. (new DT('2016-07-03'))->diff(new DT('2016-08-04')),
  197. ['y' => 0, 'm' => 1, 'd' => 1, 'h' => 0, 'i' => 0, 's' => 0],
  198. ],
  199. [
  200. (new DT('2016-08-02'))->diff(new DT('2016-07-03')),
  201. ['y' => 0, 'm' => 0, 'd' => -30, 'h' => 0, 'i' => 0, 's' => 0],
  202. ],
  203. [
  204. (new DT('2016-07-03'))->diff(new DT('2016-08-02')),
  205. ['y' => 0, 'm' => 0, 'd' => 30, 'h' => 0, 'i' => 0, 's' => 0],
  206. ],
  207. [
  208. (new DT('2016-08-04 18:10:02'))->diff(new DT('2016-07-03 14:13:03')),
  209. ['y' => 0, 'm' => -1, 'd' => -1, 'h' => -3, 'i' => -56, 's' => -59],
  210. ],
  211. [
  212. (new DT('2016-07-03 14:13:03'))->diff(new DT('2016-08-04 18:10:02')),
  213. ['y' => 0, 'm' => 1, 'd' => 1, 'h' => 3, 'i' => 56, 's' => 59],
  214. ],
  215. ];
  216. }
  217. /**
  218. * @dataProvider deinvertIntervalProvider
  219. */
  220. public function testDeinvertInterval($source, $expected_attr)
  221. {
  222. // \DateInterval does not implement clone.
  223. // @see https://bugs.php.net/bug.php?id=50559
  224. $source_copy = unserialize(serialize($source));
  225. $deinverted = DateTimeHelper::deinvertInterval($source_copy);
  226. $this->assertEquals($source, $source_copy);
  227. $this->assertEquals(0, $deinverted->invert);
  228. foreach($expected_attr as $k => $v) {
  229. $this->assertSame($v, $deinverted->$k);
  230. }
  231. }
  232. public function intervalToIsoProvider()
  233. {
  234. return [
  235. [null, null],
  236. ];
  237. }
  238. /**
  239. * @dataProvider intervalToIsoProvider
  240. */
  241. public function testIntervalToIso($interval, $iso)
  242. {
  243. $this->assertSame($iso, DateTimeHelper::intervalToIso($interval));
  244. }
  245. public function intervalToIsoReinitProvider()
  246. {
  247. return [
  248. [new DI('P1Y')],
  249. [new DI('P1M')],
  250. [new DI('P1D')],
  251. [new DI('PT1H')],
  252. [new DI('PT1M')],
  253. [new DI('PT1S')],
  254. [new DI('P1Y2M3DT4H5M6S')],
  255. ];
  256. }
  257. /**
  258. * @dataProvider intervalToIsoReinitProvider
  259. */
  260. public function testIntervalToIsoReinit($interval)
  261. {
  262. $iso = DateTimeHelper::intervalToIso($interval);
  263. $this->assertEquals($interval, new DI($iso));
  264. }
  265. public function intervalToIsoReinitUnsupportedProvider()
  266. {
  267. return [
  268. [DI::createFromDateString('-2 years')],
  269. [DI::createFromDateString('-2 months')],
  270. [DI::createFromDateString('-2 days')],
  271. [DI::createFromDateString('-2 hours')],
  272. [DI::createFromDateString('-2 minutes')],
  273. [DI::createFromDateString('-2 seconds')],
  274. [(new DT('2016-08-03'))->diff(new DT('2016-07-03'))],
  275. [(new DT('2016-08-03 10:00:01'))->diff(new DT('2016-08-03 10:00:00'))],
  276. ];
  277. }
  278. /**
  279. * @dataProvider intervalToIsoReinitUnsupportedProvider
  280. * @expectedException \Exception
  281. */
  282. public function testIntervalToIsoReinitUnsupported($interval)
  283. {
  284. DateTimeHelper::intervalToIso($interval);
  285. }
  286. public function periodToIsoProvider()
  287. {
  288. return [
  289. [null, null],
  290. [
  291. new DP(
  292. new DT('2016-08-05T14:50:14+08:00'),
  293. new DI('P1D'),
  294. new DT('2016-08-10T14:50:14+08:00')
  295. ),
  296. 'R4/2016-08-05T14:50:14+08:00/P0Y0M1DT0H0M0S',
  297. ],
  298. [
  299. new DP(
  300. new DT('2016-08-05T14:50:14+08:00'),
  301. new DI('P5D'),
  302. new DT('2016-08-10T14:50:14+08:00')
  303. ),
  304. '2016-08-05T14:50:14+08:00/P0Y0M5DT0H0M0S',
  305. ],
  306. [
  307. new DP(
  308. new DT('2016-08-05T14:50:14+08:00'),
  309. new DI('P1Y2M3DT4H5M6S'),
  310. new DT('2017-10-08T18:55:20+08:00')
  311. ),
  312. '2016-08-05T14:50:14+08:00/P1Y2M3DT4H5M6S',
  313. ],
  314. [
  315. new DP(
  316. new DT('2016-08-05T14:50:14Z'),
  317. new DI('P1D'),
  318. 0
  319. ),
  320. '2016-08-05T14:50:14+00:00/P0Y0M1DT0H0M0S',
  321. ],
  322. [
  323. new DP(
  324. new DT('2016-08-05T14:50:14Z'),
  325. new DI('PT5M'),
  326. 3
  327. ),
  328. 'R3/2016-08-05T14:50:14+00:00/P0Y0M0DT0H5M0S',
  329. ],
  330. [
  331. new DP('R3/2016-08-05T14:50:14Z/PT5M'),
  332. 'R3/2016-08-05T14:50:14+00:00/P0Y0M0DT0H5M0S',
  333. ],
  334. [
  335. new DP('R4/2016-08-05T14:50:14Z/P1Y2M3DT4H5M6S'),
  336. 'R4/2016-08-05T14:50:14+00:00/P1Y2M3DT4H5M6S',
  337. ],
  338. [
  339. DateTimeHelper::parse('2016-08-05T14:50:14Z'),
  340. '2016-08-05T14:50:14+00:00/P0Y0M0DT0H0M1S',
  341. ],
  342. [
  343. DateTimeHelper::parse('2016-08-05Z'),
  344. '2016-08-05T00:00:00+00:00/P0Y0M1DT0H0M0S',
  345. ],
  346. [
  347. DateTimeHelper::parse('2016-08-05-03:00'),
  348. '2016-08-05T00:00:00-03:00/P0Y0M1DT0H0M0S',
  349. ],
  350. ];
  351. }
  352. /**
  353. * @dataProvider periodToIsoProvider
  354. */
  355. public function testPeriodToIso($period, $iso)
  356. {
  357. $this->assertSame($iso, DateTimeHelper::periodToIso($period));
  358. }
  359. }