DateTimeComparator.php 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. <?php declare(strict_types=1);
  2. /*
  3. * This file is part of sebastian/comparator.
  4. *
  5. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  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 SebastianBergmann\Comparator;
  11. use function abs;
  12. use function assert;
  13. use function floor;
  14. use function sprintf;
  15. use DateInterval;
  16. use DateTimeInterface;
  17. use DateTimeZone;
  18. final class DateTimeComparator extends ObjectComparator
  19. {
  20. public function accepts(mixed $expected, mixed $actual): bool
  21. {
  22. return ($expected instanceof DateTimeInterface) &&
  23. ($actual instanceof DateTimeInterface);
  24. }
  25. /**
  26. * @throws ComparisonFailure
  27. */
  28. public function assertEquals(mixed $expected, mixed $actual, float $delta = 0.0, bool $canonicalize = false, bool $ignoreCase = false, array &$processed = []): void
  29. {
  30. assert($expected instanceof DateTimeInterface);
  31. assert($actual instanceof DateTimeInterface);
  32. $absDelta = abs($delta);
  33. $delta = new DateInterval(sprintf('PT%dS', $absDelta));
  34. $delta->f = $absDelta - floor($absDelta);
  35. $actualClone = (clone $actual)
  36. ->setTimezone(new DateTimeZone('UTC'));
  37. $expectedLower = (clone $expected)
  38. ->setTimezone(new DateTimeZone('UTC'))
  39. ->sub($delta);
  40. $expectedUpper = (clone $expected)
  41. ->setTimezone(new DateTimeZone('UTC'))
  42. ->add($delta);
  43. if ($actualClone < $expectedLower || $actualClone > $expectedUpper) {
  44. throw new ComparisonFailure(
  45. $expected,
  46. $actual,
  47. $this->dateTimeToString($expected),
  48. $this->dateTimeToString($actual),
  49. 'Failed asserting that two DateTime objects are equal.'
  50. );
  51. }
  52. }
  53. /**
  54. * Returns an ISO 8601 formatted string representation of a datetime or
  55. * 'Invalid DateTimeInterface object' if the provided DateTimeInterface was not properly
  56. * initialized.
  57. */
  58. private function dateTimeToString(DateTimeInterface $datetime): string
  59. {
  60. $string = $datetime->format('Y-m-d\TH:i:s.uO');
  61. return $string ?: 'Invalid DateTimeInterface object';
  62. }
  63. }