[php][bug] Fix DateTime microseconds bug in ObjectSerializer (#11213)

* fixing precision for php

* remove a bracket

* handling whitespace

* format comment

* Use regexp to trim needless microseconds

That way we can save timezone suffix.

Co-authored-by: Carmen Quan <cquan@launchdarkly.com>
This commit is contained in:
Yuriy Belenko 2022-01-04 08:41:22 +03:00 committed by GitHub
parent 9f899c5e6d
commit 0a09f1faa3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 96 additions and 8 deletions

View File

@ -120,6 +120,20 @@ class ObjectSerializer
}
}
/**
* Shorter timestamp microseconds to 6 digits length.
*
* @param string $timestamp Original timestamp
*
* @return string the shorten timestamp
*/
public static function sanitizeTimestamp($timestamp)
{
if (!is_string($timestamp)) return $timestamp;
return preg_replace('/(:\d{2}.\d{6})\d*/', '$1', $timestamp);
}
/**
* Take value and turn it into a string suitable for inclusion in
* the path, by url-encoding.
@ -313,10 +327,9 @@ class ObjectSerializer
return new \DateTime($data);
} catch (\Exception $exception) {
// Some API's return a date-time with too high nanosecond
// precision for php's DateTime to handle. This conversion
// (string -> unix timestamp -> DateTime) is a workaround
// for the problem.
return (new \DateTime())->setTimestamp(strtotime($data));
// precision for php's DateTime to handle.
// With provided regexp 6 digits of microseconds saved
return new \DateTime(self::sanitizeTimestamp($data));
}
} else {
return null;

View File

@ -129,6 +129,20 @@ class ObjectSerializer
}
}
/**
* Shorter timestamp microseconds to 6 digits length.
*
* @param string $timestamp Original timestamp
*
* @return string the shorten timestamp
*/
public static function sanitizeTimestamp($timestamp)
{
if (!is_string($timestamp)) return $timestamp;
return preg_replace('/(:\d{2}.\d{6})\d*/', '$1', $timestamp);
}
/**
* Take value and turn it into a string suitable for inclusion in
* the path, by url-encoding.
@ -322,10 +336,9 @@ class ObjectSerializer
return new \DateTime($data);
} catch (\Exception $exception) {
// Some API's return a date-time with too high nanosecond
// precision for php's DateTime to handle. This conversion
// (string -> unix timestamp -> DateTime) is a workaround
// for the problem.
return (new \DateTime())->setTimestamp(strtotime($data));
// precision for php's DateTime to handle.
// With provided regexp 6 digits of microseconds saved
return new \DateTime(self::sanitizeTimestamp($data));
}
} else {
return null;

View File

@ -64,4 +64,66 @@ class ObjectSerializerTest extends TestCase
],
];
}
/**
* @covers ObjectSerializer::sanitizeTimestamp
* @dataProvider provideTimestamps
*/
public function testSanitizeTimestamp(string $timestamp, string $expected): void
{
$this->assertEquals($expected, ObjectSerializer::sanitizeTimestamp($timestamp));
}
/**
* Test datetime deserialization.
*
* @covers ObjectSerializer::deserialize
* @dataProvider provideTimestamps
*
* @see https://github.com/OpenAPITools/openapi-generator/issues/7942
* @see https://github.com/OpenAPITools/openapi-generator/issues/10548
*/
public function testDateTimeParseSecondAccuracy(string $timestamp, string $expected): void
{
$dateTime = ObjectSerializer::deserialize($timestamp, '\DateTime');
$this->assertEquals(new \DateTime($expected), $dateTime);
}
public function provideTimestamps(): array
{
return [
'String from #7942' => [
'2020-11-11T15:17:58.868722633Z',
'2020-11-11T15:17:58.868722Z',
],
'String from #10548' => [
'2021-10-06T20:17:16.076372256Z',
'2021-10-06T20:17:16.076372Z',
],
'Without timezone' => [
'2021-10-06T20:17:16.076372256',
'2021-10-06T20:17:16.076372',
],
'Without microseconds' => [
'2021-10-06T20:17:16',
'2021-10-06T20:17:16',
],
'Without microseconds with timezone' => [
'2021-10-06T20:17:16Z',
'2021-10-06T20:17:16Z',
],
'With numeric timezone' => [
'2021-10-06T20:17:16.076372256+03:00',
'2021-10-06T20:17:16.076372+03:00',
],
'With numeric timezone without delimiter' => [
'2021-10-06T20:17:16.076372256+0300',
'2021-10-06T20:17:16.076372+0300',
],
'With numeric short timezone' => [
'2021-10-06T20:17:16.076372256+03',
'2021-10-06T20:17:16.076372+03',
],
];
}
}