2014-11-21 1 views
3

Существует то, что я назвал бы ошибкой в ​​date_parse, когда нет дня. $d = date_parse("Feb 2010") даст $d["day"] == 1.php date_parse («Feb 2010») дает день == 1

См. Комментарий к этому вопросу на the date_parse manual page.

Любое хорошее обходное решение для этой проблемы? :-)

ОБНОВЛЕНИЕ Дата исходит из опубликованных научных отчетов. К сожалению, это означает, что они могут выглядеть по-разному. Я хочу преобразовать их в более стандартный формат ISO при отображении ссылок. Чтобы помочь читателям, я хочу всегда включать только данные поля (годы, месяц, дату). Таким образом, это должно быть справедливо (и только дайте мне год):

2010 

Это должно быть в силе, но только дайте мне 2010-02 так сказать:

Feb 2010 

UPDATE 2 Таким образом, далеко я видел две ошибки здесь в date_parse. Он не может разобрать 2010. И это дает день, хотя нет дня в Feb 2010.

Я могу, конечно, написать исправление для этого, но, конечно же, кто-то уже это сделал, или ???

+1

PHP всегда пытается вернуть действительную дату, я полагаю, что именно по этой причине он возвращает 1 для этого индекса, а не для флага. IMO false действительно не имеет никакого смысла, и единственная разумная ценность, которую нужно вернуть, равна 1. – vascowhite

+0

Только год или год плюс месяц являются действительными датами. 2010 или 2010-02 являются действительными датами ISO, но я вижу, что date_parse говорит, что 2010 год является недействительным. Еще одна ошибка. :-( – Leo

+1

Обходной путь заключается в том, чтобы написать собственный синтаксический анализатор даты, который делает то, что вы хотите. – Barmar

ответ

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

+0

Да, это правильно, @Barmar. Но, во всяком случае, спасибо Саджидхану. – Leo

+2

Я честно не понимаю нижний предел здесь. Если вам не нравится мой ответ, IGNORE и найдите что-то свое. Я не вне темы здесь – Sajidkhan

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, которые анализируются как «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; 
}