Req #53831 [Com]: DateInterval constructor does not handle valid ISO 8601 strings

From: Date: Thu, 10 Jan 2019 19:15:05 +0000
Subject: Req #53831 [Com]: DateInterval constructor does not handle valid ISO 8601 strings
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-218888@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=53831&edit=1 ID: 53831 Comment by: mdwyer at michaelmdwyer dot com Reported by: pallinger at dsd dot sztaki dot hu Summary: DateInterval constructor does not handle valid ISO 8601 strings Status: Open Type: Feature/Change Request Package: Date/time related Operating System: ubuntu linux 10.10 PHP Version: 5.3.5 Block user comment: N Private report: N New Comment: This appears to still be an issue with PHP 7.2, despite them adding a microseconds field to DateInterval. My current workaround is: $fractional = new DateInterval('PT0S'); $fractional->f = ".{$microseconds}"; $fractional->invert = $seconds < 0; return (new DateTime("@{$seconds}"))->add($fractional); Previous Comments: ------------------------------------------------------------------------ [2017-12-05 22:46:04] sloanlance+php dot net at gmail dot com I'm surprised this bug has persisted since 2011-01-24. This seems to have been implemented incorrectly from the beginning. ISO 8601 has mentioned support for fractional parts since at least 2004. That is, it supports a decimal fraction to the smallest time value in a representation. For example, the following representations are valid ISO 8601 intervals, but will cause the DateInterval constructor to throw exceptions: P0.5Y P2.3D P1DT1.5H PT585.829S I appreciate the attempted workaround by "jdp2234 at hotmail dot com", but it appears to only support milliseconds. It doesn't seem to address fractions in other parts of interval representations. ------------------------------------------------------------------------ [2012-04-02 10:47:20] jdp2234 at hotmail dot com http://joshp.me/dateinterval-milliseconds/ Quick class to get around it, while the bug still exists... class DateIntervalFractions extends DateInterval { public $milliseconds; public function __construct($interval_spec) { $this->milliseconds = 0; $matches = array(); preg_match_all("#([0-9]*[.,]?[0-9]*) [S]#",$interval_spec,$matches); foreach ($matches[0] as $result) { $original = $result; list($seconds,$milliseconds) = explode(".",substr($result,0,-1)); $this->milliseconds = $milliseconds / pow(10,strlen($milliseconds) - 3); // Replace the milliseconds back to seconds, // and let the original constructor do the rest. $interval_spec = str_replace($original,$seconds . "S",$interval_spec); } parent::__construct($interval_spec); } } ------------------------------------------------------------------------ [2011-10-12 16:09:31] dagguh at gmail dot com http://en.wikipedia.org/wiki/Iso8601#Durations This decimal fraction may be specified with either a comma or a full stop, as in "P0,5Y" or "P0.5Y". Remember to accept both comma and a full stop. ------------------------------------------------------------------------ [2011-01-24 18:41:19] pallinger at dsd dot sztaki dot hu Description: ------------ --- From manual page: http://www.php.net/dateinterval.construct --- The documentation says that "Each duration period is represented by an integer value followed by a period designator.", however, the ISO 8601 allows non-integer values for the last number (http://en.wikipedia.org/wiki/ISO_8601#Durations). This is quite important if I want to parse XML data which contains millisecond-precision durations, as the seconds will surely not be integers. Test script: --------------- <?php var_dump(new DateInterval('PT1.1S')); ?> Expected result: ---------------- Should print out a valid DateInterval object, eg.: object(DateInterval)#1 (8) { ["y"]=> int(0) ["m"]=> int(0) ["d"]=> int(0) ["h"]=> int(0) ["i"]=> int(0) ["s"]=> float(1.1) ["invert"]=> int(0) ["days"]=> bool(false) } It could also include a millisecond/microsecond/nanosecond field to accomodate additional precision. However, if the durations that are stored are still integers, it would be difficult to handle durations like "P0.5Y". Actual result: -------------- PHP Fatal error: Uncaught exception 'Exception' with message 'DateInterval::__construct(): Unknown or bad format (PT1.1S)' in -:1 Stack trace: #0 -(1): DateInterval->__construct('PT1.1S') #1 {main} thrown in - on line 1 ------------------------------------------------------------------------ -- Edit this bug report at https://bugs.php.net/bug.php?id=53831&edit=1

« previous php.bugs (#218888) next »