【问题标题】:PHP datetime difference in months return bad values, mis php configuration or a bug以月为单位的 PHP 日期时间差返回错误值、错误的 php 配置或错误
【发布时间】:2020-05-04 11:32:52
【问题描述】:

所以我在我的脚本中使用 datetime 和 diff 方法来计算月差,我创建了测试脚本来告诉你我的问题是什么。

在我的服务器上运行(远程 linux 和家中的本地窗口,欧洲/华沙时区):

echo "StartDate\tEndDate\tMonthNum\tDifference\n";
for($i = 1; $i <= 12; $i++){
        $filters['date_from'] = "2020-$i-01";
        $filters['date_to'] = date("Y-m-t", strtotime("2020-$i-01"));
        $datetime1 = new DateTime($filters['date_from']);
        $datetime2 = new DateTime($filters['date_to']);
        $difference = $datetime1->diff($datetime2);
        $end = $difference->m;
            echo "{$filters['date_from']}\t{$filters['date_to']}\t" . $i . "\t$end\n";
}

结果是 PHP 7.1.29 和 PHP 7.4.1:

StartDate       EndDate MonthNum        Difference
2020-1-01       2020-01-31      1       0
2020-2-01       2020-02-29      2       0
2020-3-01       2020-03-31      3       1
2020-4-01       2020-04-30      4       0
2020-5-01       2020-05-31      5       1
2020-6-01       2020-06-30      6       0
2020-7-01       2020-07-31      7       1
2020-8-01       2020-08-31      8       0
2020-9-01       2020-09-30      9       0
2020-10-01      2020-10-31      10      1
2020-11-01      2020-11-30      11      0
2020-12-01      2020-12-31      12      1

所以当您看到差异显示 0 或 1 个月份差异时,如果月份超过 30 天,则为 1,如果少于 0 天,则为 0。

所以我在http://sandbox.onlinephpfunctions.com/ 上测试了这段代码,结果不同:

StartDate   EndDate MonthNum    Difference
2020-1-01   2020-01-31  1   0
2020-2-01   2020-02-29  2   0
2020-3-01   2020-03-31  3   0
2020-4-01   2020-04-30  4   0
2020-5-01   2020-05-31  5   0
2020-6-01   2020-06-30  6   0
2020-7-01   2020-07-31  7   0
2020-8-01   2020-08-31  8   0
2020-9-01   2020-09-30  9   0
2020-10-01  2020-10-31  10  0
2020-11-01  2020-11-30  11  0
2020-12-01  2020-12-31  12  0

所有月份都有 0 个月的差异,所以它运行良好,也许有人知道我的服务器可能是什么问题?

【问题讨论】:

  • 不一致,1月和8月有31天,但相差还是0
  • 是的,你说得对,但我的服务器上的问题仍然存在,这很可悲:(
  • 如果有什么安慰的话,不仅仅是你的服务器。 3v4l.org/jKc3s 也显示了问题。我认为您发现了一个 PHP 错误。它似乎取决于上个月的天数; diff 是相对于该月的天数计算的,因此在 3 月,由于 2 月有 29 天,因此 30 天的差异为 1 个月和 1 天。如果您查看该链接上代码的调试输出,您可以看到这一点。但是,如果您在沙盒链接上运行相同的代码,它会完全按照应有的方式运行...

标签: php date datetime diff


【解决方案1】:

是的,这是一个错误。从该月的第一天到该月的最后一天 (00:00) 的差值应始终返回 0 月,因为缺少最后一天。 1个月是从当月的第一天(00:00)到下个月的第一天00:00。 该错误是由不正确的时区转换为 UTC 引起的。如果使用 UTC 时区作为解决方法,则可以正确计算月份。

$tz = new dateTimeZone('UTC');
for($i = 1; $i <= 12; $i++){
  $n = $i+1;
  $dateFrom = "2020-$i-01";
  $dateTo = $n == 13 ? "2021-01-01" : "2020-$n-01";
  $diff = date_create($dateFrom,$tz)->diff(date_create($dateTo,$tz));
  echo $dateFrom." to ".$dateTo." = ".$diff->m. " month or ".$diff->days." days<br>\n";
}

输出:

2020-1-01 to 2020-2-01 = 1 month or 31 days
2020-2-01 to 2020-3-01 = 1 month or 29 days
2020-3-01 to 2020-4-01 = 1 month or 31 days
2020-4-01 to 2020-5-01 = 1 month or 30 days
2020-5-01 to 2020-6-01 = 1 month or 31 days
2020-6-01 to 2020-7-01 = 1 month or 30 days
2020-7-01 to 2020-8-01 = 1 month or 31 days
2020-8-01 to 2020-9-01 = 1 month or 31 days
2020-9-01 to 2020-10-01 = 1 month or 30 days
2020-10-01 to 2020-11-01 = 1 month or 31 days
2020-11-01 to 2020-12-01 = 1 month or 30 days
2020-12-01 to 2021-01-01 = 1 month or 31 days

【讨论】:

  • 你要提交报告吗?
  • 没有。我想这已经是众所周知的了。 bugs.php.net/bug.php?id=79452
  • 是的,看起来几乎是一样的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-11
  • 1970-01-01
  • 1970-01-01
  • 2012-01-11
相关资源
最近更新 更多