TotalTest.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * This file is part of the Carbon package.
  5. *
  6. * (c) Brian Nesbitt <brian@nesbot.com>
  7. *
  8. * For the full copyright and license information, please view the LICENSE
  9. * file that was distributed with this source code.
  10. */
  11. namespace Tests\CarbonInterval;
  12. use Carbon\Carbon;
  13. use Carbon\CarbonInterval;
  14. use Generator;
  15. use InvalidArgumentException;
  16. use Tests\AbstractTestCase;
  17. class TotalTest extends AbstractTestCase
  18. {
  19. /**
  20. * @dataProvider \Tests\CarbonInterval\TotalTest::dataForIntervalSpecs
  21. */
  22. public function testReturnsTotalValue($spec, $unit, $expected)
  23. {
  24. $this->assertSame(
  25. $expected,
  26. CarbonInterval::fromString($spec)->total($unit),
  27. "$spec as $unit did not get the expected total"
  28. );
  29. }
  30. public static function dataForIntervalSpecs(): Generator
  31. {
  32. yield ['10s', 'seconds', 10];
  33. yield ['100s', 'seconds', 100];
  34. yield ['2d 4h 17m 35s', 'seconds', ((2 * 24 + 4) * 60 + 17) * 60 + 35];
  35. yield ['1y', 'Seconds', 12 * 4 * 7 * 24 * 60 * 60];
  36. yield ['1000y', 'SECONDS', 1000 * 12 * 4 * 7 * 24 * 60 * 60];
  37. yield ['235s', 'minutes', 235 / 60];
  38. yield ['3h 14m 235s', 'minutes', 3 * 60 + 14 + 235 / 60];
  39. yield ['27h 150m 4960s', 'hours', 27 + (150 + 4960 / 60) / 60];
  40. yield ['1w', 'days', 7];
  41. yield ['2w 15d', 'weeks', 29 / 7];
  42. yield ['5mo 54d 185h 7680m', 'days', 5 * 4 * 7 + 54 + (185 + 7680 / 60) / 24];
  43. yield ['4y 2mo', 'days', (4 * 12 + 2) * 4 * 7];
  44. yield ['165d', 'weeks', 165 / 7];
  45. yield ['5mo', 'weeks', 5 * 4];
  46. yield ['6897d', 'months', 6897 / 7 / 4];
  47. yield ['35mo', 'years', 35 / 12];
  48. }
  49. public function testThrowsExceptionForInvalidUnits()
  50. {
  51. $this->expectExceptionObject(new InvalidArgumentException(
  52. 'Unknown unit \'foo\'.'
  53. ));
  54. CarbonInterval::create()->total('foo');
  55. }
  56. public function testGetTotalsViaGetters()
  57. {
  58. $interval = CarbonInterval::create(0, 0, 0, 0, 150, 0, 0);
  59. $this->assertSame(150 * 60 * 60 * 1000 * 1000, $interval->totalMicroseconds);
  60. $this->assertSame(150 * 60 * 60 * 1000, $interval->totalMilliseconds);
  61. $this->assertSame(150 * 60 * 60, $interval->totalSeconds);
  62. $this->assertSame(150 * 60, $interval->totalMinutes);
  63. $this->assertSame(150, $interval->totalHours);
  64. $this->assertSame(150 / 24, $interval->totalDays);
  65. $this->assertSame(150 / 24 / 7, $interval->totalWeeks);
  66. $this->assertSame(150 / 24 / 7 / 4, $interval->totalMonths);
  67. $this->assertSame(150 / 24 / 7 / 4 / 12, $interval->totalYears);
  68. $interval = CarbonInterval::milliseconds(12312);
  69. $this->assertSame(12312000, $interval->totalMicroseconds);
  70. $this->assertSame(12312, $interval->totalMilliseconds);
  71. $interval = CarbonInterval::milliseconds(-12312);
  72. $this->assertSame(-12312000, $interval->totalMicroseconds);
  73. $this->assertSame(-12312, $interval->totalMilliseconds);
  74. }
  75. public static function dataForNegativeIntervals(): Generator
  76. {
  77. yield [-1, CarbonInterval::hours(0)->hours(-150)];
  78. yield [-1, CarbonInterval::hours(150)->invert()];
  79. yield [1, CarbonInterval::hours(0)->hours(-150)->invert()];
  80. }
  81. /**
  82. * @dataProvider \Tests\CarbonInterval\TotalTest::dataForNegativeIntervals
  83. */
  84. public function testGetNegativeTotalsViaGetters($factor, $interval)
  85. {
  86. $this->assertSame($factor * 150 * 60 * 60 * 1000 * 1000, $interval->totalMicroseconds);
  87. $this->assertSame($factor * 150 * 60 * 60 * 1000, $interval->totalMilliseconds);
  88. $this->assertSame($factor * 150 * 60 * 60, $interval->totalSeconds);
  89. $this->assertSame($factor * 150 * 60, $interval->totalMinutes);
  90. $this->assertSame($factor * 150, $interval->totalHours);
  91. $this->assertSame($factor * 150 / 24, $interval->totalDays);
  92. $this->assertSame($factor * 150 / 24 / 7, $interval->totalWeeks);
  93. $this->assertSame($factor * 150 / 24 / 7 / 4, $interval->totalMonths);
  94. $this->assertSame($factor * 150 / 24 / 7 / 4 / 12, $interval->totalYears);
  95. }
  96. public function testTotalsWithCustomFactors()
  97. {
  98. $factors = CarbonInterval::getCascadeFactors();
  99. CarbonInterval::setCascadeFactors([
  100. 'minute' => [60, 'seconds'],
  101. 'hour' => [60, 'minutes'],
  102. 'day' => [8, 'hours'],
  103. 'week' => [5, 'days'],
  104. ]);
  105. $this->assertSame(1, CarbonInterval::make('1d')->totalDays);
  106. $this->assertSame(5, CarbonInterval::make('1w')->totalDays);
  107. $this->assertSame(1, CarbonInterval::make('1w')->totalWeeks);
  108. CarbonInterval::setCascadeFactors($factors);
  109. }
  110. public function testFloatHoursFactors()
  111. {
  112. $factors = CarbonInterval::getCascadeFactors();
  113. CarbonInterval::setCascadeFactors([
  114. 'minute' => [60, 'seconds'],
  115. 'hour' => [60, 'minutes'],
  116. 'day' => [7.5, 'hours'],
  117. 'week' => [5, 'days'],
  118. ]);
  119. $this->assertSame(
  120. '2 weeks 1 day 5 hours 45 minutes',
  121. CarbonInterval::minutes(11 * (7.5 * 60) + (5 * 60) + 45)->cascade()->forHumans()
  122. );
  123. CarbonInterval::setCascadeFactors($factors);
  124. }
  125. public function testFloatDaysFactors()
  126. {
  127. $factors = CarbonInterval::getCascadeFactors();
  128. CarbonInterval::setCascadeFactors([
  129. 'minute' => [60, 'seconds'],
  130. 'hour' => [60, 'minutes'],
  131. 'day' => [8, 'hours'],
  132. 'week' => [5.5, 'days'],
  133. ]);
  134. $this->assertSame(
  135. '3 weeks 1 day 5 hours 45 minutes',
  136. CarbonInterval::minutes(17.5 * (8 * 60) + (5 * 60) + 45)->cascade()->forHumans()
  137. );
  138. CarbonInterval::setCascadeFactors($factors);
  139. }
  140. public function testFloatInMultipleFactors()
  141. {
  142. $factors = CarbonInterval::getCascadeFactors();
  143. CarbonInterval::setCascadeFactors([
  144. 'minute' => [23.2, 'seconds'],
  145. 'hour' => [25.662, 'minutes'],
  146. 'day' => [10 / 3, 'hours'],
  147. 'week' => [pi(), 'days'],
  148. ]);
  149. $interval = CarbonInterval::minutes(50000)->cascade();
  150. $this->assertSame(
  151. '185 weeks 2 days 3 hours 35 minutes 35 seconds',
  152. $interval->forHumans()
  153. );
  154. // Show how we (approximately) get back to initial values
  155. $this->assertEqualsWithDelta(
  156. 50000 * 23.2,
  157. 35 + (35 * 23.2) + (3 * 25.662 * 23.2) + (2 * (10 / 3) * 25.662 * 23.2) + (185 * pi() * (10 / 3) * 25.662 * 23.2),
  158. 3
  159. );
  160. // Show how total uncascade
  161. $this->assertEqualsWithDelta(50000 / 25.662, $interval->totalHours, 0.05);
  162. $this->assertEqualsWithDelta(50000, $interval->totalMinutes, 0.1);
  163. $this->assertEqualsWithDelta(50000 * 23.2, $interval->totalSeconds, 1);
  164. CarbonInterval::setCascadeFactors($factors);
  165. }
  166. public function testGetTotalsViaGettersWithCustomFactors()
  167. {
  168. $cascades = CarbonInterval::getCascadeFactors();
  169. CarbonInterval::setCascadeFactors([
  170. 'minutes' => [Carbon::SECONDS_PER_MINUTE, 'seconds'],
  171. 'hours' => [Carbon::MINUTES_PER_HOUR, 'minutes'],
  172. 'days' => [8, 'hours'],
  173. 'weeks' => [5, 'days'],
  174. ]);
  175. $interval = CarbonInterval::create(0, 0, 0, 0, 150, 0, 0);
  176. $totalSeconds = $interval->totalSeconds;
  177. $totalMinutes = $interval->totalMinutes;
  178. $totalHours = $interval->totalHours;
  179. $totalDays = $interval->totalDays;
  180. $totalWeeks = $interval->totalWeeks;
  181. $monthsError = null;
  182. try {
  183. $interval->totalMonths;
  184. } catch (InvalidArgumentException $exception) {
  185. $monthsError = $exception->getMessage();
  186. }
  187. $yearsError = null;
  188. try {
  189. $interval->totalYears;
  190. } catch (InvalidArgumentException $exception) {
  191. $yearsError = $exception->getMessage();
  192. }
  193. CarbonInterval::setCascadeFactors($cascades);
  194. $this->assertSame(150 * 60 * 60, $totalSeconds);
  195. $this->assertSame(150 * 60, $totalMinutes);
  196. $this->assertSame(150, $totalHours);
  197. $this->assertSame(150 / 8, $totalDays);
  198. $this->assertSame(150 / 8 / 5, $totalWeeks);
  199. $this->assertSame('Unit months have no configuration to get total from other units.', $monthsError);
  200. $this->assertSame('Unit years have no configuration to get total from other units.', $yearsError);
  201. }
  202. public function testGetTotalsViaGettersWithFalseFactor()
  203. {
  204. $cascades = CarbonInterval::getCascadeFactors();
  205. CarbonInterval::setCascadeFactors([
  206. 'minutes' => [Carbon::SECONDS_PER_MINUTE, 'seconds'],
  207. 'hours' => [Carbon::MINUTES_PER_HOUR, 'minutes'],
  208. 'days' => [false, 'hours'], // soft break
  209. 'months' => [30, 'days'],
  210. 'years' => [Carbon::MONTHS_PER_YEAR, 'months'],
  211. ]);
  212. $interval = CarbonInterval::create(3, 2, 0, 6, 150, 0, 0);
  213. $totalSeconds = $interval->totalSeconds;
  214. $totalMinutes = $interval->totalMinutes;
  215. $totalHours = $interval->totalHours;
  216. $totalDays = $interval->totalDays;
  217. $totalMonths = $interval->totalMonths;
  218. $totalYears = $interval->totalYears;
  219. CarbonInterval::setCascadeFactors($cascades);
  220. $this->assertSame(150 * 60 * 60, $totalSeconds);
  221. $this->assertSame(150 * 60, $totalMinutes);
  222. $this->assertSame(150, $totalHours);
  223. $this->assertSame(1146, $totalDays);
  224. $this->assertSame(1146 / 30, $totalMonths);
  225. $this->assertSame(1146 / 30 / 12, $totalYears);
  226. }
  227. public function testMicrosecondsInterval()
  228. {
  229. $interval = CarbonInterval::milliseconds(500);
  230. $this->assertSame(0.5, $interval->totalSeconds);
  231. $this->assertSame(1 / 2 / 60, $interval->totalMinutes);
  232. $this->assertSame(1 / 2 / 3600, $interval->totalHours);
  233. $interval = CarbonInterval::milliseconds(600000)->cascade();
  234. $this->assertSame(600000000, $interval->totalMicroseconds);
  235. $this->assertSame(600000, $interval->totalMilliseconds);
  236. $this->assertSame(600, $interval->totalSeconds);
  237. $this->assertSame(10, $interval->totalMinutes);
  238. $this->assertSame(1 / 6, $interval->totalHours);
  239. }
  240. }