Skip to content
This repository has been archived by the owner on Jan 30, 2020. It is now read-only.

Commit

Permalink
Merge branch 'feature/79' into develop
Browse files Browse the repository at this point in the history
Close #79
  • Loading branch information
weierophinney committed Nov 19, 2018
2 parents 41e253e + 9d6dd64 commit 09ca8d4
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 4 deletions.
5 changes: 4 additions & 1 deletion CHANGELOG.md
Expand Up @@ -6,7 +6,10 @@ All notable changes to this project will be documented in this file, in reverse

### Added

- Nothing.
- [#79](https://github.com/zendframework/zend-hydrator/pull/79) adds a third, optional parameter to the `DateTimeFormatterStrategy` constructor.
The parameter is a boolean, and, when enabled, a string that can be parsed by
the `DateTime` constructor will still result in a `DateTime` instance during
hydration, even if the string does not follow the provided date-time format.

### Changed

Expand Down
16 changes: 16 additions & 0 deletions docs/book/strategy.md
Expand Up @@ -110,6 +110,22 @@ hydration, the new `DateTime` instance created will set the time element
accordingly. As a specific example, `Y-m-d|` will drop the time component,
ensuring comparisons are based on a midnight time value.

Starting in version 2.5.0, the constructor defines a third, optional argument,
`$dateTimeFallback`. If enabled and hydration fails, the given string is parsed
by the `DateTime` constructor, as demonstrated below:

```php
// Previous behavior:
$strategy = new Zend\Hydrator\Strategy\DateTimeFormatterStrategy('Y-m-d H:i:s.uP');
$hydrated1 = $strategy->hydrate('2016-03-04 10:29:40.123456+01'); // Format is the same; returns DateTime instance
$hydrated2 = $strategy->hydrate('2016-03-04 10:29:40+01'); // Format is different; value is not hydrated

// Using new $dateTimeFallback flag; both values are hydrated:
$strategy = new Zend\Hydrator\Strategy\DateTimeFormatterStrategy('Y-m-d H:i:s.uP', null, true);
$hydrated1 = $strategy->hydrate('2016-03-04 10:29:40.123456+01');
$hydrated2 = $strategy->hydrate('2016-03-04 10:29:40+01');
```

### Zend\\Hydrator\\Strategy\\DefaultStrategy

The `DefaultStrategy` simply proxies everything through, without performing any
Expand Down
17 changes: 15 additions & 2 deletions src/Strategy/DateTimeFormatterStrategy.php
Expand Up @@ -39,17 +39,26 @@ final class DateTimeFormatterStrategy implements StrategyInterface
*/
private $extractionFormat;

/**
* Whether or not to allow hydration of values that do not follow the format exactly.
*
* @var bool
*/
private $dateTimeFallback;

/**
* Constructor
*
* @param string $format
* @param DateTimeZone|null $timezone
* @param bool $dateTimeFallback try to parse with DateTime when createFromFormat fails
*/
public function __construct($format = DateTime::RFC3339, DateTimeZone $timezone = null)
public function __construct($format = DateTime::RFC3339, DateTimeZone $timezone = null, $dateTimeFallback = false)
{
$this->format = (string) $format;
$this->timezone = $timezone;
$this->extractionFormat = preg_replace('/(?<![\\\\])[+|!\*]/', '', $this->format);
$this->dateTimeFallback = (bool) $dateTimeFallback;
}

/**
Expand All @@ -75,7 +84,7 @@ public function extract($value)
* {@inheritDoc}
*
* @param mixed|string $value
* @return mixed|DateTime
* @return mixed|DateTimeInterface
*/
public function hydrate($value)
{
Expand All @@ -87,6 +96,10 @@ public function hydrate($value)
? DateTime::createFromFormat($this->format, $value, $this->timezone)
: DateTime::createFromFormat($this->format, $value);

if ($hydrated === false && $this->dateTimeFallback) {
$hydrated = new DateTime($value, $this->timezone);
}

return $hydrated ?: $value;
}
}
16 changes: 15 additions & 1 deletion test/Strategy/DateTimeFormatterStrategyTest.php
Expand Up @@ -11,6 +11,7 @@

use DateTime;
use DateTimeImmutable;
use DateTimezone;
use PHPUnit\Framework\TestCase;
use stdClass;
use Zend\Hydrator\Strategy\DateTimeFormatterStrategy;
Expand All @@ -28,7 +29,7 @@ public function testHydrate()
$strategy = new DateTimeFormatterStrategy('Y-m-d');
$this->assertEquals('2014-04-26', $strategy->hydrate('2014-04-26')->format('Y-m-d'));

$strategy = new DateTimeFormatterStrategy('Y-m-d', new \DateTimeZone('Asia/Kathmandu'));
$strategy = new DateTimeFormatterStrategy('Y-m-d', new DateTimeZone('Asia/Kathmandu'));

$date = $strategy->hydrate('2014-04-26');
$this->assertEquals('Asia/Kathmandu', $date->getTimezone()->getName());
Expand Down Expand Up @@ -146,4 +147,17 @@ public function formatsWithSpecialCharactersProvider()
'+-appended' => ['Y-m-d+', '2018-02-05'],
];
}

public function testCanHydrateWithDateTimeFallback()
{
$strategy = new DateTimeFormatterStrategy('Y-m-d', null, true);
$date = $strategy->hydrate('2018-09-06T12:10:30');

$this->assertSame('2018-09-06', $date->format('Y-m-d'));

$strategy = new DateTimeFormatterStrategy('Y-m-d', new DateTimeZone('Europe/Prague'), true);
$date = $strategy->hydrate('2018-09-06T12:10:30');

$this->assertSame('Europe/Prague', $date->getTimezone()->getName());
}
}

0 comments on commit 09ca8d4

Please sign in to comment.