diff --git a/src/Converter/Time/PhpTimeConverter.php b/src/Converter/Time/PhpTimeConverter.php index 371a66b..3d15111 100644 --- a/src/Converter/Time/PhpTimeConverter.php +++ b/src/Converter/Time/PhpTimeConverter.php @@ -26,6 +26,7 @@ use function dechex; use function explode; use function is_float; use function is_int; +use function str_contains; use function str_pad; use function strlen; use function substr; @@ -142,6 +143,12 @@ class PhpTimeConverter implements TimeConverterInterface return ['sec' => $split[0], 'usec' => '0']; } + // Near zero PHP renders the float in scientific notation ("-1.0E-6"), whose + // exponent would be misparsed as microseconds; fall back instead. + if (str_contains($split[1], 'E')) { + return []; + } + // If the microseconds are less than six characters AND the length of the number is greater than or equal to the // PHP precision, then it's possible that we lost some precision for the microseconds. Return an empty array so // that we can choose to use the fallback converter. diff --git a/tests/Converter/Time/PhpTimeConverterTest.php b/tests/Converter/Time/PhpTimeConverterTest.php index 2036fdd..d8a9245 100644 --- a/tests/Converter/Time/PhpTimeConverterTest.php +++ b/tests/Converter/Time/PhpTimeConverterTest.php @@ -133,6 +133,14 @@ class PhpTimeConverterTest extends TestCase 'unixTimestamp' => '0', 'microseconds' => '0', ], + + // One microsecond before the epoch: PHP renders "-1.0E-6", which must not + // be misparsed as microseconds. + [ + 'uuidTimestamp' => new Hexadecimal('1b21dd213813ff6'), + 'unixTimestamp' => '0', + 'microseconds' => '1', + ], ]; }