Php date_parse ("Feb 2010") gives day == 1
There is what I would call an error in date_parse when there is no day. $d = date_parse("Feb 2010")
will give $d["day"] == 1
.
See the comment on the date_parse man page .
Any good workaround? :-)
UPDATE Date based on published research reports. Unfortunately, this means that they may look different. I want to convert them to a more standard ISO format when displaying links. To help readers, I want to always include only field data (years, month, date). So this should be fair (and just give me a year):
2010
It should be valid, but just give me 2010-02 so to speak:
Feb 2010
UPDATE 2 I have seen two errors so far in date_parse
. He can't make out 2010
. And it gives a day, although there is no day in Feb 2010
.
I can of course write a fix for this, but surely someone has already done this, or ???
source to share
There are no answers, so I am answering my own question. Here are the workarounds I've seen.
// Work around for some bugs in date_parse (tested in PHP 5.5.19)
// http://php.net/manual/en/function.date-parse.php
//
// Date formats that are cannot be parsed correctly withoug this fix:
// 1) "2014" - Valid ISO 8061 date format but not recognized by date_parse.
// 2) "Feb 2010" - Parsed but gives ["day"] => 1.
function date_parse_5_5_bugfix($dateRaw) {
// Check "2014" bug:
$dateRaw = rtrim($dateRaw);
$dateRaw = ltrim($dateRaw);
if (strlen($dateRaw) === 4 && preg_match("/\d{4}/", $dateRaw) === 1) {
$da = date_parse($dateRaw . "-01-01");
$da["month"] = false;
$da["day"] = false;
} else {
$da = date_parse($dateRaw);
if ($da) {
if (array_key_exists("year", $da)
&& array_key_exists("month", $da)
&& array_key_exists("day", $da))
{
if ($da["day"] === 1) {
// Check "Feb 2010" bug:
// http://www.phpliveregex.com/
if (preg_match("/\b0?1(?:\b|T)/", $dateRaw) !== 1) {
$da["day"] = false;
}
}
}
}
}
return $da;
}
Some tests (visual ;-))
$a = date_parse_5_5_bugfix("2014"); print_r($a);
$b = date_parse_5_5_bugfix("feb 2010"); print_r($b);
$c = date_parse_5_5_bugfix("2014-01-01"); print_r($c);
$d = date_parse_5_5_bugfix("2014-11-01T06:43:08Z"); print_r($d);
$e = date_parse_5_5_bugfix("2014-11-01x06:43:08Z"); print_r($e);
source to share
The above fix procedure is excellent Leo, thanks. Unfortunately, he still makes the trip in January, assuming 2014-01 is the same as 2014-01-01 --- we're eleven twelfths of the way from here.
Date formats that PHP can parse that do not contain the day of the month look like (in php_src: date / lib / parse_date.re ):
gnudateshorter = year4 "-" month;
datenoday = monthtext ([ .\t-])* year4;
datenodayrev = year4 ([ .\t-])* monthtext;
Very small, convenient. We can run the same regex on $ dateRaw, essentially reverse engineering what the parser decided.
(Sideways observations: the above excludes formats like 5/2016, which are parsed as "May 20 with some extra characters at the end," they are also similar to day and year formats, so we'll try not to travel around them.)
function date_parse_bugfix($dateRaw) {
$dateRaw = trim($dateRaw);
// Check for just-the-year:
if (strlen($dateRaw) === 4 && preg_match("/\d{4}/", $dateRaw) === 1) {
$da = date_parse($dateRaw . "-01-01");
$da["month"] = false;
$da["day"] = false;
}
else {
$da = date_parse($dateRaw);
if ($da) {
// If we have a suspicious "day 1", check for the three formats above:
if ($da["day"] === 1) {
// Hat tip to http://regex101.com
// We're not actually matching to monthtext (which is looooong),
// just looking for alphabetic characters
if ((preg_match("/^\d{4}\-(0?[0-9]|1[0-2])$/", $dateRaw) === 1) ||
(preg_match("/^[a-zA-Z]+[ .\t-]*\d{4}$/", $dateRaw) === 1) ||
(preg_match("/^\d{4}[ .\t-]*[a-zA-Z]+$/", $dateRaw) === 1)) {
$da["day"] = false;
}
}
}
}
return $da;
}
source to share