首页 > 解决方案 > 如何在 PHP 中获得类似于 MySQL 提供的从 0 开始的周数?

问题描述

在 PHP 中,周数基于 ISO-8601,这意味着 1 月 1 日可以是上一年的最后一周:

date('W', strtotime('2021-01-01')) === '53';
date('W', strtotime('2019-01-01')) === '01';
date('W', strtotime('2017-01-01')) === '52';

这很好,因为它是一个国际标准,但在订购数据时可能会导致意外结果。另一方面,MySQL 具有允许将这样的一天标记为属于第零周的模式:

week('2021-01-01', 1) = 0,
week('2019-01-01', 1) = 1,
week('2017-01-01', 1) = 0,

可以在PHP中复制吗?我可能会做这样的检查:

$date = strtotime('2021-01-01');
$week = date('W', $date);

if (in_array($week, [52, 53]) && date('m', $date) === '01') {
    $week = 0;
}

但我想知道这是否完全等效,在处理日期时经常会出现边缘情况。

标签: php

解决方案


我决定验证我自己的建议。我花了几百年一年的前 10 天,比较了我的算法和 MySQL 给出的结果。没有区别,所以除非它可以使用内置代码或像 Carbon 这样的库来完成,否则我会坚持使用它。

这是供参考的测试代码。它使用 Laravel 框架中的 \DB::select() 方法来查询数据库。

$getWeek = function($date) {
    $stamp = strtotime($date);
    $week = (int) date('W', $stamp);

    if (in_array($week, [52, 53]) && date('m', $stamp) === '01') {
        $week = 0;
    }

    return $week;
};

$errorCount = 0;

for ($year = 1801; $year <= 2200; $year++) {
    foreach (range(1, 10) as $day) {
        $fullDate = "$year-01-$day";
        echo $fullDate . ' ';
        $phpWeek = $getWeek($fullDate);
        echo $phpWeek . ' ';
        $dbWeek = \DB::select("select week('$fullDate', 1) as week")[0]->week;
        echo $dbWeek . ' ';
        if ($phpWeek !== $dbWeek) {
            echo 'error! ';
            $errorCount++;
        }
        echo "\n";
    }
}
die("$errorCount errors\n");

推荐阅读