我现在很困惑。我不确定,如果我错过了一些非常重要的东西。
我写的echo (new DateTime('monday 2023W18'))->format('Y-m-d');
我在这里期待2023-05-01,但却得到了2023-05-02(这是正确日期之后的星期二)
似乎日子总是一天一天的。echo (new DateTime('sunday 2023W18'))->format('Y-m-d');
2023-05-01(星期一)
我的问题是:是我做错了什么,还是这是一个bug?
感谢您的意见
1条答案
按热度按时间50few1ms1#
它总是诱人的只是写出一个长字符串,你觉得会导致你正在寻找的日期,但要知道,解析器是一个相当松散的文本解析器的基础上的规则集。所以它可能并不总是按照你期望的方式工作。
这些年来我在日期解析方面遇到了很多异常情况。它们是虫子吗?也许吧。开发商们很关心它吗?不太清楚这只是解释器在大多数情况下工作的语义。
在这个具体案例中发生了什么?不知道。可能是它以某种方式回溯到上周的星期一,然后修改到今年的第18周...或者可能会以完全不同的方式解释它。由于没有调试工具来说明它是如何处理日期的,因此无法确定。
我学到的是,坚持这3条规则会导致最准确的日期解释:
1.如果需要多个规则进行多次修改并坚持使用其他规则,请仅为每个解释使用***1***规则(添加多个规则通常会导致解释器混淆):
1.从最广泛的规则开始,然后添加额外的规则,直到最具体的规则:运用常识
1.严格遵守Supported Date and Time Formats中描述的格式规则
在这种情况下,你正在寻找2023年第18周的星期一。2023年的第18周是最广泛的,而该周的星期一是最具体的。根据上述规则,
我们首先解析
2023W18
,这是最广泛的规则,严格遵循Compound Formats中的ISO Year with ISO Week
。然后我们将其修改为monday this week
,这是最具体的规则,并且严格遵循Relative Formats中的reltext space 'week'
规则。为什么要使用
monday this week
而不是monday
?因为monday
是非常通用的,它的解释是…好吧,粗略的。根据Relative Formats中的dayname
规则,它应该将日期提前到下一个匹配的工作日(本质上是“下星期一”)。但是,当我在这种情况下添加它时,它回溯到了前一周的星期一。为什么?谁知道呢。相对格式最好尽可能具体。使用monday this week
告诉解释器我们需要DateTime
对象当前星期的星期一,而不是让解释器来决定。***请记住***一年中的ISO周可能会导致一些关于年初/年末的混淆。根据一年的第一天或最后一天的工作日,第一天可以是前一年的最后一个星期一,也可以是下一年的第一个完整的星期。所以它可能并不总是给予你你可能期望的日期。例如,2020年的第一天(星期三)将导致该年的第一周成为第一周,因此它将回到2019年12月30日星期一作为该周的星期一。然而,2021年的第一天(星期五)将提前到2021年1月4日星期一。Wiki的链接对此进行了解释,并显示了截止点。如果您正在寻找不同的一天,您可能需要添加一些额外的规则来检查一年中的第一天/最后一天的位置,并根据您的需要进行修改。