From 9526f7c6bee1435251384410a269ee9d251822ac Mon Sep 17 00:00:00 2001 From: Michael Calcinai Date: Fri, 19 Jul 2019 12:31:21 +1200 Subject: [PATCH 1/3] Support negative dateinterval --- src/Jms/Handler/XmlSchemaDateHandler.php | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/Jms/Handler/XmlSchemaDateHandler.php b/src/Jms/Handler/XmlSchemaDateHandler.php index 11a2b13..1988d12 100644 --- a/src/Jms/Handler/XmlSchemaDateHandler.php +++ b/src/Jms/Handler/XmlSchemaDateHandler.php @@ -1,4 +1,5 @@ attributes('xsi', true); - if (isset($attributes['nil'][0]) && (string) $attributes['nil'][0] === 'true') { + if (isset($attributes['nil'][0]) && (string)$attributes['nil'][0] === 'true') { return null; } - return new \DateInterval((string)$data); + + //Accept negative intervals like -PT1M23S. Safe to assume that "-" doesn't exist elsewhere in a valid interval spec. + $interval = str_replace('-', '', (string)$data, $count); + $dateInterval = new \DateInterval($interval); + + //Invert if a negative sign was found + $dateInterval->invert = !!$count; + + return $dateInterval; } public function serializeDate(XmlSerializationVisitor $visitor, \DateTime $date, array $type, Context $context) From cce628f7e4b49dac547e3f7f8f3184b5187c00f6 Mon Sep 17 00:00:00 2001 From: Michael Calcinai Date: Mon, 22 Jul 2019 19:59:04 +1200 Subject: [PATCH 2/3] Handle natural serialization of DateInterval --- src/Jms/Handler/XmlSchemaDateHandler.php | 44 +++++++++++++++++++++--- 1 file changed, 39 insertions(+), 5 deletions(-) diff --git a/src/Jms/Handler/XmlSchemaDateHandler.php b/src/Jms/Handler/XmlSchemaDateHandler.php index 1988d12..40fa4ad 100644 --- a/src/Jms/Handler/XmlSchemaDateHandler.php +++ b/src/Jms/Handler/XmlSchemaDateHandler.php @@ -1,5 +1,4 @@ 'xml', 'method' => 'deserializeDateIntervalXml', ), + array( + 'type' => 'DateInterval', + 'direction' => GraphNavigator::DIRECTION_SERIALIZATION, + 'format' => 'xml', + 'method' => 'serializeDateInterval', + ), ); } @@ -68,10 +73,9 @@ public function __construct($defaultTimezone = 'UTC') } - public function deserializeDateIntervalXml(XmlDeserializationVisitor $visitor, $data, array $type) - { + public function deserializeDateIntervalXml(XmlDeserializationVisitor $visitor, $data, array $type){ $attributes = $data->attributes('xsi', true); - if (isset($attributes['nil'][0]) && (string)$attributes['nil'][0] === 'true') { + if (isset($attributes['nil'][0]) && (string) $attributes['nil'][0] === 'true') { return null; } @@ -85,9 +89,39 @@ public function deserializeDateIntervalXml(XmlDeserializationVisitor $visitor, $ return $dateInterval; } - public function serializeDate(XmlSerializationVisitor $visitor, \DateTime $date, array $type, Context $context) + public function serializeDateInterval(XmlSerializationVisitor $visitor, \DateInterval $interval, array $type, Context $context) { + $date = array_filter(array( + 'Y' => $interval->y, + 'M' => $interval->m, + 'D' => $interval->d + )); + + // Reading all non-zero time parts. + $time = array_filter(array( + 'H' => $interval->h, + 'M' => $interval->i, + 'S' => $interval->s + )); + + $specString = 'P'; + + // Adding each part to the spec-string. + foreach ($date as $key => $value) { + $specString .= $value . $key; + } + if (count($time) > 0) { + $specString .= 'T'; + foreach ($time as $key => $value) { + $specString .= $value . $key; + } + } + return $visitor->visitSimpleString($specString, $type, $context); + } + + public function serializeDate(XmlSerializationVisitor $visitor, \DateTime $date, array $type, Context $context) + { $v = $date->format('Y-m-d'); return $visitor->visitSimpleString($v, $type, $context); From ac7baad09e2b3f4abf9684d3906bc7cc0425af8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Morzonek?= Date: Tue, 28 Dec 2021 12:26:13 +0100 Subject: [PATCH 3/3] added tests --- src/Jms/Handler/XmlSchemaDateHandler.php | 2 +- ...mlSchemaDateHandlerDeserializationTest.php | 31 ++++++++++++++++++ .../XmlSchemaDateHandlerSerializationTest.php | 32 +++++++++++++++++++ 3 files changed, 64 insertions(+), 1 deletion(-) diff --git a/src/Jms/Handler/XmlSchemaDateHandler.php b/src/Jms/Handler/XmlSchemaDateHandler.php index 40fa4ad..eae4517 100644 --- a/src/Jms/Handler/XmlSchemaDateHandler.php +++ b/src/Jms/Handler/XmlSchemaDateHandler.php @@ -104,7 +104,7 @@ public function serializeDateInterval(XmlSerializationVisitor $visitor, \DateInt 'S' => $interval->s )); - $specString = 'P'; + $specString = ($interval->invert === 1) ? '-P' : 'P'; // Adding each part to the spec-string. foreach ($date as $key => $value) { diff --git a/tests/XmlSchemaDateHandlerDeserializationTest.php b/tests/XmlSchemaDateHandlerDeserializationTest.php index e33df0b..84e33ad 100644 --- a/tests/XmlSchemaDateHandlerDeserializationTest.php +++ b/tests/XmlSchemaDateHandlerDeserializationTest.php @@ -95,4 +95,35 @@ public function testDeserializeInvalidDate() $element = new \SimpleXMLElement("2015-01-01T"); $this->handler->deserializeDate($this->visitor, $element, [], $this->context); } + + /** + * @dataProvider getDeserializeDateInterval + * @param string $interval + * @param \DateInterval $expected + */ + public function testDeserializeDateInterval(string $interval, \DateInterval $expected) + { + $element = new \SimpleXMLElement("$interval"); + $deserialized = $this->handler->deserializeDateIntervalXml($this->visitor, $element, []); + $this->assertEquals($expected, $deserialized); + } + + public function getDeserializeDateInterval() + { + $interval1 = new \DateInterval('PT1M23S'); + $interval2 = new \DateInterval('P2DT3H'); + + $interval1Invert = clone $interval1; + $interval1Invert->invert = 1; + + $interval2Invert = clone $interval2; + $interval2Invert->invert = 1; + + return [ + ['PT1M23S', $interval1], + ['-PT1M23S', $interval1Invert], + ['P2DT3H', $interval2], + ['-P2DT3H', $interval2Invert], + ]; + } } diff --git a/tests/XmlSchemaDateHandlerSerializationTest.php b/tests/XmlSchemaDateHandlerSerializationTest.php index f445aff..637dbaf 100644 --- a/tests/XmlSchemaDateHandlerSerializationTest.php +++ b/tests/XmlSchemaDateHandlerSerializationTest.php @@ -110,4 +110,36 @@ public function getSerializeDate() [new \DateTime('2015-01-01 12:00:56', new \DateTimeZone("Europe/London")), '2015-01-01'], ]; } + + /** + * @dataProvider getSerializeDateInterval + * @param \DateInterval $interval + * @param string $expected + */ + public function testSerializeDateInterval(\DateInterval $interval, string $expected) + { + $ret = $this->handler->serializeDateInterval($this->visitor, $interval, [], $this->context); + + $actual = $ret ? $ret->nodeValue : $this->visitor->getCurrentNode()->nodeValue; + $this->assertEquals($expected, $actual); + } + + public function getSerializeDateInterval() + { + $interval1 = new \DateInterval('PT1M23S'); + $interval2 = new \DateInterval('P2DT3H'); + + $interval1Invert = clone $interval1; + $interval1Invert->invert = 1; + + $interval2Invert = clone $interval2; + $interval2Invert->invert = 1; + + return [ + [$interval1, 'PT1M23S'], + [$interval1Invert, '-PT1M23S'], + [$interval2, 'P2DT3H'], + [$interval2Invert, '-P2DT3H'], + ]; + } }