diff --git a/docs/pages/how-to/deal-with-dates.md b/docs/pages/how-to/deal-with-dates.md index 65e5f300..fa9470f8 100644 --- a/docs/pages/how-to/deal-with-dates.md +++ b/docs/pages/how-to/deal-with-dates.md @@ -1,7 +1,7 @@ # Dealing with dates When the mapper builds a date object, it has to know which format(s) are -supported. By default, any valid timestamp or ATOM-formatted value will be +supported. By default, any valid timestamp or RFC 3339-formatted value will be accepted. If other formats are to be supported, they need to be registered using the diff --git a/src/Library/Settings.php b/src/Library/Settings.php index 143eac2f..54d2617d 100644 --- a/src/Library/Settings.php +++ b/src/Library/Settings.php @@ -14,7 +14,11 @@ final class Settings { /** @var non-empty-array */ - public const DEFAULT_SUPPORTED_DATETIME_FORMATS = [DATE_ATOM, 'U']; + public const DEFAULT_SUPPORTED_DATETIME_FORMATS = [ + 'Y-m-d\\TH:i:sP', // RFC 3339 + 'Y-m-d\\TH:i:s.uP', // RFC 3339 with microseconds + 'U', // Unix Timestamp + ]; /** @var array */ public array $inferredMapping = []; diff --git a/src/Mapper/Object/DateTimeFormatConstructor.php b/src/Mapper/Object/DateTimeFormatConstructor.php index 2e2c53f8..98298f22 100644 --- a/src/Mapper/Object/DateTimeFormatConstructor.php +++ b/src/Mapper/Object/DateTimeFormatConstructor.php @@ -14,7 +14,7 @@ * date formats should be allowed during mapping. * * By default, if this constructor is never registered, the dates will accept - * any valid timestamp or ATOM-formatted value. + * any valid timestamp or RFC 3339-formatted value. * * Usage: * diff --git a/src/MapperBuilder.php b/src/MapperBuilder.php index 30c191fa..3cce949e 100644 --- a/src/MapperBuilder.php +++ b/src/MapperBuilder.php @@ -219,7 +219,7 @@ public function registerConstructor(callable|string ...$constructors): self /** * Describes which date formats will be supported during mapping. * - * By default, the dates will accept any valid timestamp or ATOM-formatted + * By default, the dates will accept any valid timestamp or RFC 3339-formatted * value. * * ```php @@ -244,7 +244,7 @@ public function supportDateFormats(string $format, string ...$formats): self /** * Returns the date formats supported during mapping. * - * By default, any valid timestamp or ATOM-formatted value are accepted. + * By default, any valid timestamp or RFC 3339-formatted value are accepted. * Custom formats can be set using method `supportDateFormats()`. * * @return non-empty-array diff --git a/tests/Integration/Mapping/Object/DateTimeMappingTest.php b/tests/Integration/Mapping/Object/DateTimeMappingTest.php index b9803a04..cb3bac5a 100644 --- a/tests/Integration/Mapping/Object/DateTimeMappingTest.php +++ b/tests/Integration/Mapping/Object/DateTimeMappingTest.php @@ -24,7 +24,7 @@ public function test_default_datetime_constructor_cannot_be_used(): void } } - public function test_default_date_constructor_with_valid_atom_format_source_returns_datetime(): void + public function test_default_date_constructor_with_valid_rfc_3339_format_source_returns_datetime(): void { try { $result = (new MapperBuilder()) @@ -37,6 +37,36 @@ public function test_default_date_constructor_with_valid_atom_format_source_retu self::assertSame('2022-08-05T08:32:06+00:00', $result->format(DATE_ATOM)); } + public function test_default_date_constructor_with_valid_rfc_3339_and_milliseconds_format_source_returns_datetime(): void + { + try { + $result = (new MapperBuilder()) + ->mapper() + ->map(DateTimeInterface::class, '2022-08-05T08:32:06.123Z'); + } catch (MappingError $error) { + $this->mappingFail($error); + } + + self::assertSame('1659688326', $result->format('U')); + self::assertSame('123', $result->format('v')); + self::assertSame('123000', $result->format('u')); + } + + public function test_default_date_constructor_with_valid_rfc_3339_and_microseconds_format_source_returns_datetime(): void + { + try { + $result = (new MapperBuilder()) + ->mapper() + ->map(DateTimeInterface::class, '2022-08-05T08:32:06.123456Z'); + } catch (MappingError $error) { + $this->mappingFail($error); + } + + self::assertSame('1659688326', $result->format('U')); + self::assertSame('123', $result->format('v')); + self::assertSame('123456', $result->format('u')); + } + public function test_default_date_constructor_with_valid_timestamp_format_source_returns_datetime(): void { try { @@ -100,7 +130,7 @@ public function test_default_date_constructor_with_invalid_source_throws_excepti $error = $exception->node()->messages()[0]; self::assertSame('1630686564', $error->code()); - self::assertSame("Value 'invalid datetime' does not match any of the following formats: `Y-m-d\TH:i:sP`, `U`.", (string)$error); + self::assertSame("Value 'invalid datetime' does not match any of the following formats: `Y-m-d\TH:i:sP`, `Y-m-d\TH:i:s.uP`, `U`.", (string)$error); } } diff --git a/tests/Unit/MapperBuilderTest.php b/tests/Unit/MapperBuilderTest.php index bd15c959..584be3f2 100644 --- a/tests/Unit/MapperBuilderTest.php +++ b/tests/Unit/MapperBuilderTest.php @@ -54,7 +54,7 @@ public function test_mapper_instance_is_the_same(): void public function test_get_supported_date_formats_returns_defaults_formats_when_not_overridden(): void { - self::assertSame([DATE_ATOM, 'U'], $this->mapperBuilder->supportedDateFormats()); + self::assertSame(['Y-m-d\\TH:i:sP', 'Y-m-d\\TH:i:s.uP', 'U'], $this->mapperBuilder->supportedDateFormats()); } public function test_get_supported_date_formats_returns_configured_values(): void