php DateTime返回错误的日期,包含Weekday周和年

h5qlskok  于 2023-05-05  发布在  PHP
关注(0)|答案(1)|浏览(157)

我现在很困惑。我不确定,如果我错过了一些非常重要的东西。
我写的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?
感谢您的意见

50few1ms

50few1ms1#

它总是诱人的只是写出一个长字符串,你觉得会导致你正在寻找的日期,但要知道,解析器是一个相当松散的文本解析器的基础上的规则集。所以它可能并不总是按照你期望的方式工作。
这些年来我在日期解析方面遇到了很多异常情况。它们是虫子吗?也许吧。开发商们很关心它吗?不太清楚这只是解释器在大多数情况下工作的语义。
在这个具体案例中发生了什么?不知道。可能是它以某种方式回溯到上周的星期一,然后修改到今年的第18周...或者可能会以完全不同的方式解释它。由于没有调试工具来说明它是如何处理日期的,因此无法确定。
我学到的是,坚持这3条规则会导致最准确的日期解释:
1.如果需要多个规则进行多次修改并坚持使用其他规则,请仅为每个解释使用***1***规则(添加多个规则通常会导致解释器混淆):
1.从最广泛的规则开始,然后添加额外的规则,直到最具体的规则:运用常识
1.严格遵守Supported Date and Time Formats中描述的格式规则
在这种情况下,你正在寻找2023年第18周的星期一。2023年的第18周是最广泛的,而该周的星期一是最具体的。根据上述规则,

echo (new DateTime('2023W18'))-modify('monday this week')->format('Y-m-d');
// 2023-05-01

我们首先解析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的链接对此进行了解释,并显示了截止点。如果您正在寻找不同的一天,您可能需要添加一些额外的规则来检查一年中的第一天/最后一天的位置,并根据您的需要进行修改。

相关问题