【问题标题】:strtotime result makes no sense, php bug?strtotime 结果没有意义,php 错误?
【发布时间】:2015-03-28 21:31:54
【问题描述】:

下面一行:

echo date('d', strtotime('First Saturday August 2015'));

打印08,这似乎没有任何意义,因为一周中一天的第一次出现不能在第 7 天之后。

它是一个 php bug 还是一个 php bug 或者甚至是一个 php bug?我不知道...

php版本:5.5.19

【问题讨论】:

  • 2015 年 8 月 1 日是星期六,8 月的第一个星期六。 8 月 8 日是第二个星期六。

标签: php strtotime php-5.5


【解决方案1】:

更新 #1: 在我对 PHP 源代码进行了一些调查之后,在下面解释了像 "of" 这样的简单词所产生的巨大差异。

更新 #2: 实际上一个关于 PHP 手册的文档页面,其中解释了 the formatsstrftime() 接受的日期。直到现在我才意识到这一点。感谢@Outspaced 在他们的回答中提供链接。

如需快速轻松阅读,请跳过更新#1部分。


初步答案:

确实,

echo date('Y-m-d', strtotime('First Saturday August 2015'));

打印:

2015-08-08

但是

echo date('Y-m-d', strtotime('First Saturday of August 2015'));

打印正确的日期:

2015-08-01

由于strtotime() 试图“理解”英语,我猜你和它说不同的方言:-)

更新 #1:

在阅读了 PHP source code of function strtotime() 之后,我认为它会将 First Saturday August 2015 解析为 First Saturday,然后是 August 2015

August 2015 是一个绝对表达式,因为有 no indication about the day 它会产生 2015-08-01(2015 年 8 月的第一个st),这是一个合理的猜测(我认为唯一可能的) )。

First Saturday 是一个relative expression。它相对于字符串中提供的绝对标记 (August 2015) 或作为strtotime() 的第二个参数,它"shifts" 绝对标记的时间戳向后或向前一些量。

将它们放在一起,strtotime()First Saturday August 2015 解释为 First SaturdayAugust 1, 2015 开始计数,事实上,August 8, 2015

另一方面,First Saturday of August 2015 使用 different rule 解析。 nextlastpreviousthis 或从 firsttwelfth 的任何序数之一,后跟工作日名称(全名或缩写),后跟 of 被解析为所提供月份的工作日(如果字符串中没有提供,则为当前月份)。

更新 #2

在PHP文档中发现strtotime()接受的字符串格式其实是explained后,解释就简单多了。查看documentation page 中的第二个“注意:”框。

First Saturday August 2015 在注释中的第 4 项中进行了解释:

"ordinal dayname" 确实提前到另一天。

First Saturday of August 2015 在注释的第 6 项中进行了解释:

"ordinal dayname 'of'" 不会提前到另一天。

注释以一个完整的解释块结束,专门用于magical单词“of”。

【讨论】:

  • 有趣的是echo date('Y-m-d', strtotime('Saturday August 2015')); 也打印了正确的日期。
  • 我也不是母语人士,关于方言的部分只是个玩笑;-) PHP 不懂英语,该函数遵循一组规则来解析日期。有很多规则,也许这就是文档中没有描述它们的原因。
  • 这就是为什么php的strtotime既神奇又可怕的原因
  • @BrianWarshaw 什么?不会。结果始终是一致且可靠的。很容易出错,但我猜这就是你使用 PHP 得到的结果
  • @BrianWarshaw(关于“为什么要承担从字符串中介翻译的成本?”)因为写$date = strtotime('First Saturday of August 2015');比写$ts = mktime(0, 0, 0, 8, 1, 2015); $date = $ts + 86400 * (6 - date('w', $ts));更容易,而且更容易阅读和理解 :-) 让我们回想一下,PHP 最初是作为一种工具,其目的是使网页编码成为一项简单的任务。
【解决方案2】:

你需要一个'of':

date('d/m/Y', strtotime('First Saturday of August 2015'))

参见手册: http://docs.php.net/manual/en/datetime.formats.relative.php

【讨论】:

    【解决方案3】:

    如前所述,PHP 不太了解您选择的方言。如果您打算接受来自用户的不同输入(不是一个坏主意)来表示日期,我建议您自己对该用户输入进行一些规范化,以便您可以向 strtotime 提交可预测的格式。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-05
      • 1970-01-01
      • 2011-05-30
      • 1970-01-01
      相关资源
      最近更新 更多