Skip to content

Commit

Permalink
Merge fc087fe into 6320a9f
Browse files Browse the repository at this point in the history
  • Loading branch information
LucasTheCure committed Apr 4, 2019
2 parents 6320a9f + fc087fe commit 1ca433a
Show file tree
Hide file tree
Showing 4 changed files with 253 additions and 7 deletions.
6 changes: 5 additions & 1 deletion composer.json
@@ -1,5 +1,5 @@
{
"name": "goetas-webservices/xsd2php-runtime",
"name": "lucasthecure/xsd2php-runtime",
"description": "Convert XSD (XML Schema) definitions into PHP classes",
"type": "library",
"authors": [
Expand All @@ -25,6 +25,7 @@
"jms/serializer": "1.4.1|1.6.1|1.6.2"
},
"require-dev": {
"ext-simplexml": "*",
"phpunit/phpunit": "^4.8|^5.0"
},
"autoload": {
Expand All @@ -41,5 +42,8 @@
"branch-alias": {
"dev-master": "0.2-dev"
}
},
"replace": {
"goetas-webservices/xsd2php-runtime": "self.version"
}
}
37 changes: 33 additions & 4 deletions src/Jms/Handler/XmlSchemaDateHandler.php
Expand Up @@ -12,6 +12,8 @@ class XmlSchemaDateHandler implements SubscribingHandlerInterface
{

protected $defaultTimezone;
protected $serializeTimezone;
protected $deserializeTimezone;

public static function getSubscribingMethods()
{
Expand Down Expand Up @@ -61,10 +63,17 @@ public static function getSubscribingMethods()
);
}

public function __construct($defaultTimezone = 'UTC')
/**
* @param string $defaultTimezone default timezone if timezone is absent in deserialized string
* @param null $serializeTimezone timezone of serialized date/datetime/time. Works properly since php 7.0
* @param null $deserializeTimezone timezone of deserialized date/datetime/time. Works properly since php 7.0
* note that $defaultTimezone may be applied first
*/
public function __construct($defaultTimezone = 'UTC', $serializeTimezone = null, $deserializeTimezone = null)
{
$this->defaultTimezone = new \DateTimeZone($defaultTimezone);

$this->serializeTimezone = $serializeTimezone ? new \DateTimeZone($serializeTimezone) : null;
$this->deserializeTimezone = $deserializeTimezone ? new \DateTimeZone($deserializeTimezone) : null;
}

public function deserializeDateIntervalXml(XmlDeserializationVisitor $visitor, $data, array $type){
Expand All @@ -77,7 +86,7 @@ public function deserializeDateIntervalXml(XmlDeserializationVisitor $visitor, $

public function serializeDate(XmlSerializationVisitor $visitor, \DateTime $date, array $type, Context $context)
{

$date = $this->prepareDateTimeBeforeSerialize($date);
$v = $date->format('Y-m-d');

return $visitor->visitSimpleString($v, $type, $context);
Expand All @@ -98,7 +107,7 @@ public function deserializeDate(XmlDeserializationVisitor $visitor, $data, array

public function serializeDateTime(XmlSerializationVisitor $visitor, \DateTime $date, array $type, Context $context)
{

$date = $this->prepareDateTimeBeforeSerialize($date);
$v = $date->format(\DateTime::W3C);

return $visitor->visitSimpleString($v, $type, $context);
Expand All @@ -117,6 +126,7 @@ public function deserializeDateTime(XmlDeserializationVisitor $visitor, $data, a

public function serializeTime(XmlSerializationVisitor $visitor, \DateTime $date, array $type, Context $context)
{
$date = $this->prepareDateTimeBeforeSerialize($date);
$v = $date->format('H:i:s');
if ($date->getTimezone()->getOffset($date) !== $this->defaultTimezone->getOffset($date)) {
$v .= $date->format('P');
Expand All @@ -131,6 +141,10 @@ public function deserializeTime(XmlDeserializationVisitor $visitor, $data, array
return null;
}

if ($this->deserializeTimezone) {
return $this->parseDateTime($data, $type);
}

$data = (string)$data;

return new \DateTime($data, $this->defaultTimezone);
Expand All @@ -144,7 +158,22 @@ private function parseDateTime($data, array $type)
throw new RuntimeException(sprintf('Invalid datetime "%s", expected valid XML Schema dateTime string.', $data));
}

if ($this->deserializeTimezone) {
$datetime->setTimezone($this->deserializeTimezone);
}

return $datetime;
}

private function prepareDateTimeBeforeSerialize(\DateTime $date)
{
if ($this->serializeTimezone) {
$dateCopy = clone $date;
$dateCopy->setTimezone($this->serializeTimezone);
return $dateCopy;
}

return $date;
}
}

143 changes: 141 additions & 2 deletions tests/XmlSchemaDateHandlerDeserializationTest.php
Expand Up @@ -12,7 +12,6 @@
use JMS\Serializer\Metadata\Driver\AnnotationDriver;
use JMS\Serializer\Naming\IdenticalPropertyNamingStrategy;
use JMS\Serializer\XmlDeserializationVisitor;
use JMS\Serializer\XmlSerializationVisitor;
use Metadata\MetadataFactory;

class XmlSchemaDateHandlerDeserializationTest extends \PHPUnit_Framework_TestCase
Expand Down Expand Up @@ -67,7 +66,7 @@ private function initJmsv1($naming, $handlerRegistry, $cons, $dispatcher)

/**
* @dataProvider getDeserializeDate
* @param string $date
* @param string $date
* @param \DateTime $expected
*/
public function testDeserializeDate($date, \DateTime $expected)
Expand All @@ -87,6 +86,53 @@ public function getDeserializeDate()
];
}

/**
* @requires PHP 7.0
* @dataProvider getDeserializeDateWithTimezone
* @param string $date
* @param \DateTime $expected
* @param string $defaultTimezone
* @param string $serializeTimezone
* @param string $deserializeTimezone
*/
public function testDeserializeDateWithTimezone(
$date,
\DateTime $expected,
$defaultTimezone = 'UTC',
$serializeTimezone = null,
$deserializeTimezone = null
) {
$handler = new XmlSchemaDateHandler($defaultTimezone, $serializeTimezone, $deserializeTimezone);
$element = new \SimpleXMLElement("<Date>$date</Date>");
$deserialized = $handler->deserializeDate($this->visitor, $element, [], $this->context);
$this->assertEquals($expected, $deserialized);
}

public function getDeserializeDateWithTimezone()
{
$tzPlus6 = new \DateTimeZone('+06:00');
$tzMinus20 = new \DateTimeZone('-20:00');

return [
// timezone is not set (default timezone is used)
['2015-01-01', new \DateTime('2015-01-01'), 'UTC'],
['2015-01-01', new \DateTime('2015-01-01', $tzPlus6), '+06:00'],
['2015-01-01', new \DateTime('2015-01-01', $tzMinus20), '-20:00'],
// timezone is set (note that default timezone is ignored by php DateTime constructor)
['2015-01-01Z', new \DateTime('2015-01-01+00:00'), 'UTC'],
['2015-01-01Z', new \DateTime('2015-01-01+00:00'), '+06:00'],
['2015-01-01+06:00', new \DateTime('2015-01-01+06:00'), 'UTC'],
['2015-01-01+06:00', new \DateTime('2015-01-01+06:00'), '-20:00'],
// deserialize timezone is set (here we expect timezone shifting to required one)
['2015-01-01Z', new \DateTime('2015-01-01+00:00'), 'UTC', null, 'UTC'],
['2015-01-01Z', new \DateTime('2015-01-01 06:00:00+06:00'), 'UTC', null, '+06:00'],
['2015-01-01Z', new \DateTime('2014-12-31 04:00:00-20:00'), 'UTC', null, '-20:00'],
['2015-01-01+06:00', new \DateTime('2015-01-01+06:00'), 'UTC', null, '+0:00'],
['2015-01-01+06:00', new \DateTime('2015-01-01 02:00:00+8:00'), 'UTC', null, '+8:00'],
['2015-01-01+06:00', new \DateTime('2014-12-30 22:00:00-20:00'), 'UTC', null, '-20:00'],
];
}

/**
* @expectedException \RuntimeException
*/
Expand All @@ -95,4 +141,97 @@ public function testDeserializeInvalidDate()
$element = new \SimpleXMLElement("<Date>2015-01-01T</Date>");
$this->handler->deserializeDate($this->visitor, $element, [], $this->context);
}

/**
* @requires PHP 7.0
* @dataProvider getDeserializeDateTimeWithTimezone
* @param string $date
* @param \DateTime $expected
* @param string $defaultTimezone
* @param string $serializeTimezone
* @param string $deserializeTimezone
*/
public function testDeserializeDateTimeWithTimezone(
$date,
\DateTime $expected,
$defaultTimezone = 'UTC',
$serializeTimezone = null,
$deserializeTimezone = null
) {
$handler = new XmlSchemaDateHandler($defaultTimezone, $serializeTimezone, $deserializeTimezone);
$element = new \SimpleXMLElement("<Datetime>$date</Datetime>");
$deserialized = $handler->deserializeDateTime($this->visitor, $element, [], $this->context);
$this->assertEquals($expected, $deserialized);
}

public function getDeserializeDateTimeWithTimezone()
{
$tzPlus6 = new \DateTimeZone('+06:00');
$tzMinus20 = new \DateTimeZone('-20:00');

return [
// timezone is not set (default timezone is used)
['2015-01-01T10:01:01', new \DateTime('2015-01-01 10:01:01'), 'UTC'],
['2015-01-01T10:01:01', new \DateTime('2015-01-01 10:01:01', $tzPlus6), '+06:00'],
['2015-01-01T10:01:01', new \DateTime('2015-01-01 10:01:01', $tzMinus20), '-20:00'],
// timezone is set (note that default timezone is ignored by php DateTime constructor)
['2015-01-01T10:01:01Z', new \DateTime('2015-01-01 10:01:01+0:00'), 'UTC'],
['2015-01-01T10:01:01Z', new \DateTime('2015-01-01 10:01:01+0:00'), '+06:00'],
['2015-01-01T10:01:01+06:00', new \DateTime('2015-01-01 10:01:01+06:00'), 'UTC'],
['2015-01-01T10:01:01+06:00', new \DateTime('2015-01-01 10:01:01+6:00'), '-20:00'],
// deserialize timezone is set (here we expect timezone shifting to required one)
['2015-01-01T10:01:01Z', new \DateTime('2015-01-01 10:01:01+0:00'), 'UTC', null, 'UTC'],
['2015-01-01T10:01:01Z', new \DateTime('2015-01-01 16:01:01+6:00'), 'UTC', null, '+06:00'],
['2015-01-01T10:01:01Z', new \DateTime('2014-12-31 14:01:01-20:00'), 'UTC', null, '-20:00'],
['2015-01-01T10:01:01+06:00', new \DateTime('2015-01-01 04:01:01+0:00'), 'UTC', null, '+0:00'],
['2015-01-01T10:01:01+06:00', new \DateTime('2015-01-01 12:01:01+8:00'), 'UTC', null, '+8:00'],
['2015-01-01T10:01:01+06:00', new \DateTime('2014-12-31 08:01:01-20:00'), 'UTC', null, '-20:00'],
];
}

/**
* @requires PHP 7.0
* @dataProvider getDeserializeTimeWithTimezone
* @param string $date
* @param \DateTime $expected
* @param string $defaultTimezone
* @param string $serializeTimezone
* @param string $deserializeTimezone
*/
public function testDeserializeTimeWithTimezone(
$date,
\DateTime $expected,
$defaultTimezone = 'UTC',
$serializeTimezone = null,
$deserializeTimezone = null
) {
$handler = new XmlSchemaDateHandler($defaultTimezone, $serializeTimezone, $deserializeTimezone);
$element = new \SimpleXMLElement("<Time>$date</Time>");
$deserialized = $handler->deserializeTime($this->visitor, $element, [], $this->context);
$this->assertEquals($expected, $deserialized);
}

public function getDeserializeTimeWithTimezone()
{
$tzPlus6 = new \DateTimeZone('+06:00');
$tzMinus12 = new \DateTimeZone('-12:00');

return [
// timezone is not set (default timezone is used)
['10:01:01', new \DateTime('10:01:01'), 'UTC'],
['10:01:01', new \DateTime('10:01:01', $tzPlus6), '+06:00'],
['10:01:01', new \DateTime('10:01:01', $tzMinus12), '-12:00'],
// timezone is set (note that default timezone is ignored by php DateTime constructor)
['10:01:01Z', new \DateTime('10:01:01+0:00'), 'UTC'],
['10:01:01+06:00', new \DateTime('10:01:01+06:00'), 'UTC'],
['10:01:01-12:00', new \DateTime('10:01:01-12:00'), 'UTC'],
// deserialize timezone is set (here we expect timezone shifting to required one)
['10:01:01Z', new \DateTime('10:01:01+00:00'), 'UTC', null, 'UTC'],
['10:01:01Z', new \DateTime('16:01:01+06:00'), 'UTC', null, '+06:00'],
['10:01:01Z', new \DateTime('02:01:01-08:00'), 'UTC', null, '-8:00'],
['10:01:01+06:00', new \DateTime('04:01:01+0:00'), 'UTC', null, '+0:00'],
['10:01:01+00:00', new \DateTime('18:01:01+8:00'), 'UTC', null, '+8:00'],
['10:01:01+08:00', new \DateTime('00:01:01-2:00'), 'UTC', null, '-2:00'],
];
}
}
74 changes: 74 additions & 0 deletions tests/XmlSchemaDateHandlerSerializationTest.php
Expand Up @@ -66,6 +66,7 @@ private function initJmsv1($naming, $handlerRegistry, $cons, $dispatcher)
/**
* @dataProvider getSerializeDateTime
* @param \DateTime $date
* @param string $expected
*/
public function testSerializeDateTime(\DateTime $date, $expected)
{
Expand All @@ -87,6 +88,43 @@ public function getSerializeDateTime()
];
}

/**
* @requires PHP 7.0
* @dataProvider getSerializeDateTimeWithTimezone
* @param \DateTime $date
* @param string $expected
* @param string $defaultTimezone
* @param string $serializeTimezone
* @param string $deserializeTimezone
*/
public function testSerializeDateTimeWithTimezone(
\DateTime $date,
$expected,
$defaultTimezone = 'UTC',
$serializeTimezone = null,
$deserializeTimezone = null
) {
$handler = new XmlSchemaDateHandler($defaultTimezone, $serializeTimezone, $deserializeTimezone);
$ret = $handler->serializeDateTime($this->visitor, $date, [], $this->context);
$actual = $ret ? $ret->nodeValue : $this->visitor->getCurrentNode()->nodeValue;
$this->assertEquals($expected, $actual);
}

public function getSerializeDateTimeWithTimezone()
{
return [
// serialize timezone is set (here we expect timezone shifting to required one)
[new \DateTime('2015-01-01 12:00:56+00:00'), '2015-01-01T12:00:56+00:00', 'UTC', 'Z'],
[new \DateTime('2015-01-01 12:00:56+02:00'), '2015-01-01T10:00:56+00:00', 'UTC', 'Z'],
[new \DateTime('2015-01-01 12:00:56+06:00'), '2015-01-01T06:00:56+00:00', 'UTC', '+00:00'],
[new \DateTime('2015-01-01 12:00:56+06:00'), '2015-01-01T12:00:56+06:00', 'UTC', '+06:00'],
[new \DateTime('2015-01-01 12:00:56+00:00'), '2015-01-01T18:00:56+06:00', 'UTC', '+06:00'],
[new \DateTime('2015-01-01 12:00:56+12:00'), '2015-01-01T06:00:56+06:00', 'UTC', '+06:00'],
[new \DateTime('2015-01-01 12:00:56+00:00'), '2015-01-01T06:00:56-06:00', 'UTC', '-06:00'],
[new \DateTime('2015-01-01 12:00:56-12:00'), '2015-01-01T18:00:56-06:00', 'UTC', '-06:00'],
];
}

/**
* @dataProvider getSerializeDate
* @param \DateTime $date
Expand All @@ -110,4 +148,40 @@ public function getSerializeDate()
[new \DateTime('2015-01-01 12:00:56', new \DateTimeZone("Europe/London")), '2015-01-01'],
];
}

/**
* @requires PHP 7.0
* @dataProvider getSerializeDateWithTimezone
* @param \DateTime $date
* @param string $expected
* @param string $defaultTimezone
* @param string $serializeTimezone
* @param string $deserializeTimezone
*/
public function testSerializeDateWithTimezone(
\DateTime $date,
$expected,
$defaultTimezone = 'UTC',
$serializeTimezone = null,
$deserializeTimezone = null
) {
$handler = new XmlSchemaDateHandler($defaultTimezone, $serializeTimezone, $deserializeTimezone);
$ret = $handler->serializeDate($this->visitor, $date, [], $this->context);
$actual = $ret ? $ret->nodeValue : $this->visitor->getCurrentNode()->nodeValue;
$this->assertEquals($expected, $actual);
}

public function getSerializeDateWithTimezone()
{
return [
[new \DateTime('2015-01-01 12:00:56+00:00'), '2015-01-01', 'UTC', 'Z'],
[new \DateTime('2015-01-01 12:00:56+02:00'), '2015-01-01', 'UTC', 'Z'],
[new \DateTime('2015-01-01 12:00:56-02:00'), '2015-01-01', 'UTC', 'Z'],
[new \DateTime('2015-01-01 12:00:56+00:00'), '2015-01-01', 'UTC', '+06:00'],
[new \DateTime('2015-01-01 12:00:56+00:00'), '2015-01-02', 'UTC', '+12:00'],
[new \DateTime('2015-01-01 11:00:50+00:00'), '2014-12-31', 'UTC', '-12:00'],
[new \DateTime('2015-01-01 12:00:56+06:00'), '2015-01-01', 'UTC', '+06:00'],
[new \DateTime('2015-01-01 12:00:56+00:00'), '2015-01-02', 'UTC', '+25:00'],
];
}
}

0 comments on commit 1ca433a

Please sign in to comment.