Bug #66156 [Opn]: date_create_from_format() fails for "!ndY" format

From: Date: Sat, 23 Nov 2013 16:46:30 +0000
Subject: Bug #66156 [Opn]: date_create_from_format() fails for "!ndY" format
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-182902@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=66156&edit=1 ID: 66156 Updated by: salathe@php.net Reported by: mjpelmear at gmail dot com Summary: date_create_from_format() fails for "!ndY" format Status: Open Type: Bug Package: Date/time related Operating System: Any PHP Version: master-Git-2013-11-23 (Git) Block user comment: N Private report: N New Comment: It looks like the date string is taken to be (in Y-m-d format for presentation) 0989-30-71, which when wrapped around into a “normal” date gives the mentioned 0991-08-10. The string is broken up as follows: “n” wants a two-digit month number, it accepts “30”. “d” wants a two-digit day of month number, it accepts “71”. “Y” wants a four-digit year number, it accepts “989”. The warning is generated when “30” and “71” are checked for being “valid" month and day of month numbers, respectively. Internally, in many cases, there is no difference between using the leading-zero format character and the non-leading zero one. E.g. “n” and “m” are extracted using the same internal code. These are described in the documentation already. Your claim that this date format is not supported is incorrect. It is supported; it simply doesn’t behave as you were expecting. Should format characters like “n” and “m” give different outcomes for this function? Perhaps, but that’s opening the time string parsing up to a not insignificant re-write. Should the string parsing try to be a little more “clever” by attempting to get a “valid” date from the multiple possible combinations in ambiguous date strings? Perhaps, but do we want to introduce this complexity (and we’ll never get it right 100% of the time)? I don’t have an answer. In your particular case, I can only suggest manipulating the date string such that it is no longer ambiguous; perhaps by adding appropriate delimiter characters between the different date parts. Previous Comments: ------------------------------------------------------------------------ [2013-11-23 06:20:06] mjpelmear at gmail dot com If someone wants to provide feedback as to which of the following is preferable to fix this problem, I would be happy to make a pull request to fix it: 1) We should simply provide an appropriate error message. or 2) We should implement some sort of lookahead to actually handle this type of format. or 3) Something else? ------------------------------------------------------------------------ [2013-11-23 06:15:17] mjpelmear at gmail dot com Description: ------------ date_create_from_format() improperly parses dates in "!ndY" format, but reports the problem as being with the data, not with the parser's [lack of] support for the format. This date format is a strange one, but we encountered it in data files received from a client, so it seems to be in use, albeit undesirable. Analysis: --------- The root issue is that the parser is reading the incoming string from left to right, but when doing so it has no way to determine whether the month is one or two digits (since "n" means the month would be a single digit if < 10). See timelib_parse_from_format() in ext/date/lib/parse_date.c. Note that while it would be impossible to support a format like "!njY" because this would have some ambiguous cases ("1112013" for example), it is at least possible to support "!ndY" and similar cases. Test script: --------------- $date = date_create_from_format( '!ndY', '3071989' ); assert( $date->format('Y-m-d') == '1989-03-07' ); // assertion fails. print_r(DateTime::getLastErrors()); echo PHP_EOL; print_r($date); echo PHP_EOL; Expected result: ---------------- The assertion should succeed, or we should receive a meaningful error message indicating that this date format isn't supported. Actual result: -------------- The assertion fails (DateTime shows the date as "0991-08-10", in Y-m-d format). DateTime::getLastErrors() simply indicates that the parsed date was invalid ("The parsed date was invalid"). ------------------------------------------------------------------------ -- Edit this bug report at https://bugs.php.net/bug.php?id=66156&edit=1

« previous php.bugs (#182902) next »