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

Commit

Permalink
Merge pull request #8 from Zenith-Kim-Light/rfc3339
Browse files Browse the repository at this point in the history
Added handler for correct processing RFC3339 formatted date/times
  • Loading branch information
mshumakov authored Jun 17, 2020
2 parents a7d141a + 1be548b commit 5f6260b
Show file tree
Hide file tree
Showing 3 changed files with 151 additions and 0 deletions.
5 changes: 5 additions & 0 deletions src/Resources/config/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ services:
tags:
- { name: jms_serializer.subscribing_handler }

lenats.jms_serializer.datetime.date_rfc3339 _handler:
class: LeNats\Services\DateRFC3339Handler
tags:
- { name: jms_serializer.subscribing_handler }

LeNats\:
resource: '../../{Services,Listeners,Commands}'

Expand Down
96 changes: 96 additions & 0 deletions src/Services/DateRFC3339Handler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<?php
declare(strict_types=1);

namespace LeNats\Services;

use DateTime;
use \JMS\Serializer\Handler\SubscribingHandlerInterface;
use \JMS\Serializer\Handler\DateHandler;

/**
* Decorates a DateHandler to bypass a bug with nano precision recognition
* @see https://bugs.php.net/bug.php?id=64814
* @package LeNats\Services
*/
class DateRFC3339Handler implements SubscribingHandlerInterface
{
/**
* @var DateHandler
*/
private $decoratedHandler;

/**
* @var string
*/
private $defaultFormat;

/**
* @param string $defaultFormat
* @param string $defaultTimezone
* @param bool $xmlCData
*/
public function __construct(
string $defaultFormat = DateTime::ATOM, string $defaultTimezone = 'UTC', bool $xmlCData = true
) {
$this->decoratedHandler = new DateHandler($defaultFormat, $defaultTimezone, $xmlCData);
$this->defaultFormat = $defaultFormat;
}

/**
* @param $name
* @param $arguments
*
* @return mixed
*/
public function __call($name, array $arguments)
{
if (method_exists($this->decoratedHandler, $name)) {
switch ($this->defaultFormat) {
case DateTime::ATOM:
case DateTime::RFC3339:
case DateTime::RFC3339_EXTENDED:
case DateTime::W3C:
$arguments[1] = $this->prepare($arguments[1]);
break;
}

return call_user_func_array([$this->decoratedHandler, $name], $arguments);
}

return null;
}

/**
* @inheritDoc
*/
public static function getSubscribingMethods()
{
return DateHandler::getSubscribingMethods();
}

/**
* Удаляет секцию *time-secfrac* из строки времени
* @see https://bugs.php.net/bug.php?id=64814
*
* @param string $paramDatetime
*
* @return string
*/
private function prepare(string $paramDatetime): string
{
preg_match(
'#' . // open tag
'(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2})' // date-time
. '(\.\d+)?' // "Z" | time-numoffset
. '((Z)|([+-].+))?' // time-offset
. '#' // close tag
,
$paramDatetime,
$matches
);
$datetime = $matches[1];
$timeNumoffset = $matches[5] ?? '+00:00';

return $datetime . $timeNumoffset;
}
}
50 changes: 50 additions & 0 deletions tests/Services/DateRFC3339HandlerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php
declare(strict_types=1);

namespace LeNats\Services;

use PHPUnit\Framework\TestCase;
use ReflectionClass;

class DateRFC3339HandlerTest extends TestCase
{
/**
* @dataProvider datetimeProvider
*
* @param string $datetimeRfc3339
* @param $expected
*
* @throws \ReflectionException
*/
public function testPrepare(string $datetimeRfc3339, $expected)
{
$handler = new DateRFC3339Handler();
$reflection = new ReflectionClass($handler);
$method = $reflection->getMethod('prepare');
$method->setAccessible(true);
$actual = $method->invoke($handler, $datetimeRfc3339);
$this->assertEquals($expected, $actual);
}

public function datetimeProvider(): array
{
return [
'RFC3339 formatted date which php can parse'=>[
'2020-06-08T12:46:41+00:00',
'2020-06-08T12:46:41+00:00',
],
'RFC3339 formatted date with numsec'=>[
'2020-06-08T14:50:22.257114',
'2020-06-08T14:50:22+00:00',
],
'RFC3339 formatted date with numsec and Z'=>[
'2020-06-08T14:50:22.257114Z',
'2020-06-08T14:50:22+00:00',
],
'RFC3339 formatted date with numsec and time offset'=>[
'2006-12-12T10:01:02.999999999-04:00',
'2006-12-12T10:01:02-04:00',
],
];
}
}

0 comments on commit 5f6260b

Please sign in to comment.