似乎有很多人在PHP中遇到日期/时间问题,并且不可避免地,许多已接受的答案往往是“Use strtotime
in this way。”
这真的是引导人们处理日期问题的最佳方式吗?我开始觉得strtotime
是一种非常好的技巧,不一定依赖于重要的日期/时间计算,并且由于它采用任意字符串的性质,它似乎是一个潜在的来源越野车,难以预测的行为。它无法区分MM / DD / YYYY和DD / MM / YYYY是一件大事,不是吗?
StackOverflow通常非常善于推广良好实践(我很少看到没有人说“使用PDO”的mysql_real_escape_string
对话。)
但是,PHP中的日期问题似乎没有被接受的规范,很多人都会回到strtotime
的拐杖上。
那么,如果有的话,我们应该怎么做呢?是否有一个更好的规范,我们应该强制执行问题,如“我如何添加1周到X”,或“如何将此日期格式转换为其他日期格式?”
处理strtotime
尝试的日期/时间问题的最佳,最可靠的方法是什么,但往往没有?
答案 0 :(得分:19)
我首先要说的是,我是使用DateTime对象的主要倡导者,它允许您使用DateTime::createFromFormat()
函数。 DateTime对象使代码更具可读性,并且无需使用60 * 60 * 24进行整个Unix时间戳修改以提前日期。
话虽如此,strtotime()所采用的任意字符串并不是很难预测。 Supported Date and Time Formats列出了支持的格式。
根据您无法区分MM / DD / YYYY和DD / MM / YYYY的示例,它会根据Date Formats进行区分。使用斜杠的日期始终读为美国格式。因此格式为00/00/0000的日期将始终读为MM / DD / YYYY。或者使用短划线或句点将是DMY。例如00-00-0000将始终读作DD-MM-YYYY。
以下是一些例子:
<?php
$dates = array(
// MM DD YYYY
'11/12/2013' => strtotime('2013-11-12'),
// Using 0 goes to the previous month
'0/12/2013' => strtotime('2012-12-12'),
// 31st of November (30 days) goes to 1st December
'11/31/2013' => strtotime('2013-12-01'),
// There isn't a 25th month... expect false
'25/12/2013' => false,
// DD MM YYYY
'11-12-2013' => strtotime('2013-12-11'),
'11.12.2013' => strtotime('2013-12-11'),
'31.12.2013' => strtotime('2013-12-31'),
// There isn't a 25th month expect false
'12.25.2013' => false,
);
foreach($dates as $date => $expected) {
assert(strtotime($date) == $expected);
}
正如您所看到的一些关键示例25/12/2013
和12.25.2013
如果以相反的格式阅读,则两者都有效,但是它们会返回 false
强>因为根据支持的日期和时间格式无效......
因此,您可以看到行为是可预测的。与往常一样,如果您从使用输入中收到日期,则应首先验证该输入。如果您没有先验证输入,则无法使用任何方法。
如果您想对所阅读的日期非常具体,或者您所提供的格式不是受支持的格式,那么我建议您使用DateTime::createFromFormat()
。
答案 1 :(得分:8)
strtotime()
,因为自v4.x天以来它一直在PHP中,所以基本上保证可用。可用性胜过奇怪的时间(没有双关语意),它会转过身来咬你,并用错误解析的日期咬你。
目前使用DateTime / DateInterval对象的“正确”方法是使用DateTime / DateInterval对象,但那些是PHP的最新增加(5.2 / 5.3,我认为)因此并不总是可用 - 那里有很多主机仍在4.x。
答案 2 :(得分:2)
我经常使用strtotime()
。事实是,你不应该把它用作拐杖,但你应该意识到它的局限性。
如果您想强制执行标准,那么我认为您应该使用基于c的mktime()
。例如,要在1周后获得:
date('Y-m-d', mktime(0, 0, 0, date('n'), date('j') + 7);
答案 3 :(得分:0)
Derek Rethans在'Advanced Date and Time Handling in PHP'的Froscon 2010上发表了演讲。
在http://derickrethans.nl/talks/time-froscon10.pdf以PDF格式查找幻灯片。这些依赖于最近的PHP(5.2及以上版本),其使用也应该是最佳实践。
答案 4 :(得分:0)
PHP中日期计算最可靠的方法是使用时间戳。
确实它受到32位整数的限制,但在某些奇怪的环境中键入时,使用Date对象不是一个选项,例如PHP 4。
为了确保您获得最正确的行为,我建议使用strptime()从人类可读日期获取时间戳。这比strtotime()和strftime()更好,因为它不会试图猜测日期的格式,而是使用您提供的日期格式。
获得正确的时间戳后,您可以在PHP中使用多种方法来完成工作。
答案 5 :(得分:0)
问题是您必须在应用程序的所有层中为日期/时间/区域值(ISO8601:2004)选择严格的数据格式,并找到最能处理此格式的PHP函数,即:{{ 1}}
具有不同日期/时间/区域格式的IMHO用于用户界面(GUI层),试图猜测PHP函数中的日期输入意味着您没有从客户端执行任何数据清理(使用Javascript可能?)并且您正在以未知格式从Web公式中传输数据。
如果日期/时间/区域格式与服务器端的ISO8601不匹配,您只需拒绝它,etvoilà!
希望这有帮助!
答案 6 :(得分:0)
在PHP中当然可以:检查strtotime manual, especially this comment。
如果您有可用的MySQL连接,SELECT DATE_ADD('2011-05-31',INTERVAL 1 MONTH)将不那么多余,因为(正确的)功能已经实现,您无需自己实现它。