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

A DateTime filter #85

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions docs/book/standard-filters.md
Original file line number Diff line number Diff line change
Expand Up @@ -713,6 +713,30 @@ All options can be set at instantiation or by using a related method. For exampl
methods for `target` are `getTarget()` and `setTarget()`. You can also use the `setOptions()` method
which accepts an array of all options.

## DateTime

Converts `$value` to a `DateTime` or `DateTimeImmutable` instance.

### Supported Options

The following options are supported for `Zend\Filter\DateTime`:

- `immutable`: `true` if a `DateTimeImmutable` instance should be returned,
`false` (the default) if `DateTime` is expected. Methods for getting/setting
this option are available: `isImmutable()` and `setImmutable(bool)`.

### Basic usage

```php
$filter = new Zend\Filter\DateTime();
$dt = $filter->filter('2019-04-24T14:33:12+02:00');
// $dt is a DateTime instance with the above date, time and timezone

$filter = new Zend\Filter\DateTime(true);
$dt = $filter->filter('2019-04-24T14:34:34+02:00');
// $dt is a DateTimeImmutable instance with the above date, time and timezone
```

## Digits

Returns the string `$value`, removing all but digits.
Expand Down
108 changes: 108 additions & 0 deletions src/DateTime.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/

namespace Zend\Filter;

use DateTime as PhpDateTime;
use DateTimeImmutable;
use Traversable;

class DateTime extends AbstractFilter
{
/** @var array */
protected $options = [
'immutable' => false,
];

/** @param array|bool|null|Traversable $immutableOrOptions */
public function __construct($immutableOrOptions = null)
{
if ($immutableOrOptions !== null) {
if ($immutableOrOptions instanceof Traversable) {
$immutableOrOptions = iterator_to_array($immutableOrOptions);
}

if (is_array($immutableOrOptions)) {
if (isset($immutableOrOptions['immutable'])) {
$this->setOptions($immutableOrOptions);
} else {
$this->setImmutable($immutableOrOptions);
}
} else {
$this->setImmutable($immutableOrOptions);
}
}
}

/**
* Defined by Zend\Filter\FilterInterface
*
* Returns (DateTimeInterface) $value
*
* If the value provided is neither a string nor instance of
* DateTimeInterface, it will remain unfiltered
*
* @param mixed $value
* @return mixed
*/
public function filter($value)
{
$immutable = $this->isImmutable();

$isDateTime = $value instanceof PhpDateTime;
$isDateTimeImmutable = $value instanceof DateTimeImmutable;

if (($isDateTimeImmutable && $immutable)
|| ($isDateTime && ! $immutable)
|| ! ($isDateTime || $isDateTimeImmutable || is_string($value))) {
// no conversion
return $value;
}

if ($isDateTimeImmutable && ! $immutable) {
// create mutable DateTime from DateTimeImmutable
$mutableDateTime = new PhpDateTime('@0');
$mutableDateTime = $mutableDateTime->sub($value->diff($mutableDateTime));
$mutableDateTime->setTimezone($value->getTimezone());
return $mutableDateTime;
}

if ($isDateTime && $immutable) {
// create DateTimeImmutable from mutable DateTime
return DateTimeImmutable::createFromMutable($value);
}

if ($immutable) {
return new DateTimeImmutable($value);
}

return new PhpDateTime($value);
}

/** @return bool */
public function isImmutable()
{
return $this->options['immutable'];
}

/**
* @param bool $immutable
* @return self
* @throws Exception\InvalidArgumentException
*/
public function setImmutable($immutable)
{
if (! is_bool($immutable)) {
throw new Exception\InvalidArgumentException('Expected $immutable to be a boolean');
}

$this->options['immutable'] = $immutable;
return $this;
}
}
103 changes: 103 additions & 0 deletions test/DateTimeTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/

namespace ZendTest\Filter;

use DateTime;
use DateTimeImmutable;
use PHPUnit\Framework\TestCase;
use Zend\Filter\Exception;
use Zend\Filter\DateTime as DateTimeFilter;

class DateTimeTest extends TestCase
{
public function testConstructorDefaults()
{
$filter = new DateTimeFilter();

$this->assertEquals(false, $filter->isImmutable());
}

public function testConstructorOptions()
{
$filter = new DateTimeFilter(['immutable' => true]);

$this->assertEquals(true, $filter->isImmutable());
}

public function testConstructorParams()
{
$filter = new DateTimeFilter(true);

$this->assertEquals(true, $filter->isImmutable());
}

/**
* @param bool $immutable
* @param mixed $value
* @dataProvider noConversionProvider
*/
public function testNoConversion($immutable, $value)
{
$filter = new DateTimeFilter($immutable);
$this->assertSame($value, $filter->filter($value));
}

public function testRealConversion()
{
$dateTime = '2019-04-24T14:25:55.123+02:00';
$filter = new DateTimeFilter(true);

$filtered = $filter->filter($dateTime);

$this->assertInstanceOf(DateTimeImmutable::class, $filtered);
$this->assertEquals(new DateTimeImmutable($dateTime), $filtered);

$dateTime = '2019-04-24T14:26:22.456+02:00';
$filter = new DateTimeFilter();

$filtered = $filter->filter($dateTime);

$this->assertInstanceOf(DateTime::class, $filtered);
$this->assertEquals(new DateTime($dateTime), $filter->filter($dateTime));
}

public function testSimpleConversion()
{
$dateTime = new DateTime();
$filter = new DateTimeFilter(true);

$filtered = $filter->filter($dateTime);

$this->assertInstanceOf(DateTimeImmutable::class, $filtered);
$this->assertEquals($dateTime, $filtered);

$dateTime = new DateTimeImmutable();
$filter = new DateTimeFilter();

$filtered = $filter->filter($dateTime);

$this->assertInstanceOf(DateTime::class, $filtered);
$this->assertEquals($dateTime, $filter->filter($dateTime));
}

public function noConversionProvider()
{
return [
[false, new DateTime()],
[false, null],
[false, 42],
[false, 3.14],
[true, new DateTimeImmutable()],
[true, null],
[true, 42],
[true, 3.14],
];
}
}