2014-11-21 54 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; 
} 
相關問題