【问题标题】:Quirk with PHP DateTime ISO weeksPHP DateTime ISO 周的怪癖
【发布时间】:2017-12-30 16:13:19
【问题描述】:

我有 3 个值:

$timezone = new \DateTimeZone('America/New_York');
$year = 2019;
$week = 52;

然后我获取这 3 个值并通过脚本运行它:

$nowTime = new \DateTime('now', $timezone);
$currTime = clone $nowTime;
$currTime->setISODate($year, $week, 1);
$currTime->setTime(0,0,0);

如您所见,我将当前时间设置为 2019 年第 52 周的开始。

然后我正在尝试获取有关下周的信息。

$nextTime = clone $currTime;
$nextTime->modify('+1 week');

$nextWeek = [
    'year' => $nextTime->format('Y'),
    'week' => $nextTime->format('W'),
];

这个脚本几乎在我发现的所有实例中都有效...

希望,在 2019 年的第 52 周,它不会在下周作为 2020 年的第 1 周返回,而是在下周作为 2019 年的第 1 周返回......这让我及时倒退。

我该如何解决这个问题?这似乎发生在一年中有 53 周的每一年。

【问题讨论】:

  • 你的问题可能会更清晰!
  • 你可能会问为什么$myTime = new DateTime('2019/12/30'); var_dump($myTime->format('Y - W'));这个代码返回星期为 01 而不是 53

标签: php datetime


【解决方案1】:

您将两种没有意义的日期格式(YW)组合在一起。 W 是 ISO 周数,而 Y 是日历年。

2020 年的第一个 ISO 周从 2019 年 12 月 30 日开始,因此对于该日期,W 返回 1,但 Y 仍指 2019 年日历年。

PHP 提供了o 日期修饰符,可以在您的代码中代替Y,在手册中定义为:

ISO-8601 周编号年份。这与 Y 具有相同的值,除了如果 ISO 周数 (W) 属于上一年或下一年,则使用那一年。 (在 PHP 5.1.0 中添加)

因此您可以将代码更改为

$nextWeek = [
    'year' => $nextTime->format('o'),
    'week' => $nextTime->format('W'),
];

它应该按预期工作。

【讨论】:

  • 完美!这就是问题所在。
【解决方案2】:

根据任务的不同,有 2 种不同的方式来处理周数。

1。 ISO format:

每周从星期一开始。每周的年份是公历年 星期四。因此,每年的第一周总是 包含 1 月 4 日。因此 ISO 周年编号略 在接近 1 月 1 日的时候有几天偏离公历。

这些规则可能很难手动处理,这就是为什么它是标准 PHP 的一部分,所以你可以使用 'week' => $nextTime->format('W')

确实有可能 2019 年的一天属于 2020 年之后的一周。而且很容易证明:当您打开 2019/12 月的日历时,您可能会注意到上周“可能共享”明年的天数.为了防止重叠问题,当同一周属于不同年份但其数量不同时,例如2019 年的第 52 周与 2020 年的第 1 周相同,他们决定制定一套规则:ISO。这些规则在会计中特别有用,可以防止“模棱两可的周”。

2。您只需要一个“数学”周数作为简单的计数器:

$nextWeek = [
    'year' => $nextTime->format('Y'),
    'week' => (int)(($nextTime->format('z')) / 7) + 1
];

z 格式化程序是一年中的某一天(从 0 开始),这就是我在末尾添加“+1”的原因。

尽管它看起来是一个不错的方法,但它有一个缺点:2019 年第 52 周与 2020 年第 1 周相同。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多