Quirk与PHP DateTime ISO周

时间:2017-12-30 16:13:19

标签: php datetime

我有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'),
];

这个脚本几乎适用于我找到的所有实例......

Hopever,在2019年的第52周,而不是在2020年作为第1周返回下一周,它将在2019年的第1周返回下一周......这使我及时向后退。

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

2 个答案:

答案 0 :(得分: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'),
];

它应该按预期工作。

答案 1 :(得分:0)

根据任务的不同,有两种不同的方式可以处理周数。

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周相同。