php date_parse(“Feb 2010”)给出了一天== 1

时间:2014-11-21 00:48:58

标签: php date-parsing

当没有白天时,我会在date_parse中称之为bug。 $d = date_parse("Feb 2010")$d["day"] == 1

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

这个问题有什么好的解决方法吗? : - )

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

2010

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

Feb 2010

更新2 到目前为止,我在date_parse看到了两个错误。它无法解析2010。虽然Feb 2010中没有一天,但它给了一天。

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

3 个答案:

答案 0 :(得分:2)

上面的错误修正程序很棒,Leo,谢谢。不幸的是,它仍然在1月份徘徊,认为2014-01与2014-01-01相同 - 我们是那里的第11个十二分之一。

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

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

很少,很方便。我们可以在$ dateRaw上运行相同的正则表达式,基本上是对解析器所决定的进行逆向工程。

(侧面观察:上面不包括像5/2016这样的格式,它被解析为" 5月20日结束时有一些额外的字符&#34 ;;它们也类似于日期和星期 - 年份格式,所以我们不会绊倒那些。)

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

答案 1 :(得分: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);

答案 2 :(得分:0)

你可以尝试:

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