11

我不敢相信我以前从未遇到过这个。

基本上,我正在解析人工创建的文本文档中的文本,而我需要解析的字段之一是日期和时间。因为我在澳大利亚,日期的格式类似于dd/mm/yyyystrtotime只想将其解析为美国格式的日期。此外,exploding by/是行不通的,因为正如我所提到的,这些文档是手工输入的,其中一些采用d M yy.

我尝试了多种组合,setlocale但无论我尝试什么,语言总是设置为美国英语。

我相当确定 setlocale 是这里的关键,但我似乎无法找到正确的代码。试过这些:

  • 澳大利亚
  • 奥恩
  • en_AU
  • 澳大利亚
  • 澳大利亚

还有什么我可以尝试的吗?

为清楚起见:我在带有 Windows 框的 IIS 上运行。

非常感谢 :)

伊恩

例子:

$mydatetime = strtotime("9/02/10 2.00PM");
echo date('j F Y H:i', $mydatetime);

生产

2 September 2010 14:00

我希望它产生:

9 February 2010 14:00

我的解决方案

我在这里给一个答案打勾,因为它是我的一个更容易阅读的解决方案,但这是我想出的:

$DateTime = "9/02/10 2.00PM";
$USDateTime = preg_replace('%([0-3]?[0-9]{1})\s*?[\./ ]\s*?((?:1[0-2])|0?[0-9])\s*?[./ ]\s*?(\d{4}|\d{2})%', '${2}/${1}/${3}', $DateTime);  
echo date('j F Y H:i',strtotime($USDateTime));

因为我不能依赖用户与他们的日期输入保持一致,所以我让我的正则表达式更复杂一点:

  • 0 到 3 之间的 0 或 1 个数字
  • 0 到 9 之间的 1 位数字——是的,这将匹配 37 作为有效日期,但我认为正则表达式已经足够大了!
  • 可能是一些空格
  • 分隔符('.'、'/' 或 '')
  • 可能是一些空格
  • 任何一个:
    • 10 到 12 之间的数字或
    • 1 到 9 之间的数字,前导 0 可选
  • 可能是一些空格
  • 分隔符('.'、'/' 或 '')
  • 可能是一些空格
  • 任何一个:
    • 一个 2 位数长的数字或
    • 一个 4 位数长的数字

希望这将匹配大多数日期写作风格......

4

6 回答 6

20

有一个快速修复似乎迫使 PHPstrtotime使用英国日期格式。即:将传入字符串中的所有“/”替换为“-”。

例子:

date('Y-m-d', strtotime('01/04/2011'));

将产生:2011-01-04

date('Y-m-d', strtotime('01-04-2011'));

将产生:2011-04-01

你可以使用str_replace来实现这一点。

例子:

str_replace('/', '-', '01/04/2011');

编辑:

如评论中所述,这是有效的,因为 PHP 将斜杠解释为美国,点/破折号解释为欧洲。

我已经广泛使用了这个技巧,到目前为止没有任何问题。

如果有人有充分的理由不使用它,请发表评论。

于 2011-04-11T10:13:20.803 回答
3

问题是它strtotime不采用格式参数。怎么样strptime

于 2010-03-15T03:05:14.967 回答
1

setlocale() 正是因为你描述的原因很糟糕:你永远不知道你会得到什么。最好手动处理字符串。

Zend Framework 的Zend_Date是一种替代方案,承诺更准确和一致的日期处理。我自己还没有经验,刚开始使用它,但到目前为止,我喜欢它。

于 2010-03-15T03:02:05.463 回答
1

啊,我们幸运的澳大利亚人遇到的老问题。

我过去所做的是这样的

public static function getTime($str) { // 3/12/2008

       preg_match_all('/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/', $str, $matches);

       return (isset($matches[0][0])) ? strtotime($matches[3][0] . '-' . $matches[2][0] . '-' . $matches[1][0]) : NULL;

    }

虽然这依赖于这种格式的日期dd/mm/yyyy

您可能可以使用另一个正则表达式来转换d M yy或使用修改过的正则表达式。我不知道这是否正确,但这可能是一个开始:

/^(\d{1,2})(?:\/|\s)(\d{1,2})(?:\/|\s)(\d{2,4})$/

于 2010-03-15T03:20:54.913 回答
0
$date = date_create_from_format('d/m/Y', $date_string);
$unix_timestamp = $date->getTimestamp();

或者

$date = DateTime::createFromFormat('d/m/Y', $date_string);
$unix_timestamp = $date->getTimestamp();
于 2015-07-24T13:34:44.830 回答
0

对于未来的读者,请尝试以下方法从不受信任的用户输入中解析日期,因为这strptime()太死板了。它输出 ISO 日期字符串,您可以将其传递给new Date()strtotime()等,或 false 表示无效日期,或 null 表示没有可用输入。您必须使其适应处理时间。它还接受 2 位数年份和 ISO 日期输入。

function parseUserDate($input, $allow_zero = false) {
    if (!is_string($input)) {
        return $input === null ? null : false;
    }
    $input = preg_split('/\\D+/', $input, null, PREG_SPLIT_NO_EMPTY);
    if (!$input) {
        return null;# no date
    }
    if (count($input) == 3) {
        list($od, , $oy) = $input;
        if (strlen($od) > 2 && strlen($oy) < 3) {# assume ISO
            $oy = $od;
            $input = array_reverse($input);
        }
        $intify = function($dig) {
            return (int) ltrim($dig, '0');# prevent octals
        };
        list($d, $m, $y) = array_map($intify, $input);
        if (strlen($oy) < 3) {
            $current_year = date('Y');
            $current_year_2 = $intify(substr($current_year, -2));
            $diff = $y - $current_year_2;
            if ($diff > 50) {
                $diff -= 100;
            }
            elseif ($diff < -50) {
                $diff += 100;
            }
            $y = $diff + $current_year;
        }
        if (
            ($allow_zero && $d == 0 && $m == 0 && $y == 0)
            || checkdate($m, $d, $y)# murrican function
        ) {
            return sprintf('%04d-%02d-%02d', $y, $m, $d);
        }
    }
    return false;# invalid date
}
于 2018-02-09T02:44:47.287 回答