From 0df267f2a1992ee8b8e2f23314f23ac725ecaa78 Mon Sep 17 00:00:00 2001 From: Christian Kolb Date: Sun, 9 Jun 2024 21:05:47 +0200 Subject: [PATCH] Add weekday value object (#55) Co-authored-by: Christian Kolb --- Makefile | 4 + infection.json5 | 10 ++ src/Date.php | 6 +- .../DoctrineTypeRegisterCompilerPass.php | 4 + src/Doctrine/WeekdayType.php | 50 ++++++++ src/Doctrine/WeekdaysType.php | 56 ++++++++ src/Moment.php | 42 ++++-- src/Month.php | 1 - src/Resources/config/services.yaml | 6 + src/Serializer/WeekdayNormalizer.php | 51 ++++++++ src/Serializer/WeekdaysNormalizer.php | 49 +++++++ src/Time.php | 1 - src/Weekday.php | 103 +++++++++++++++ src/Weekdays.php | 60 +++++++++ src/Year.php | 1 - tests/Date/WeekdayTest.php | 48 +++++++ .../DoctrineTypeRegisterCompilerPassTest.php | 11 +- tests/Doctrine/WeekdayTypeTest.php | 54 ++++++++ tests/Doctrine/WeekdaysTypeTest.php | 63 +++++++++ tests/Moment/IsAfterInTimeZoneTest.php | 23 +++- .../Moment/IsAfterOrEqualToInTimeZoneTest.php | 23 +++- tests/Moment/IsBeforeInTimeZoneTest.php | 23 +++- .../IsBeforeOrEqualToInTimeZoneTest.php | 23 +++- tests/Moment/IsEqualToInTimeZoneTest.php | 23 +++- tests/Moment/IsNotAfterInTimeZoneTest.php | 23 +++- .../IsNotAfterOrEqualToInTimeZoneTest.php | 23 +++- tests/Moment/IsNotBeforeInTimeZoneTest.php | 23 +++- .../IsNotBeforeOrEqualToInTimeZoneTest.php | 23 +++- tests/Moment/IsNotEqualToInTimeZoneTest.php | 23 +++- tests/Moment/WeekdayTest.php | 93 ++++++++++++++ tests/Serializer/WeekdayNormalizerTest.php | 114 +++++++++++++++++ tests/Serializer/WeekdaysNormalizerTest.php | 121 ++++++++++++++++++ tests/Weekday/CompareToTest.php | 61 +++++++++ tests/Weekday/ConstructionTest.php | 68 ++++++++++ tests/Weekday/DayOfWeekTest.php | 67 ++++++++++ tests/Weekday/IsAfterOrEqualToTest.php | 56 ++++++++ tests/Weekday/IsAfterTest.php | 56 ++++++++ tests/Weekday/IsBeforeOrEqualToTest.php | 56 ++++++++ tests/Weekday/IsBeforeTest.php | 56 ++++++++ tests/Weekday/IsEqualToTest.php | 56 ++++++++ tests/Weekday/IsNotAfterOrEqualToTest.php | 56 ++++++++ tests/Weekday/IsNotAfterTest.php | 56 ++++++++ tests/Weekday/IsNotBeforeOrEqualToTest.php | 56 ++++++++ tests/Weekday/IsNotBeforeTest.php | 56 ++++++++ tests/Weekday/IsNotEqualToTest.php | 56 ++++++++ tests/Weekdays/ConstructionTest.php | 47 +++++++ tests/Weekdays/ContainsTest.php | 58 +++++++++ tests/Weekdays/NormalizationTest.php | 35 +++++ tests/Weekdays/NotContainsTest.php | 59 +++++++++ 49 files changed, 2098 insertions(+), 35 deletions(-) create mode 100644 src/Doctrine/WeekdayType.php create mode 100644 src/Doctrine/WeekdaysType.php create mode 100644 src/Serializer/WeekdayNormalizer.php create mode 100644 src/Serializer/WeekdaysNormalizer.php create mode 100644 src/Weekday.php create mode 100644 src/Weekdays.php create mode 100644 tests/Date/WeekdayTest.php rename tests/{DigitalCraftsman => }/DateTimePrecision/DependencyInjection/DoctrineTypeRegisterCompilerPassTest.php (76%) create mode 100644 tests/Doctrine/WeekdayTypeTest.php create mode 100644 tests/Doctrine/WeekdaysTypeTest.php create mode 100644 tests/Moment/WeekdayTest.php create mode 100644 tests/Serializer/WeekdayNormalizerTest.php create mode 100644 tests/Serializer/WeekdaysNormalizerTest.php create mode 100644 tests/Weekday/CompareToTest.php create mode 100644 tests/Weekday/ConstructionTest.php create mode 100644 tests/Weekday/DayOfWeekTest.php create mode 100644 tests/Weekday/IsAfterOrEqualToTest.php create mode 100644 tests/Weekday/IsAfterTest.php create mode 100644 tests/Weekday/IsBeforeOrEqualToTest.php create mode 100644 tests/Weekday/IsBeforeTest.php create mode 100644 tests/Weekday/IsEqualToTest.php create mode 100644 tests/Weekday/IsNotAfterOrEqualToTest.php create mode 100644 tests/Weekday/IsNotAfterTest.php create mode 100644 tests/Weekday/IsNotBeforeOrEqualToTest.php create mode 100644 tests/Weekday/IsNotBeforeTest.php create mode 100644 tests/Weekday/IsNotEqualToTest.php create mode 100644 tests/Weekdays/ConstructionTest.php create mode 100644 tests/Weekdays/ContainsTest.php create mode 100644 tests/Weekdays/NormalizationTest.php create mode 100644 tests/Weekdays/NotContainsTest.php diff --git a/Makefile b/Makefile index e27acd5..4b636e0 100644 --- a/Makefile +++ b/Makefile @@ -103,6 +103,10 @@ php-8.2-tests: php-8.3-tests: docker-compose run --rm php-8.3 ./vendor/bin/phpunit +## php-tests-coverage Run the tests for default PHP version and create coverage report. +.PHONY: php-tests-coverage +php-tests-coverage: php-8.3-tests-html-coverage + ## php-8.2-tests-html-coverage Run the tests with PHP 8.2 including coverage report as HTML. .PHONY: php-8.2-tests-html-coverage php-8.2-tests-html-coverage: diff --git a/infection.json5 b/infection.json5 index 64fc377..6c3e24c 100644 --- a/infection.json5 +++ b/infection.json5 @@ -12,6 +12,16 @@ "DigitalCraftsman\\DateTimePrecision\\Moment", ] }, + "IncrementInteger": { + "ignore": [ + "DigitalCraftsman\\DateTimePrecision\\Doctrine\\WeekdaysType::convertToPHPValue" + ] + }, + "DecrementInteger": { + "ignore": [ + "DigitalCraftsman\\DateTimePrecision\\Doctrine\\WeekdaysType::convertToPHPValue" + ] + } }, "minMsi": 100, "minCoveredMsi": 100 diff --git a/src/Date.php b/src/Date.php index dcfca76..4219ccb 100644 --- a/src/Date.php +++ b/src/Date.php @@ -4,7 +4,6 @@ namespace DigitalCraftsman\DateTimePrecision; -/** @psalm-immutable */ final readonly class Date implements \Stringable { private const DATE_FORMAT = 'Y-m-d'; @@ -152,6 +151,11 @@ public function datesUntil( return $dates; } + public function weekday(): Weekday + { + return Weekday::fromDateTime($this->toDateTimeImmutable()); + } + // Mutations public function format(string $format): string diff --git a/src/DependencyInjection/DoctrineTypeRegisterCompilerPass.php b/src/DependencyInjection/DoctrineTypeRegisterCompilerPass.php index 4a6a59c..16d0395 100644 --- a/src/DependencyInjection/DoctrineTypeRegisterCompilerPass.php +++ b/src/DependencyInjection/DoctrineTypeRegisterCompilerPass.php @@ -8,6 +8,8 @@ use DigitalCraftsman\DateTimePrecision\Doctrine\MomentType; use DigitalCraftsman\DateTimePrecision\Doctrine\MonthType; use DigitalCraftsman\DateTimePrecision\Doctrine\TimeType; +use DigitalCraftsman\DateTimePrecision\Doctrine\WeekdaysType; +use DigitalCraftsman\DateTimePrecision\Doctrine\WeekdayType; use DigitalCraftsman\DateTimePrecision\Doctrine\YearType; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -23,6 +25,8 @@ public function process(ContainerBuilder $container): void $typeDefinitions['dtp_moment'] = ['class' => MomentType::class]; $typeDefinitions['dtp_time'] = ['class' => TimeType::class]; + $typeDefinitions['dtp_weekday'] = ['class' => WeekdayType::class]; + $typeDefinitions['dtp_weekdays'] = ['class' => WeekdaysType::class]; $typeDefinitions['dtp_date'] = ['class' => DateType::class]; $typeDefinitions['dtp_month'] = ['class' => MonthType::class]; $typeDefinitions['dtp_year'] = ['class' => YearType::class]; diff --git a/src/Doctrine/WeekdayType.php b/src/Doctrine/WeekdayType.php new file mode 100644 index 0000000..e15c715 --- /dev/null +++ b/src/Doctrine/WeekdayType.php @@ -0,0 +1,50 @@ +value; + } + + /** @param string|null $value */ + public function convertToPHPValue($value, AbstractPlatform $platform): ?Weekday + { + return $value === null + ? null + : Weekday::from($value); + } + + /** @codeCoverageIgnore */ + public function getSQLDeclaration(array $column, AbstractPlatform $platform): string + { + $column['length'] = 9; + + return $platform->getStringTypeDeclarationSQL($column); + } + + /** @codeCoverageIgnore */ + public function requiresSQLCommentHint(AbstractPlatform $platform): bool + { + return true; + } +} diff --git a/src/Doctrine/WeekdaysType.php b/src/Doctrine/WeekdaysType.php new file mode 100644 index 0000000..fabb878 --- /dev/null +++ b/src/Doctrine/WeekdaysType.php @@ -0,0 +1,56 @@ +normalize(); + + return json_encode($array, JSON_THROW_ON_ERROR); + } + + /** @param string|null $value */ + public function convertToPHPValue($value, AbstractPlatform $platform): ?Weekdays + { + if ($value === null) { + return null; + } + + $array = json_decode($value, true, 512, JSON_THROW_ON_ERROR); + + return Weekdays::denormalize($array); + } + + /** @codeCoverageIgnore */ + public function getSQLDeclaration(array $column, AbstractPlatform $platform): string + { + $column['jsonb'] = true; + + return $platform->getJsonTypeDeclarationSQL($column); + } + + /** @codeCoverageIgnore */ + public function requiresSQLCommentHint(AbstractPlatform $platform): bool + { + return true; + } +} diff --git a/src/Moment.php b/src/Moment.php index 36913e9..cf7f051 100644 --- a/src/Moment.php +++ b/src/Moment.php @@ -68,6 +68,18 @@ public function timeInTimeZone(\DateTimeZone $timeZone): Time ->time(); } + public function weekday(): Weekday + { + return Weekday::fromDateTime($this->dateTime); + } + + public function weekdayInTimeZone(\DateTimeZone $timeZone): Weekday + { + return $this + ->toTimeZone($timeZone) + ->weekday(); + } + public function month(): Month { return Month::fromDateTime($this->dateTime); @@ -98,11 +110,12 @@ public function isEqualTo(self $moment): bool } public function isEqualToInTimeZone( - Time | Date | Month | Year $comparator, + Time | Weekday | Date | Month | Year $comparator, \DateTimeZone $timeZone, ): bool { return match (true) { $comparator instanceof Time => $this->timeInTimeZone($timeZone)->isEqualTo($comparator), + $comparator instanceof Weekday => $this->weekdayInTimeZone($timeZone)->isEqualTo($comparator), $comparator instanceof Date => $this->dateInTimeZone($timeZone)->isEqualTo($comparator), $comparator instanceof Month => $this->monthInTimeZone($timeZone)->isEqualTo($comparator), $comparator instanceof Year => $this->yearInTimeZone($timeZone)->isEqualTo($comparator), @@ -115,11 +128,12 @@ public function isNotEqualTo(self $moment): bool } public function isNotEqualToInTimeZone( - Time | Date | Month | Year $comparator, + Time | Weekday | Date | Month | Year $comparator, \DateTimeZone $timeZone, ): bool { return match (true) { $comparator instanceof Time => $this->timeInTimeZone($timeZone)->isNotEqualTo($comparator), + $comparator instanceof Weekday => $this->weekdayInTimeZone($timeZone)->isNotEqualTo($comparator), $comparator instanceof Date => $this->dateInTimeZone($timeZone)->isNotEqualTo($comparator), $comparator instanceof Month => $this->monthInTimeZone($timeZone)->isNotEqualTo($comparator), $comparator instanceof Year => $this->yearInTimeZone($timeZone)->isNotEqualTo($comparator), @@ -132,11 +146,12 @@ public function isAfter(self $moment): bool } public function isAfterInTimeZone( - Time | Date | Month | Year $comparator, + Time | Weekday | Date | Month | Year $comparator, \DateTimeZone $timeZone, ): bool { return match (true) { $comparator instanceof Time => $this->timeInTimeZone($timeZone)->isAfter($comparator), + $comparator instanceof Weekday => $this->weekdayInTimeZone($timeZone)->isAfter($comparator), $comparator instanceof Date => $this->dateInTimeZone($timeZone)->isAfter($comparator), $comparator instanceof Month => $this->monthInTimeZone($timeZone)->isAfter($comparator), $comparator instanceof Year => $this->yearInTimeZone($timeZone)->isAfter($comparator), @@ -149,11 +164,12 @@ public function isNotAfter(self $moment): bool } public function isNotAfterInTimeZone( - Time | Date | Month | Year $comparator, + Time | Weekday | Date | Month | Year $comparator, \DateTimeZone $timeZone, ): bool { return match (true) { $comparator instanceof Time => $this->timeInTimeZone($timeZone)->isNotAfter($comparator), + $comparator instanceof Weekday => $this->weekdayInTimeZone($timeZone)->isNotAfter($comparator), $comparator instanceof Date => $this->dateInTimeZone($timeZone)->isNotAfter($comparator), $comparator instanceof Month => $this->monthInTimeZone($timeZone)->isNotAfter($comparator), $comparator instanceof Year => $this->yearInTimeZone($timeZone)->isNotAfter($comparator), @@ -166,11 +182,12 @@ public function isAfterOrEqualTo(self $moment): bool } public function isAfterOrEqualToInTimeZone( - Time | Date | Month | Year $comparator, + Time | Weekday | Date | Month | Year $comparator, \DateTimeZone $timeZone, ): bool { return match (true) { $comparator instanceof Time => $this->timeInTimeZone($timeZone)->isAfterOrEqualTo($comparator), + $comparator instanceof Weekday => $this->weekdayInTimeZone($timeZone)->isAfterOrEqualTo($comparator), $comparator instanceof Date => $this->dateInTimeZone($timeZone)->isAfterOrEqualTo($comparator), $comparator instanceof Month => $this->monthInTimeZone($timeZone)->isAfterOrEqualTo($comparator), $comparator instanceof Year => $this->yearInTimeZone($timeZone)->isAfterOrEqualTo($comparator), @@ -183,11 +200,12 @@ public function isNotAfterOrEqualTo(self $moment): bool } public function isNotAfterOrEqualToInTimeZone( - Time | Date | Month | Year $comparator, + Time | Weekday | Date | Month | Year $comparator, \DateTimeZone $timeZone, ): bool { return match (true) { $comparator instanceof Time => $this->timeInTimeZone($timeZone)->isNotAfterOrEqualTo($comparator), + $comparator instanceof Weekday => $this->weekdayInTimeZone($timeZone)->isNotAfterOrEqualTo($comparator), $comparator instanceof Date => $this->dateInTimeZone($timeZone)->isNotAfterOrEqualTo($comparator), $comparator instanceof Month => $this->monthInTimeZone($timeZone)->isNotAfterOrEqualTo($comparator), $comparator instanceof Year => $this->yearInTimeZone($timeZone)->isNotAfterOrEqualTo($comparator), @@ -200,11 +218,12 @@ public function isBeforeOrEqualTo(self $moment): bool } public function isBeforeOrEqualToInTimeZone( - Time | Date | Month | Year $comparator, + Time | Weekday | Date | Month | Year $comparator, \DateTimeZone $timeZone, ): bool { return match (true) { $comparator instanceof Time => $this->timeInTimeZone($timeZone)->isBeforeOrEqualTo($comparator), + $comparator instanceof Weekday => $this->weekdayInTimeZone($timeZone)->isBeforeOrEqualTo($comparator), $comparator instanceof Date => $this->dateInTimeZone($timeZone)->isBeforeOrEqualTo($comparator), $comparator instanceof Month => $this->monthInTimeZone($timeZone)->isBeforeOrEqualTo($comparator), $comparator instanceof Year => $this->yearInTimeZone($timeZone)->isBeforeOrEqualTo($comparator), @@ -217,11 +236,12 @@ public function isNotBeforeOrEqualTo(self $moment): bool } public function isNotBeforeOrEqualToInTimeZone( - Time | Date | Month | Year $comparator, + Time | Weekday | Date | Month | Year $comparator, \DateTimeZone $timeZone, ): bool { return match (true) { $comparator instanceof Time => $this->timeInTimeZone($timeZone)->isNotBeforeOrEqualTo($comparator), + $comparator instanceof Weekday => $this->weekdayInTimeZone($timeZone)->isNotBeforeOrEqualTo($comparator), $comparator instanceof Date => $this->dateInTimeZone($timeZone)->isNotBeforeOrEqualTo($comparator), $comparator instanceof Month => $this->monthInTimeZone($timeZone)->isNotBeforeOrEqualTo($comparator), $comparator instanceof Year => $this->yearInTimeZone($timeZone)->isNotBeforeOrEqualTo($comparator), @@ -235,11 +255,12 @@ public function isBefore( } public function isBeforeInTimeZone( - Time | Date | Month | Year $comparator, + Time | Weekday | Date | Month | Year $comparator, \DateTimeZone $timeZone, ): bool { return match (true) { $comparator instanceof Time => $this->timeInTimeZone($timeZone)->isBefore($comparator), + $comparator instanceof Weekday => $this->weekdayInTimeZone($timeZone)->isBefore($comparator), $comparator instanceof Date => $this->dateInTimeZone($timeZone)->isBefore($comparator), $comparator instanceof Month => $this->monthInTimeZone($timeZone)->isBefore($comparator), $comparator instanceof Year => $this->yearInTimeZone($timeZone)->isBefore($comparator), @@ -252,11 +273,12 @@ public function isNotBefore(self $moment): bool } public function isNotBeforeInTimeZone( - Time | Date | Month | Year $comparator, + Time | Weekday | Date | Month | Year $comparator, \DateTimeZone $timeZone, ): bool { return match (true) { $comparator instanceof Time => $this->timeInTimeZone($timeZone)->isNotBefore($comparator), + $comparator instanceof Weekday => $this->weekdayInTimeZone($timeZone)->isNotBefore($comparator), $comparator instanceof Date => $this->dateInTimeZone($timeZone)->isNotBefore($comparator), $comparator instanceof Month => $this->monthInTimeZone($timeZone)->isNotBefore($comparator), $comparator instanceof Year => $this->yearInTimeZone($timeZone)->isNotBefore($comparator), diff --git a/src/Month.php b/src/Month.php index 32aa55a..9c3e36a 100644 --- a/src/Month.php +++ b/src/Month.php @@ -4,7 +4,6 @@ namespace DigitalCraftsman\DateTimePrecision; -/** @psalm-immutable */ final readonly class Month implements \Stringable { private const MONTH_FORMAT = 'Y-m'; diff --git a/src/Resources/config/services.yaml b/src/Resources/config/services.yaml index aeea9a5..10d0004 100644 --- a/src/Resources/config/services.yaml +++ b/src/Resources/config/services.yaml @@ -13,6 +13,12 @@ services: DigitalCraftsman\DateTimePrecision\Serializer\TimeNormalizer: tags: [ { name: 'serializer.normalizer' } ] + DigitalCraftsman\DateTimePrecision\Serializer\WeekdayNormalizer: + tags: [ { name: 'serializer.normalizer' } ] + + DigitalCraftsman\DateTimePrecision\Serializer\WeekdaysNormalizer: + tags: [ { name: 'serializer.normalizer' } ] + DigitalCraftsman\DateTimePrecision\Serializer\DateNormalizer: tags: [ { name: 'serializer.normalizer' } ] diff --git a/src/Serializer/WeekdayNormalizer.php b/src/Serializer/WeekdayNormalizer.php new file mode 100644 index 0000000..c337dbd --- /dev/null +++ b/src/Serializer/WeekdayNormalizer.php @@ -0,0 +1,51 @@ +value; + } + + /** @param ?string $data */ + public function denormalize($data, $type, $format = null, array $context = []): ?Weekday + { + return $data === null + ? null + : Weekday::from($data); + } + + /** + * @return array + * + * @codeCoverageIgnore + */ + public function getSupportedTypes(?string $format): array + { + return [ + Weekday::class => true, + ]; + } +} diff --git a/src/Serializer/WeekdaysNormalizer.php b/src/Serializer/WeekdaysNormalizer.php new file mode 100644 index 0000000..1cfeaf8 --- /dev/null +++ b/src/Serializer/WeekdaysNormalizer.php @@ -0,0 +1,49 @@ +normalize(); + } + + /** @param ?array $data */ + public function denormalize($data, $type, $format = null, array $context = []): ?Weekdays + { + return $data === null + ? null + : Weekdays::denormalize($data); + } + + /** + * @return array + * + * @codeCoverageIgnore + */ + public function getSupportedTypes(?string $format): array + { + return [ + Weekdays::class => true, + ]; + } +} diff --git a/src/Time.php b/src/Time.php index 7d097c8..65f2d69 100644 --- a/src/Time.php +++ b/src/Time.php @@ -4,7 +4,6 @@ namespace DigitalCraftsman\DateTimePrecision; -/** @psalm-immutable */ final readonly class Time implements \Stringable { private const TIME_FORMAT = 'H:i:s.u'; diff --git a/src/Weekday.php b/src/Weekday.php new file mode 100644 index 0000000..4617711 --- /dev/null +++ b/src/Weekday.php @@ -0,0 +1,103 @@ +format('N'); + + return match ($dayOfWeek) { + 1 => self::MONDAY, + 2 => self::TUESDAY, + 3 => self::WEDNESDAY, + 4 => self::THURSDAY, + 5 => self::FRIDAY, + 6 => self::SATURDAY, + 7 => self::SUNDAY, + }; + } + + // -- Accessors + + public function dayOfWeek(): int + { + return match ($this) { + self::MONDAY => 1, + self::TUESDAY => 2, + self::WEDNESDAY => 3, + self::THURSDAY => 4, + self::FRIDAY => 5, + self::SATURDAY => 6, + self::SUNDAY => 7, + }; + } + + public function isEqualTo(self $weekday): bool + { + return $this === $weekday; + } + + public function isNotEqualTo(self $weekday): bool + { + return $this !== $weekday; + } + + public function isBefore(self $date): bool + { + return $this->dayOfWeek() < $date->dayOfWeek(); + } + + public function isNotBefore(self $date): bool + { + return !($this->dayOfWeek() < $date->dayOfWeek()); + } + + public function isBeforeOrEqualTo(self $date): bool + { + return $this->dayOfWeek() <= $date->dayOfWeek(); + } + + public function isNotBeforeOrEqualTo(self $date): bool + { + return !($this->dayOfWeek() <= $date->dayOfWeek()); + } + + public function isAfter(self $date): bool + { + return $this->dayOfWeek() > $date->dayOfWeek(); + } + + public function isNotAfter(self $date): bool + { + return !($this->dayOfWeek() > $date->dayOfWeek()); + } + + public function isAfterOrEqualTo(self $date): bool + { + return $this->dayOfWeek() >= $date->dayOfWeek(); + } + + public function isNotAfterOrEqualTo(self $date): bool + { + return !($this->dayOfWeek() >= $date->dayOfWeek()); + } + + public function compareTo(self $date): int + { + return $this->dayOfWeek() <=> $date->dayOfWeek(); + } +} diff --git a/src/Weekdays.php b/src/Weekdays.php new file mode 100644 index 0000000..3282327 --- /dev/null +++ b/src/Weekdays.php @@ -0,0 +1,60 @@ + $weekdays */ + public function __construct( + /** @var array $weekdays */ + public array $weekdays, + ) { + $enumValues = []; + foreach ($this->weekdays as $weekday) { + $enumValues[] = $weekday->value; + } + if (count($enumValues) !== count(array_unique($enumValues))) { + throw new \InvalidArgumentException('Weekdays must be unique.'); + } + } + + // -- Array normalizable + + /** @param array $array */ + public static function denormalize(array $array): self + { + $weekdays = []; + foreach ($array as $value) { + $weekdays[] = Weekday::from($value); + } + + return new self($weekdays); + } + + /** @return array */ + public function normalize(): array + { + $weekdayStrings = []; + foreach ($this->weekdays as $weekday) { + $weekdayStrings[] = $weekday->value; + } + + return $weekdayStrings; + } + + // Accessors + + public function contains(Weekday $weekday): bool + { + return in_array($weekday, $this->weekdays, true); + } + + public function notContains(Weekday $weekday): bool + { + return !in_array($weekday, $this->weekdays, true); + } +} diff --git a/src/Year.php b/src/Year.php index 1798e5a..66b2f30 100644 --- a/src/Year.php +++ b/src/Year.php @@ -4,7 +4,6 @@ namespace DigitalCraftsman\DateTimePrecision; -/** @psalm-immutable */ final readonly class Year { // -- Construction diff --git a/tests/Date/WeekdayTest.php b/tests/Date/WeekdayTest.php new file mode 100644 index 0000000..55b38e3 --- /dev/null +++ b/tests/Date/WeekdayTest.php @@ -0,0 +1,48 @@ +weekday()); + } + + /** + * @return array + */ + public static function dataProviderForWeekday(): array + { + return [ + 'saturday' => [ + Weekday::SATURDAY, + Date::fromString('2022-10-08'), + ], + 'monday' => [ + Weekday::MONDAY, + Date::fromString('2022-10-10'), + ], + ]; + } +} diff --git a/tests/DigitalCraftsman/DateTimePrecision/DependencyInjection/DoctrineTypeRegisterCompilerPassTest.php b/tests/DateTimePrecision/DependencyInjection/DoctrineTypeRegisterCompilerPassTest.php similarity index 76% rename from tests/DigitalCraftsman/DateTimePrecision/DependencyInjection/DoctrineTypeRegisterCompilerPassTest.php rename to tests/DateTimePrecision/DependencyInjection/DoctrineTypeRegisterCompilerPassTest.php index 7e8505f..4a321ea 100644 --- a/tests/DigitalCraftsman/DateTimePrecision/DependencyInjection/DoctrineTypeRegisterCompilerPassTest.php +++ b/tests/DateTimePrecision/DependencyInjection/DoctrineTypeRegisterCompilerPassTest.php @@ -2,12 +2,15 @@ declare(strict_types=1); -namespace DigitalCraftsman\DateTimePrecision\DependencyInjection; +namespace DigitalCraftsman\DateTimePrecision\DateTimePrecision\DependencyInjection; +use DigitalCraftsman\DateTimePrecision\DependencyInjection\DoctrineTypeRegisterCompilerPass; use DigitalCraftsman\DateTimePrecision\Doctrine\DateType; use DigitalCraftsman\DateTimePrecision\Doctrine\MomentType; use DigitalCraftsman\DateTimePrecision\Doctrine\MonthType; use DigitalCraftsman\DateTimePrecision\Doctrine\TimeType; +use DigitalCraftsman\DateTimePrecision\Doctrine\WeekdaysType; +use DigitalCraftsman\DateTimePrecision\Doctrine\WeekdayType; use DigitalCraftsman\DateTimePrecision\Doctrine\YearType; use PHPUnit\Framework\TestCase; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -41,6 +44,12 @@ public function process_works(): void self::assertArrayHasKey('dtp_time', $updatedParameters); self::assertSame(['class' => TimeType::class], $updatedParameters['dtp_time']); + self::assertArrayHasKey('dtp_weekday', $updatedParameters); + self::assertSame(['class' => WeekdayType::class], $updatedParameters['dtp_weekday']); + + self::assertArrayHasKey('dtp_weekdays', $updatedParameters); + self::assertSame(['class' => WeekdaysType::class], $updatedParameters['dtp_weekdays']); + self::assertArrayHasKey('dtp_date', $updatedParameters); self::assertSame(['class' => DateType::class], $updatedParameters['dtp_date']); diff --git a/tests/Doctrine/WeekdayTypeTest.php b/tests/Doctrine/WeekdayTypeTest.php new file mode 100644 index 0000000..fe1e49b --- /dev/null +++ b/tests/Doctrine/WeekdayTypeTest.php @@ -0,0 +1,54 @@ +convertToDatabaseValue($weekday, $platform); + $phpValue = $weekdayType->convertToPHPValue($databaseValue, $platform); + + // -- Assert + self::assertEquals($weekday, $phpValue); + } + + /** + * @test + * + * @covers ::convertToDatabaseValue + * @covers ::convertToPHPValue + */ + public function convert_from_and_to_null_value_works(): void + { + // -- Arrange + $weekdayType = new WeekdayType(); + $platform = new PostgreSQLPlatform(); + + // -- Act + $databaseValue = $weekdayType->convertToDatabaseValue(null, $platform); + $phpValue = $weekdayType->convertToPHPValue($databaseValue, $platform); + + // -- Assert + self::assertNull($phpValue); + } +} diff --git a/tests/Doctrine/WeekdaysTypeTest.php b/tests/Doctrine/WeekdaysTypeTest.php new file mode 100644 index 0000000..14cb373 --- /dev/null +++ b/tests/Doctrine/WeekdaysTypeTest.php @@ -0,0 +1,63 @@ +convertToDatabaseValue($weekdays, $platform); + $convertedValue = $doctrineType->convertToPHPValue($databaseValue, $platform); + + // -- Assert + self::assertSame($expectedDatabaseValue, $databaseValue); + self::assertEquals($weekdays, $convertedValue); + } + + /** + * @test + * + * @covers ::convertToDatabaseValue + * @covers ::convertToPHPValue + */ + public function convert_from_and_to_weekdays_php_value_works_with_null(): void + { + // -- Arrange + $doctrineType = new WeekdaysType(); + $platform = new PostgreSQLPlatform(); + + // -- Act + $databaseValue = $doctrineType->convertToDatabaseValue(null, $platform); + $phpValue = $doctrineType->convertToPHPValue($databaseValue, $platform); + + // -- Assert + self::assertNull($phpValue); + } +} diff --git a/tests/Moment/IsAfterInTimeZoneTest.php b/tests/Moment/IsAfterInTimeZoneTest.php index bafc998..028339d 100644 --- a/tests/Moment/IsAfterInTimeZoneTest.php +++ b/tests/Moment/IsAfterInTimeZoneTest.php @@ -8,6 +8,7 @@ use DigitalCraftsman\DateTimePrecision\Moment; use DigitalCraftsman\DateTimePrecision\Month; use DigitalCraftsman\DateTimePrecision\Time; +use DigitalCraftsman\DateTimePrecision\Weekday; use DigitalCraftsman\DateTimePrecision\Year; use PHPUnit\Framework\TestCase; @@ -24,7 +25,7 @@ final class IsAfterInTimeZoneTest extends TestCase public function is_after_in_time_zone_works( bool $expectedResult, Moment $moment, - Time | Date | Month | Year $comparator, + Time | Weekday | Date | Month | Year $comparator, \DateTimeZone $timeZone, ): void { // -- Act & Assert @@ -35,7 +36,7 @@ public function is_after_in_time_zone_works( * @return array */ @@ -60,6 +61,24 @@ public static function dataProvider(): array Time::fromString('15:00:00'), new \DateTimeZone('Europe/Berlin'), ], + 'moment before weekday' => [ + false, + Moment::fromStringInTimeZone('2022-10-07 15:00:00', new \DateTimeZone('Europe/Berlin')), + Weekday::SATURDAY, + new \DateTimeZone('Europe/Berlin'), + ], + 'moment same weekday' => [ + false, + Moment::fromStringInTimeZone('2022-10-08 15:00:00', new \DateTimeZone('Europe/Berlin')), + Weekday::SATURDAY, + new \DateTimeZone('Europe/Berlin'), + ], + 'moment after weekday' => [ + true, + Moment::fromStringInTimeZone('2022-10-09 15:00:00', new \DateTimeZone('Europe/Berlin')), + Weekday::SATURDAY, + new \DateTimeZone('Europe/Berlin'), + ], 'moment before date' => [ false, Moment::fromStringInTimeZone('2022-10-07 15:00:00', new \DateTimeZone('Europe/Berlin')), diff --git a/tests/Moment/IsAfterOrEqualToInTimeZoneTest.php b/tests/Moment/IsAfterOrEqualToInTimeZoneTest.php index 45d76d6..17bb5a7 100644 --- a/tests/Moment/IsAfterOrEqualToInTimeZoneTest.php +++ b/tests/Moment/IsAfterOrEqualToInTimeZoneTest.php @@ -8,6 +8,7 @@ use DigitalCraftsman\DateTimePrecision\Moment; use DigitalCraftsman\DateTimePrecision\Month; use DigitalCraftsman\DateTimePrecision\Time; +use DigitalCraftsman\DateTimePrecision\Weekday; use DigitalCraftsman\DateTimePrecision\Year; use PHPUnit\Framework\TestCase; @@ -24,7 +25,7 @@ final class IsAfterOrEqualToInTimeZoneTest extends TestCase public function is_after_or_equal_to_in_time_zone_works( bool $expectedResult, Moment $moment, - Time | Date | Month | Year $comparator, + Time | Weekday | Date | Month | Year $comparator, \DateTimeZone $timeZone, ): void { // -- Act & Assert @@ -35,7 +36,7 @@ public function is_after_or_equal_to_in_time_zone_works( * @return array */ @@ -60,6 +61,24 @@ public static function dataProvider(): array Time::fromString('15:00:00'), new \DateTimeZone('Europe/Berlin'), ], + 'moment before weekday' => [ + false, + Moment::fromStringInTimeZone('2022-10-07 15:00:00', new \DateTimeZone('Europe/Berlin')), + Weekday::SATURDAY, + new \DateTimeZone('Europe/Berlin'), + ], + 'moment same weekday' => [ + true, + Moment::fromStringInTimeZone('2022-10-08 15:00:00', new \DateTimeZone('Europe/Berlin')), + Weekday::SATURDAY, + new \DateTimeZone('Europe/Berlin'), + ], + 'moment after weekday' => [ + true, + Moment::fromStringInTimeZone('2022-10-09 15:00:00', new \DateTimeZone('Europe/Berlin')), + Weekday::SATURDAY, + new \DateTimeZone('Europe/Berlin'), + ], 'moment before date' => [ false, Moment::fromStringInTimeZone('2022-10-07 15:00:00', new \DateTimeZone('Europe/Berlin')), diff --git a/tests/Moment/IsBeforeInTimeZoneTest.php b/tests/Moment/IsBeforeInTimeZoneTest.php index 197c34d..61bda0b 100644 --- a/tests/Moment/IsBeforeInTimeZoneTest.php +++ b/tests/Moment/IsBeforeInTimeZoneTest.php @@ -8,6 +8,7 @@ use DigitalCraftsman\DateTimePrecision\Moment; use DigitalCraftsman\DateTimePrecision\Month; use DigitalCraftsman\DateTimePrecision\Time; +use DigitalCraftsman\DateTimePrecision\Weekday; use DigitalCraftsman\DateTimePrecision\Year; use PHPUnit\Framework\TestCase; @@ -24,7 +25,7 @@ final class IsBeforeInTimeZoneTest extends TestCase public function is_before_in_time_zone_works( bool $expectedResult, Moment $moment, - Time | Date | Month | Year $comparator, + Time | Weekday | Date | Month | Year $comparator, \DateTimeZone $timeZone, ): void { // -- Act & Assert @@ -35,7 +36,7 @@ public function is_before_in_time_zone_works( * @return array */ @@ -60,6 +61,24 @@ public static function dataProvider(): array Time::fromString('15:00:00'), new \DateTimeZone('Europe/Berlin'), ], + 'moment before weekday' => [ + true, + Moment::fromStringInTimeZone('2022-10-07 15:00:00', new \DateTimeZone('Europe/Berlin')), + Weekday::SATURDAY, + new \DateTimeZone('Europe/Berlin'), + ], + 'moment same weekday' => [ + false, + Moment::fromStringInTimeZone('2022-10-08 15:00:00', new \DateTimeZone('Europe/Berlin')), + Weekday::SATURDAY, + new \DateTimeZone('Europe/Berlin'), + ], + 'moment after weekday' => [ + false, + Moment::fromStringInTimeZone('2022-10-09 15:00:00', new \DateTimeZone('Europe/Berlin')), + Weekday::SATURDAY, + new \DateTimeZone('Europe/Berlin'), + ], 'moment before date' => [ true, Moment::fromStringInTimeZone('2022-10-07 15:00:00', new \DateTimeZone('Europe/Berlin')), diff --git a/tests/Moment/IsBeforeOrEqualToInTimeZoneTest.php b/tests/Moment/IsBeforeOrEqualToInTimeZoneTest.php index 17066f7..4b2c6b4 100644 --- a/tests/Moment/IsBeforeOrEqualToInTimeZoneTest.php +++ b/tests/Moment/IsBeforeOrEqualToInTimeZoneTest.php @@ -8,6 +8,7 @@ use DigitalCraftsman\DateTimePrecision\Moment; use DigitalCraftsman\DateTimePrecision\Month; use DigitalCraftsman\DateTimePrecision\Time; +use DigitalCraftsman\DateTimePrecision\Weekday; use DigitalCraftsman\DateTimePrecision\Year; use PHPUnit\Framework\TestCase; @@ -24,7 +25,7 @@ final class IsBeforeOrEqualToInTimeZoneTest extends TestCase public function is_before_or_equal_to_in_time_zone_works( bool $expectedResult, Moment $moment, - Time | Date | Month | Year $comparator, + Time | Weekday | Date | Month | Year $comparator, \DateTimeZone $timeZone, ): void { // -- Act & Assert @@ -35,7 +36,7 @@ public function is_before_or_equal_to_in_time_zone_works( * @return array */ @@ -60,6 +61,24 @@ public static function dataProvider(): array Time::fromString('15:00:00'), new \DateTimeZone('Europe/Berlin'), ], + 'moment before weekday' => [ + true, + Moment::fromStringInTimeZone('2022-10-07 15:00:00', new \DateTimeZone('Europe/Berlin')), + Weekday::SATURDAY, + new \DateTimeZone('Europe/Berlin'), + ], + 'moment same weekday' => [ + true, + Moment::fromStringInTimeZone('2022-10-08 15:00:00', new \DateTimeZone('Europe/Berlin')), + Weekday::SATURDAY, + new \DateTimeZone('Europe/Berlin'), + ], + 'moment after weekday' => [ + false, + Moment::fromStringInTimeZone('2022-10-09 15:00:00', new \DateTimeZone('Europe/Berlin')), + Weekday::SATURDAY, + new \DateTimeZone('Europe/Berlin'), + ], 'moment before date' => [ true, Moment::fromStringInTimeZone('2022-10-07 15:00:00', new \DateTimeZone('Europe/Berlin')), diff --git a/tests/Moment/IsEqualToInTimeZoneTest.php b/tests/Moment/IsEqualToInTimeZoneTest.php index af1ea6f..9f6cf16 100644 --- a/tests/Moment/IsEqualToInTimeZoneTest.php +++ b/tests/Moment/IsEqualToInTimeZoneTest.php @@ -8,6 +8,7 @@ use DigitalCraftsman\DateTimePrecision\Moment; use DigitalCraftsman\DateTimePrecision\Month; use DigitalCraftsman\DateTimePrecision\Time; +use DigitalCraftsman\DateTimePrecision\Weekday; use DigitalCraftsman\DateTimePrecision\Year; use PHPUnit\Framework\TestCase; @@ -24,7 +25,7 @@ final class IsEqualToInTimeZoneTest extends TestCase public function is_equal_to_in_time_zone_works( bool $expectedResult, Moment $moment, - Time | Date | Month | Year $comparator, + Time | Weekday | Date | Month | Year $comparator, \DateTimeZone $timeZone, ): void { // -- Act & Assert @@ -35,7 +36,7 @@ public function is_equal_to_in_time_zone_works( * @return array */ @@ -60,6 +61,24 @@ public static function dataProvider(): array Time::fromString('15:00:00'), new \DateTimeZone('Europe/Berlin'), ], + 'moment before weekday' => [ + false, + Moment::fromStringInTimeZone('2022-10-07 15:00:00', new \DateTimeZone('Europe/Berlin')), + Weekday::SATURDAY, + new \DateTimeZone('Europe/Berlin'), + ], + 'moment same weekday' => [ + true, + Moment::fromStringInTimeZone('2022-10-08 15:00:00', new \DateTimeZone('Europe/Berlin')), + Weekday::SATURDAY, + new \DateTimeZone('Europe/Berlin'), + ], + 'moment after weekday' => [ + false, + Moment::fromStringInTimeZone('2022-10-09 15:00:00', new \DateTimeZone('Europe/Berlin')), + Weekday::SATURDAY, + new \DateTimeZone('Europe/Berlin'), + ], 'moment before date' => [ false, Moment::fromStringInTimeZone('2022-10-07 15:00:00', new \DateTimeZone('Europe/Berlin')), diff --git a/tests/Moment/IsNotAfterInTimeZoneTest.php b/tests/Moment/IsNotAfterInTimeZoneTest.php index 829ab0c..e34c7b5 100644 --- a/tests/Moment/IsNotAfterInTimeZoneTest.php +++ b/tests/Moment/IsNotAfterInTimeZoneTest.php @@ -8,6 +8,7 @@ use DigitalCraftsman\DateTimePrecision\Moment; use DigitalCraftsman\DateTimePrecision\Month; use DigitalCraftsman\DateTimePrecision\Time; +use DigitalCraftsman\DateTimePrecision\Weekday; use DigitalCraftsman\DateTimePrecision\Year; use PHPUnit\Framework\TestCase; @@ -24,7 +25,7 @@ final class IsNotAfterInTimeZoneTest extends TestCase public function is_not_after_in_time_zone_works( bool $expectedResult, Moment $moment, - Time | Date | Month | Year $comparator, + Time | Weekday | Date | Month | Year $comparator, \DateTimeZone $timeZone, ): void { // -- Act & Assert @@ -35,7 +36,7 @@ public function is_not_after_in_time_zone_works( * @return array */ @@ -60,6 +61,24 @@ public static function dataProvider(): array Time::fromString('15:00:00'), new \DateTimeZone('Europe/Berlin'), ], + 'moment before weekday' => [ + true, + Moment::fromStringInTimeZone('2022-10-07 15:00:00', new \DateTimeZone('Europe/Berlin')), + Weekday::SATURDAY, + new \DateTimeZone('Europe/Berlin'), + ], + 'moment same weekday' => [ + true, + Moment::fromStringInTimeZone('2022-10-08 15:00:00', new \DateTimeZone('Europe/Berlin')), + Weekday::SATURDAY, + new \DateTimeZone('Europe/Berlin'), + ], + 'moment after weekday' => [ + false, + Moment::fromStringInTimeZone('2022-10-09 15:00:00', new \DateTimeZone('Europe/Berlin')), + Weekday::SATURDAY, + new \DateTimeZone('Europe/Berlin'), + ], 'moment before date' => [ true, Moment::fromStringInTimeZone('2022-10-07 15:00:00', new \DateTimeZone('Europe/Berlin')), diff --git a/tests/Moment/IsNotAfterOrEqualToInTimeZoneTest.php b/tests/Moment/IsNotAfterOrEqualToInTimeZoneTest.php index 21f0a7b..7e0f046 100644 --- a/tests/Moment/IsNotAfterOrEqualToInTimeZoneTest.php +++ b/tests/Moment/IsNotAfterOrEqualToInTimeZoneTest.php @@ -8,6 +8,7 @@ use DigitalCraftsman\DateTimePrecision\Moment; use DigitalCraftsman\DateTimePrecision\Month; use DigitalCraftsman\DateTimePrecision\Time; +use DigitalCraftsman\DateTimePrecision\Weekday; use DigitalCraftsman\DateTimePrecision\Year; use PHPUnit\Framework\TestCase; @@ -24,7 +25,7 @@ final class IsNotAfterOrEqualToInTimeZoneTest extends TestCase public function is_not_after_or_equal_to_in_time_zone_works( bool $expectedResult, Moment $moment, - Time | Date | Month | Year $comparator, + Time | Weekday | Date | Month | Year $comparator, \DateTimeZone $timeZone, ): void { // -- Act & Assert @@ -35,7 +36,7 @@ public function is_not_after_or_equal_to_in_time_zone_works( * @return array */ @@ -60,6 +61,24 @@ public static function dataProvider(): array Time::fromString('15:00:00'), new \DateTimeZone('Europe/Berlin'), ], + 'moment before weekday' => [ + true, + Moment::fromStringInTimeZone('2022-10-07 15:00:00', new \DateTimeZone('Europe/Berlin')), + Weekday::SATURDAY, + new \DateTimeZone('Europe/Berlin'), + ], + 'moment same weekday' => [ + false, + Moment::fromStringInTimeZone('2022-10-08 15:00:00', new \DateTimeZone('Europe/Berlin')), + Weekday::SATURDAY, + new \DateTimeZone('Europe/Berlin'), + ], + 'moment after weekday' => [ + false, + Moment::fromStringInTimeZone('2022-10-09 15:00:00', new \DateTimeZone('Europe/Berlin')), + Weekday::SATURDAY, + new \DateTimeZone('Europe/Berlin'), + ], 'moment before date' => [ true, Moment::fromStringInTimeZone('2022-10-07 15:00:00', new \DateTimeZone('Europe/Berlin')), diff --git a/tests/Moment/IsNotBeforeInTimeZoneTest.php b/tests/Moment/IsNotBeforeInTimeZoneTest.php index 0a1bcd1..4d1f5b0 100644 --- a/tests/Moment/IsNotBeforeInTimeZoneTest.php +++ b/tests/Moment/IsNotBeforeInTimeZoneTest.php @@ -8,6 +8,7 @@ use DigitalCraftsman\DateTimePrecision\Moment; use DigitalCraftsman\DateTimePrecision\Month; use DigitalCraftsman\DateTimePrecision\Time; +use DigitalCraftsman\DateTimePrecision\Weekday; use DigitalCraftsman\DateTimePrecision\Year; use PHPUnit\Framework\TestCase; @@ -24,7 +25,7 @@ final class IsNotBeforeInTimeZoneTest extends TestCase public function is_not_before_in_time_zone_works( bool $expectedResult, Moment $moment, - Time | Date | Month | Year $comparator, + Time | Weekday | Date | Month | Year $comparator, \DateTimeZone $timeZone, ): void { // -- Act & Assert @@ -35,7 +36,7 @@ public function is_not_before_in_time_zone_works( * @return array */ @@ -60,6 +61,24 @@ public static function dataProvider(): array Time::fromString('15:00:00'), new \DateTimeZone('Europe/Berlin'), ], + 'moment before weekday' => [ + false, + Moment::fromStringInTimeZone('2022-10-07 15:00:00', new \DateTimeZone('Europe/Berlin')), + Weekday::SATURDAY, + new \DateTimeZone('Europe/Berlin'), + ], + 'moment same weekday' => [ + true, + Moment::fromStringInTimeZone('2022-10-08 15:00:00', new \DateTimeZone('Europe/Berlin')), + Weekday::SATURDAY, + new \DateTimeZone('Europe/Berlin'), + ], + 'moment after weekday' => [ + true, + Moment::fromStringInTimeZone('2022-10-09 15:00:00', new \DateTimeZone('Europe/Berlin')), + Weekday::SATURDAY, + new \DateTimeZone('Europe/Berlin'), + ], 'moment before date' => [ false, Moment::fromStringInTimeZone('2022-10-07 15:00:00', new \DateTimeZone('Europe/Berlin')), diff --git a/tests/Moment/IsNotBeforeOrEqualToInTimeZoneTest.php b/tests/Moment/IsNotBeforeOrEqualToInTimeZoneTest.php index 7d28831..18df559 100644 --- a/tests/Moment/IsNotBeforeOrEqualToInTimeZoneTest.php +++ b/tests/Moment/IsNotBeforeOrEqualToInTimeZoneTest.php @@ -8,6 +8,7 @@ use DigitalCraftsman\DateTimePrecision\Moment; use DigitalCraftsman\DateTimePrecision\Month; use DigitalCraftsman\DateTimePrecision\Time; +use DigitalCraftsman\DateTimePrecision\Weekday; use DigitalCraftsman\DateTimePrecision\Year; use PHPUnit\Framework\TestCase; @@ -24,7 +25,7 @@ final class IsNotBeforeOrEqualToInTimeZoneTest extends TestCase public function is_not_before_or_equal_to_in_time_zone_works( bool $expectedResult, Moment $moment, - Time | Date | Month | Year $comparator, + Time | Weekday | Date | Month | Year $comparator, \DateTimeZone $timeZone, ): void { // -- Act & Assert @@ -35,7 +36,7 @@ public function is_not_before_or_equal_to_in_time_zone_works( * @return array */ @@ -60,6 +61,24 @@ public static function dataProvider(): array Time::fromString('15:00:00'), new \DateTimeZone('Europe/Berlin'), ], + 'moment before weekday' => [ + false, + Moment::fromStringInTimeZone('2022-10-07 15:00:00', new \DateTimeZone('Europe/Berlin')), + Weekday::SATURDAY, + new \DateTimeZone('Europe/Berlin'), + ], + 'moment same weekday' => [ + false, + Moment::fromStringInTimeZone('2022-10-08 15:00:00', new \DateTimeZone('Europe/Berlin')), + Weekday::SATURDAY, + new \DateTimeZone('Europe/Berlin'), + ], + 'moment after weekday' => [ + true, + Moment::fromStringInTimeZone('2022-10-09 15:00:00', new \DateTimeZone('Europe/Berlin')), + Weekday::SATURDAY, + new \DateTimeZone('Europe/Berlin'), + ], 'moment before date' => [ false, Moment::fromStringInTimeZone('2022-10-07 15:00:00', new \DateTimeZone('Europe/Berlin')), diff --git a/tests/Moment/IsNotEqualToInTimeZoneTest.php b/tests/Moment/IsNotEqualToInTimeZoneTest.php index 9dac15b..d3e2789 100644 --- a/tests/Moment/IsNotEqualToInTimeZoneTest.php +++ b/tests/Moment/IsNotEqualToInTimeZoneTest.php @@ -8,6 +8,7 @@ use DigitalCraftsman\DateTimePrecision\Moment; use DigitalCraftsman\DateTimePrecision\Month; use DigitalCraftsman\DateTimePrecision\Time; +use DigitalCraftsman\DateTimePrecision\Weekday; use DigitalCraftsman\DateTimePrecision\Year; use PHPUnit\Framework\TestCase; @@ -24,7 +25,7 @@ final class IsNotEqualToInTimeZoneTest extends TestCase public function is_not_equal_to_in_time_zone_works( bool $expectedResult, Moment $moment, - Time | Date | Month | Year $comparator, + Time | Weekday | Date | Month | Year $comparator, \DateTimeZone $timeZone, ): void { // -- Act & Assert @@ -35,7 +36,7 @@ public function is_not_equal_to_in_time_zone_works( * @return array */ @@ -60,6 +61,24 @@ public static function dataProvider(): array Time::fromString('15:00:00'), new \DateTimeZone('Europe/Berlin'), ], + 'moment before weekday' => [ + true, + Moment::fromStringInTimeZone('2022-10-08 14:55:00', new \DateTimeZone('Europe/Berlin')), + Weekday::SUNDAY, + new \DateTimeZone('Europe/Berlin'), + ], + 'moment same weekday' => [ + false, + Moment::fromStringInTimeZone('2022-10-08 15:00:00', new \DateTimeZone('Europe/Berlin')), + Weekday::SATURDAY, + new \DateTimeZone('Europe/Berlin'), + ], + 'moment after weekday' => [ + true, + Moment::fromStringInTimeZone('2022-10-08 15:05:00', new \DateTimeZone('Europe/Berlin')), + Weekday::THURSDAY, + new \DateTimeZone('Europe/Berlin'), + ], 'moment before date' => [ true, Moment::fromStringInTimeZone('2022-10-07 15:00:00', new \DateTimeZone('Europe/Berlin')), diff --git a/tests/Moment/WeekdayTest.php b/tests/Moment/WeekdayTest.php new file mode 100644 index 0000000..8d854f1 --- /dev/null +++ b/tests/Moment/WeekdayTest.php @@ -0,0 +1,93 @@ +weekday()); + } + + /** + * @return array + */ + public static function dataProviderForTime(): array + { + return [ + 'same weekday in UTC' => [ + Weekday::SATURDAY, + Moment::fromString('2022-10-08 15:00:00'), + ], + 'weekday adapted due to weekday zone difference' => [ + Weekday::SATURDAY, + Moment::fromStringInTimeZone('2022-10-08 00:00:00', new \DateTimeZone('Europe/Berlin')) + ->toTimeZone(new \DateTimeZone('Europe/Berlin')), + ], + ]; + } + + /** + * @test + * + * @dataProvider dataProviderForTimeInTimeZone + * + * @covers ::weekdayInTimeZone + */ + public function weekday_in_weekday_zone_works( + Weekday $expectedResult, + Moment $dateTime, + \DateTimeZone $weekdayZone, + ): void { + // -- Act & Assert + self::assertEquals($expectedResult, $dateTime->weekdayInTimeZone($weekdayZone)); + } + + /** + * @return array + */ + public static function dataProviderForTimeInTimeZone(): array + { + return [ + 'same weekday in UTC' => [ + Weekday::SATURDAY, + Moment::fromString('2022-10-08 15:00:00'), + new \DateTimeZone('UTC'), + ], + 'adapting weekday for two hours through timezone difference' => [ + Weekday::SUNDAY, + Moment::fromString('2022-10-08 23:00:00'), + new \DateTimeZone('Europe/Berlin'), + ], + 'same weekday when timezone was used for creation of datetime' => [ + Weekday::SATURDAY, + Moment::fromStringInTimeZone('2022-10-08 15:00:00', new \DateTimeZone('Europe/Berlin')), + new \DateTimeZone('Europe/Berlin'), + ], + ]; + } +} diff --git a/tests/Serializer/WeekdayNormalizerTest.php b/tests/Serializer/WeekdayNormalizerTest.php new file mode 100644 index 0000000..bbcebad --- /dev/null +++ b/tests/Serializer/WeekdayNormalizerTest.php @@ -0,0 +1,114 @@ +normalize($weekday); + $denormalizedData = $normalizer->denormalize($normalizedData, Weekday::class); + + // -- Assert + self::assertEquals($weekday, $denormalizedData); + } + + /** + * @test + * + * @covers ::normalize + */ + public function weekday_normalization_with_null_works(): void + { + // -- Arrange + $normalizer = new WeekdayNormalizer(); + + // -- Act + $normalizedData = $normalizer->normalize(null); + + // -- Assert + self::assertNull($normalizedData); + } + + /** + * @test + * + * @covers ::denormalize + */ + public function weekday_denormalization_with_null_works(): void + { + // -- Arrange + $normalizer = new WeekdayNormalizer(); + + // -- Act + $denormalizedData = $normalizer->denormalize(null, Weekday::class); + + // -- Assert + self::assertNull($denormalizedData); + } + + /** + * @test + * + * @covers ::supportsNormalization + */ + public function supports_normalization(): void + { + // -- Arrange + $weekday = Weekday::TUESDAY; + + $normalizer = new WeekdayNormalizer(); + + // -- Act & Assert + self::assertTrue($normalizer->supportsNormalization($weekday)); + } + + /** + * @test + * + * @covers ::supportsNormalization + */ + public function supports_normalization_fails(): void + { + // -- Arrange + $year = Year::fromString('2022'); + + $normalizer = new WeekdayNormalizer(); + + // -- Act & Assert + self::assertFalse($normalizer->supportsNormalization($year)); + } + + /** + * @test + * + * @covers ::supportsDenormalization + */ + public function supports_denormalization(): void + { + // -- Arrange + $normalizer = new WeekdayNormalizer(); + + // -- Act & Assert + self::assertTrue($normalizer->supportsDenormalization(null, Weekday::class)); + } +} diff --git a/tests/Serializer/WeekdaysNormalizerTest.php b/tests/Serializer/WeekdaysNormalizerTest.php new file mode 100644 index 0000000..dc7d643 --- /dev/null +++ b/tests/Serializer/WeekdaysNormalizerTest.php @@ -0,0 +1,121 @@ +normalize($weekdays); + $denormalizedData = $normalizer->denormalize($normalizedData, Weekdays::class); + + // -- Assert + self::assertEquals($weekdays, $denormalizedData); + } + + /** + * @test + * + * @covers ::normalize + */ + public function weekday_normalization_with_null_works(): void + { + // -- Arrange + $normalizer = new WeekdaysNormalizer(); + + // -- Act + $normalizedData = $normalizer->normalize(null); + + // -- Assert + self::assertNull($normalizedData); + } + + /** + * @test + * + * @covers ::denormalize + */ + public function weekdays_denormalization_with_null_works(): void + { + // -- Arrange + $normalizer = new WeekdaysNormalizer(); + + // -- Act + $denormalizedData = $normalizer->denormalize(null, Weekdays::class); + + // -- Assert + self::assertNull($denormalizedData); + } + + /** + * @test + * + * @covers ::supportsNormalization + */ + public function supports_normalization(): void + { + // -- Arrange + $weekdays = new Weekdays([ + Weekday::MONDAY, + Weekday::SATURDAY, + ]); + + $normalizer = new WeekdaysNormalizer(); + + // -- Act & Assert + self::assertTrue($normalizer->supportsNormalization($weekdays)); + } + + /** + * @test + * + * @covers ::supportsNormalization + */ + public function supports_normalization_fails(): void + { + // -- Arrange + $year = Year::fromString('2022'); + + $normalizer = new WeekdaysNormalizer(); + + // -- Act & Assert + self::assertFalse($normalizer->supportsNormalization($year)); + } + + /** + * @test + * + * @covers ::supportsDenormalization + */ + public function supports_denormalization(): void + { + // -- Arrange + $normalizer = new WeekdaysNormalizer(); + + // -- Act & Assert + self::assertTrue($normalizer->supportsDenormalization(null, Weekdays::class)); + } +} diff --git a/tests/Weekday/CompareToTest.php b/tests/Weekday/CompareToTest.php new file mode 100644 index 0000000..1815b05 --- /dev/null +++ b/tests/Weekday/CompareToTest.php @@ -0,0 +1,61 @@ +compareTo($comparator)); + } + + /** + * @return array + */ + public static function dataProvider(): array + { + return [ + '1 weekday later' => [ + 1, + Weekday::THURSDAY, + Weekday::WEDNESDAY, + ], + 'same weekday' => [ + 0, + Weekday::SATURDAY, + Weekday::SATURDAY, + ], + '1 weekday before' => [ + -1, + Weekday::TUESDAY, + Weekday::WEDNESDAY, + ], + '2 weekdays before' => [ + -1, + Weekday::MONDAY, + Weekday::WEDNESDAY, + ], + ]; + } +} diff --git a/tests/Weekday/ConstructionTest.php b/tests/Weekday/ConstructionTest.php new file mode 100644 index 0000000..b6386b8 --- /dev/null +++ b/tests/Weekday/ConstructionTest.php @@ -0,0 +1,68 @@ +isEqualTo(Weekday::fromDateTime($moment->dateTime))); + } + + /** + * @return array + */ + public static function dataProvider(): array + { + return [ + 'monday' => [ + Weekday::MONDAY, + Moment::fromString('2022-10-10 22:15:00'), + ], + 'tuesday' => [ + Weekday::TUESDAY, + Moment::fromString('2022-10-11 22:15:00'), + ], + 'wednesday' => [ + Weekday::WEDNESDAY, + Moment::fromString('2022-10-12 22:15:00'), + ], + 'thursday' => [ + Weekday::THURSDAY, + Moment::fromString('2022-10-13 22:15:00'), + ], + 'friday' => [ + Weekday::FRIDAY, + Moment::fromString('2022-10-14 22:15:00'), + ], + 'saturday' => [ + Weekday::SATURDAY, + Moment::fromString('2022-10-15 22:15:00'), + ], + 'sunday' => [ + Weekday::SUNDAY, + Moment::fromString('2022-10-16 22:15:00'), + ], + ]; + } +} diff --git a/tests/Weekday/DayOfWeekTest.php b/tests/Weekday/DayOfWeekTest.php new file mode 100644 index 0000000..b42945e --- /dev/null +++ b/tests/Weekday/DayOfWeekTest.php @@ -0,0 +1,67 @@ +dayOfWeek()); + } + + /** + * @return array + */ + public static function dataProvider(): array + { + return [ + 'monday' => [ + 1, + Weekday::MONDAY, + ], + 'tuesday' => [ + 2, + Weekday::TUESDAY, + ], + 'wednesday' => [ + 3, + Weekday::WEDNESDAY, + ], + 'thursday' => [ + 4, + Weekday::THURSDAY, + ], + 'friday' => [ + 5, + Weekday::FRIDAY, + ], + 'saturday' => [ + 6, + Weekday::SATURDAY, + ], + 'sunday' => [ + 7, + Weekday::SUNDAY, + ], + ]; + } +} diff --git a/tests/Weekday/IsAfterOrEqualToTest.php b/tests/Weekday/IsAfterOrEqualToTest.php new file mode 100644 index 0000000..33540a0 --- /dev/null +++ b/tests/Weekday/IsAfterOrEqualToTest.php @@ -0,0 +1,56 @@ +isAfterOrEqualTo($comparator)); + } + + /** + * @return array + */ + public static function dataProvider(): array + { + return [ + '1 day before' => [ + false, + Weekday::MONDAY, + Weekday::TUESDAY, + ], + 'same day' => [ + true, + Weekday::TUESDAY, + Weekday::TUESDAY, + ], + '1 day later' => [ + true, + Weekday::TUESDAY, + Weekday::MONDAY, + ], + ]; + } +} diff --git a/tests/Weekday/IsAfterTest.php b/tests/Weekday/IsAfterTest.php new file mode 100644 index 0000000..951d4d4 --- /dev/null +++ b/tests/Weekday/IsAfterTest.php @@ -0,0 +1,56 @@ +isAfter($comparator)); + } + + /** + * @return array + */ + public static function dataProvider(): array + { + return [ + '1 day before' => [ + false, + Weekday::MONDAY, + Weekday::TUESDAY, + ], + 'same day' => [ + false, + Weekday::TUESDAY, + Weekday::TUESDAY, + ], + '1 day later' => [ + true, + Weekday::TUESDAY, + Weekday::MONDAY, + ], + ]; + } +} diff --git a/tests/Weekday/IsBeforeOrEqualToTest.php b/tests/Weekday/IsBeforeOrEqualToTest.php new file mode 100644 index 0000000..f6bbfde --- /dev/null +++ b/tests/Weekday/IsBeforeOrEqualToTest.php @@ -0,0 +1,56 @@ +isBeforeOrEqualTo($comparator)); + } + + /** + * @return array + */ + public static function dataProvider(): array + { + return [ + '1 day before' => [ + true, + Weekday::MONDAY, + Weekday::TUESDAY, + ], + 'same day' => [ + true, + Weekday::TUESDAY, + Weekday::TUESDAY, + ], + '1 day later' => [ + false, + Weekday::TUESDAY, + Weekday::MONDAY, + ], + ]; + } +} diff --git a/tests/Weekday/IsBeforeTest.php b/tests/Weekday/IsBeforeTest.php new file mode 100644 index 0000000..685a572 --- /dev/null +++ b/tests/Weekday/IsBeforeTest.php @@ -0,0 +1,56 @@ +isBefore($comparator)); + } + + /** + * @return array + */ + public static function dataProvider(): array + { + return [ + '1 day before' => [ + true, + Weekday::MONDAY, + Weekday::TUESDAY, + ], + 'same day' => [ + false, + Weekday::TUESDAY, + Weekday::TUESDAY, + ], + '1 day later' => [ + false, + Weekday::TUESDAY, + Weekday::MONDAY, + ], + ]; + } +} diff --git a/tests/Weekday/IsEqualToTest.php b/tests/Weekday/IsEqualToTest.php new file mode 100644 index 0000000..e4ac2c4 --- /dev/null +++ b/tests/Weekday/IsEqualToTest.php @@ -0,0 +1,56 @@ +isEqualTo($comparator)); + } + + /** + * @return array + */ + public static function dataProvider(): array + { + return [ + '1 day before' => [ + false, + Weekday::MONDAY, + Weekday::TUESDAY, + ], + 'same day' => [ + true, + Weekday::TUESDAY, + Weekday::TUESDAY, + ], + '1 day later' => [ + false, + Weekday::TUESDAY, + Weekday::MONDAY, + ], + ]; + } +} diff --git a/tests/Weekday/IsNotAfterOrEqualToTest.php b/tests/Weekday/IsNotAfterOrEqualToTest.php new file mode 100644 index 0000000..15d1a7c --- /dev/null +++ b/tests/Weekday/IsNotAfterOrEqualToTest.php @@ -0,0 +1,56 @@ +isNotAfterOrEqualTo($comparator)); + } + + /** + * @return array + */ + public static function dataProvider(): array + { + return [ + '1 day before' => [ + true, + Weekday::MONDAY, + Weekday::TUESDAY, + ], + 'same day' => [ + false, + Weekday::TUESDAY, + Weekday::TUESDAY, + ], + '1 day later' => [ + false, + Weekday::TUESDAY, + Weekday::MONDAY, + ], + ]; + } +} diff --git a/tests/Weekday/IsNotAfterTest.php b/tests/Weekday/IsNotAfterTest.php new file mode 100644 index 0000000..f4c000b --- /dev/null +++ b/tests/Weekday/IsNotAfterTest.php @@ -0,0 +1,56 @@ +isNotAfter($comparator)); + } + + /** + * @return array + */ + public static function dataProvider(): array + { + return [ + '1 day before' => [ + true, + Weekday::MONDAY, + Weekday::TUESDAY, + ], + 'same day' => [ + true, + Weekday::TUESDAY, + Weekday::TUESDAY, + ], + '1 day later' => [ + false, + Weekday::TUESDAY, + Weekday::MONDAY, + ], + ]; + } +} diff --git a/tests/Weekday/IsNotBeforeOrEqualToTest.php b/tests/Weekday/IsNotBeforeOrEqualToTest.php new file mode 100644 index 0000000..8698241 --- /dev/null +++ b/tests/Weekday/IsNotBeforeOrEqualToTest.php @@ -0,0 +1,56 @@ +isNotBeforeOrEqualTo($comparator)); + } + + /** + * @return array + */ + public static function dataProvider(): array + { + return [ + '1 day before' => [ + false, + Weekday::MONDAY, + Weekday::TUESDAY, + ], + 'same day' => [ + false, + Weekday::TUESDAY, + Weekday::TUESDAY, + ], + '1 day later' => [ + true, + Weekday::TUESDAY, + Weekday::MONDAY, + ], + ]; + } +} diff --git a/tests/Weekday/IsNotBeforeTest.php b/tests/Weekday/IsNotBeforeTest.php new file mode 100644 index 0000000..0d03f11 --- /dev/null +++ b/tests/Weekday/IsNotBeforeTest.php @@ -0,0 +1,56 @@ +isNotBefore($comparator)); + } + + /** + * @return array + */ + public static function dataProvider(): array + { + return [ + '1 day before' => [ + false, + Weekday::MONDAY, + Weekday::TUESDAY, + ], + 'same day' => [ + true, + Weekday::TUESDAY, + Weekday::TUESDAY, + ], + '1 day later' => [ + true, + Weekday::TUESDAY, + Weekday::MONDAY, + ], + ]; + } +} diff --git a/tests/Weekday/IsNotEqualToTest.php b/tests/Weekday/IsNotEqualToTest.php new file mode 100644 index 0000000..8c299ba --- /dev/null +++ b/tests/Weekday/IsNotEqualToTest.php @@ -0,0 +1,56 @@ +isNotEqualTo($comparator)); + } + + /** + * @return array + */ + public static function dataProvider(): array + { + return [ + '1 day before' => [ + true, + Weekday::MONDAY, + Weekday::TUESDAY, + ], + 'same day' => [ + false, + Weekday::TUESDAY, + Weekday::TUESDAY, + ], + '1 day later' => [ + true, + Weekday::TUESDAY, + Weekday::MONDAY, + ], + ]; + } +} diff --git a/tests/Weekdays/ConstructionTest.php b/tests/Weekdays/ConstructionTest.php new file mode 100644 index 0000000..2a7625f --- /dev/null +++ b/tests/Weekdays/ConstructionTest.php @@ -0,0 +1,47 @@ +expectException(\InvalidArgumentException::class); + + // -- Act + new Weekdays([ + Weekday::MONDAY, + Weekday::MONDAY, + Weekday::TUESDAY, + ]); + } +} diff --git a/tests/Weekdays/ContainsTest.php b/tests/Weekdays/ContainsTest.php new file mode 100644 index 0000000..6dda7cc --- /dev/null +++ b/tests/Weekdays/ContainsTest.php @@ -0,0 +1,58 @@ +contains($comparator)); + } + + /** + * @return array + */ + public static function dataProvider(): array + { + return [ + 'tuesday' => [ + true, + new Weekdays([ + Weekday::TUESDAY, + Weekday::WEDNESDAY, + ]), + Weekday::TUESDAY, + ], + 'thursday' => [ + false, + new Weekdays([ + Weekday::MONDAY, + Weekday::WEDNESDAY, + ]), + Weekday::THURSDAY, + ], + ]; + } +} diff --git a/tests/Weekdays/NormalizationTest.php b/tests/Weekdays/NormalizationTest.php new file mode 100644 index 0000000..17e8b85 --- /dev/null +++ b/tests/Weekdays/NormalizationTest.php @@ -0,0 +1,35 @@ +normalize(); + $denormalizedWeekdays = Weekdays::denormalize($normalizedWeekdays); + + // -- Assert + self::assertEquals($weekdays, $denormalizedWeekdays); + } +} diff --git a/tests/Weekdays/NotContainsTest.php b/tests/Weekdays/NotContainsTest.php new file mode 100644 index 0000000..58d302b --- /dev/null +++ b/tests/Weekdays/NotContainsTest.php @@ -0,0 +1,59 @@ +notContains($comparator)); + } + + /** + * @return array + */ + public static function dataProvider(): array + { + return [ + 'tuesday' => [ + true, + new Weekdays([ + Weekday::MONDAY, + Weekday::WEDNESDAY, + ]), + Weekday::TUESDAY, + ], + 'thursday' => [ + false, + new Weekdays([ + Weekday::MONDAY, + Weekday::WEDNESDAY, + Weekday::THURSDAY, + ]), + Weekday::THURSDAY, + ], + ]; + } +}