strtotime()被认为有害吗?

时间:2011-03-13 03:33:48

标签: php date strtotime

似乎有很多人在PHP中遇到日期/时间问题,并且不可避免地,许多已接受的答案往往是“Use strtotime in this way。”

这真的是引导人们处理日期问题的最佳方式吗?我开始觉得strtotime是一种非常好的技巧,不一定依赖于重要的日期/时间计算,并且由于它采用任意字符串的性质,它似乎是一个潜在的来源越野车,难以预测的行为。它无法区分MM / DD / YYYY和DD / MM / YYYY是一件大事,不是吗?

StackOverflow通常非常善于推广良好实践(我很少看到没有人说“使用PDO”的mysql_real_escape_string对话。)

但是,PHP中的日期问题似乎没有被接受的规范,很多人都会回到strtotime的拐杖上。

那么,如果有的话,我们应该怎么做呢?是否有一个更好的规范,我们应该强制执行问题,如“我如何添加1周到X”,或“如何将此日期格式转换为其他日期格式?”

处理strtotime尝试的日期/时间问题的最佳,最可靠的方法是什么,但往往没有?

7 个答案:

答案 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/201312.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)将不那么多余,因为(正确的)功能已经实现,您无需自己实现它。