Valinor/docs/pages/other/dealing-with-dates.md
Romain Canon f232cc0636 feat!: introduce constructor for custom date formats
A new constructor can be registered to declare which format(s) are
supported during the mapping of a date object. By default, any valid
timestamp or ATOM-formatted value will be accepted.

```php
(new \CuyZ\Valinor\MapperBuilder())
    // Both COOKIE and ATOM formats will be accepted
    ->registerConstructor(
        new \CuyZ\Valinor\Mapper\Object\DateTimeFormatConstructor(DATE_COOKIE, DATE_ATOM)
    )
    ->mapper()
    ->map(DateTimeInterface::class, 'Monday, 08-Nov-1971 13:37:42 UTC');
```

The previously very opinionated behaviour has been removed, but can be
temporarily used to help with the migration.

```php
(new \CuyZ\Valinor\MapperBuilder())
    ->registerConstructor(
        new \CuyZ\Valinor\Mapper\Object\BackwardCompatibilityDateTimeConstructor()
    )
    ->mapper()
    ->map(DateTimeInterface::class, 'Monday, 08-Nov-1971 13:37:42 UTC');
```
2022-09-01 12:24:24 +02:00

1.8 KiB

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 accepted.

If other formats are to be supported, they need to be registered using the following constructor:

(new \CuyZ\Valinor\MapperBuilder())
    // Both `Cookie` and `ATOM` formats will be accepted
    ->registerConstructor(
        new \CuyZ\Valinor\Mapper\Object\DateTimeFormatConstructor(DATE_COOKIE, DATE_ATOM)
    )
    ->mapper()
    ->map(DateTimeInterface::class, 'Monday, 08-Nov-1971 13:37:42 UTC');

Custom date class implementation

By default, the library will map a DateTimeInterface to a DateTimeImmutable instance. If other implementations are to be supported, custom constructors can be used.

Here is an implementation example for the nesbot/carbon library:

(new MapperBuilder())
    // When the mapper meets a `DateTimeInterface` it will convert it to Carbon
    ->infer(DateTimeInterface::class, fn () => \Carbon\Carbon::class)
    
    // We teach the mapper how to create a Carbon instance
    ->registerConstructor(function (string $time): \Carbon\Carbon {
        // Only `Cookie` format will be accepted
        return Carbon::createFromFormat(DATE_COOKIE, $time);
    })
    
    // Carbon uses its own exceptions, so we need to wrap it for the mapper
    ->filterExceptions(function (Throwable $exception) {
        if ($exception instanceof \Carbon\Exceptions\Exception) {
            return \CuyZ\Valinor\Mapper\Tree\Message\ThrowableMessage::from($exception);
        }
                    
        throw $exception;
    })
    
    ->mapper()
    ->map(DateTimeInterface::class, 'Monday, 08-Nov-1971 13:37:42 UTC');