如何使用澳大利亚语进行 strtotime 解析日期(即英国)格式:日/月/年?
题
我不敢相信我以前从未遇到过这个。
基本上,我正在解析人工创建的文本文档中的文本,我需要解析的字段之一是日期和时间。因为我在澳大利亚,所以日期格式如下 dd/mm/yyyy
但 strtotime
只想将其解析为美国格式的日期。另外,爆炸式的 /
行不通,因为正如我提到的,这些文档是手写的,其中一些采用以下形式 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 位数字长的数字 OR
- 4 位数字长的数字
希望这能匹配大多数日期书写风格......
解决方案
有一个快速修复似乎可以强制 PHP strtotime
使用英国日期格式。那是:将传入字符串中的所有“/”替换为“-”。
例子:
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 将斜杠解释为美国的,将点/破折号解释为欧洲的。
我已经广泛使用了这个技巧,到目前为止没有遇到任何问题。
如果有人有任何充分的理由不使用此功能,请发表评论。
其他提示
问题是 strtotime
不需要 格式 争论。关于什么 strptime
?
setlocale() 很糟糕,原因正是您所描述的:你永远不知道你会得到什么。最好手动处理字符串。
Zend框架的 Zend_Date 是一种承诺更准确和一致的日期处理的替代方案。我自己还没有使用它的经验,刚刚开始使用它,但到目前为止,我喜欢它。
啊,这是我们幸运的澳大利亚人遇到的老问题。
我过去做过的事情是这样的
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})$/
$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();
对于未来的读者,请尝试以下方法来解析不受信任的用户输入的日期,其中 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
}