2014-11-21 55 views
3

当没有一天的时候,我会在date_parse中调用一个bug。 $d = date_parse("Feb 2010")将给$d["day"] == 1php date_parse(“2010年2月”)给出的日期== 1

请参阅the date_parse manual page上的评论。

对此问题有什么好的解决方法? :-)

UPDATE 该日期来自已发表的研究报告。不幸的是,这意味着他们可以用不同的方式看待。我想在显示引用时将它们转换为更加标准的ISO格式。为了帮助我想要的读者总是只包括给定的字段(年,月,日)。所以这应该是有效的(并且只给我一年):

2010 

这应该是有效的,但只给我这么2010-02说:

Feb 2010 

更新2 所以远远我看到date_parse这里有两个错误。它无法解析2010。尽管Feb 2010中没有任何一天,但它给了我们一天的时间。

我当然可以为此写一个修复程序,但肯定有人已经这样做了,或者?

+1

PHP总是试图返回一个有效的日期,我想这就是它为该索引返回1而不是假的原因。国际海事组织的虚假确实没有任何意义,唯一可以回报的合理价值是1. – vascowhite 2014-11-21 00:52:43

+0

只是年份或年份加上月份仍然是有效的日期。 2010或2010-02是有效的ISO日期,但我现在看到date_parse说2010年是无效的。只是另一个错误。 :-( – Leo 2014-11-21 00:55:11

+1

解决方法是编写你自己的日期解析器,它可以做你想做的事 – Barmar 2014-11-21 00:58:21

回答

1

没有答案,所以我回答我的问题。这是我看到的问题的解决方法。

// 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; 
} 

一些测试(视觉;-))

$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); 
0

你可以尝试:

$dateTime = strtotime('February, 2010'); 
echo date('Y-m', $dateTime); 
+1

我想他想知道用户提供了哪些字段。所以如果用户没有给出一天的话,他希望这一天成为'空'。 – Barmar 2014-11-21 00:56:49

+0

是的,没错,@Barmar。不过谢谢Sajidkhan。 – Leo 2014-11-21 00:58:09

+2

我真的不明白在这里downvote。如果你不喜欢我的回答,IGNORE并找到你自己的东西。我不是在这里脱离主题 – Sajidkhan 2014-11-21 01:05:14

2

上述漏洞修复程序是伟大的,狮子座,谢谢。不幸的是,它仍然在一月份旅行,认为2014-01与2014-01-01相同---我们是那里的十一分之一。

的日期格式,PHP可以解析,即包含一个月中某一天的,似乎是(在php_src:date/lib/parse_date.re):

gnudateshorter = year4 "-" month; 
datenoday  = monthtext ([ .\t-])* year4; 
datenodayrev  = year4 ([ .\t-])* monthtext; 

很少,方便。我们可以在$ dateRaw上运行相同的正则表达式,基本上对解析器决定的内容进行逆向工程。 (侧面观察:上面不包括5/2016这样的格式,它被解析为“5月20日,最后有一些额外的字符”;它们也类似于一年中的一年和一年中的格式,所以我们尽量不要绊倒那些人。)

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; 
} 
相关问题