如何在PHP中计算日期之间的天数:5个致命错误

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

“过去了多少天?”——一个让新手头疼的问题

\n\n

每个PHP开发者迟早都会遇到这样一个任务:需要计算两个日期之间过去了多少天。看起来,这有什么难的呢?拿两个字符串,一个减去另一个——就完成了。但正是在这里,在看似平坦的路上,会犯下最阴险的错误。

\n\n

我们查看了Stack Overflow,发现了一个真实的问题“Finding the number of days between two dates”,该问题获得了数千次浏览。事实证明,即使是经验丰富的程序员也会陷入与时区、Unix时间戳以及strtotime()意外行为相关的陷阱。

\n\n

在本文中,我们将解析在PHP中计算日期之间天数时最常见的五个错误,并向您展示如何避免它们。准备好编辑器——会有很多代码和实践建议。

\n\n

错误#1:直接相减Unix时间戳

\n\n

最常见的错误——尝试通过简单相减时间戳来获取日期差:

\n\n
<?php\n$date1 = strtotime('2024-01-01');\n$date2 = strtotime('2024-01-10');\n$days = ($date2 - $date1) / (60 * 60 * 24);\necho $days; // 9\n?>
\n\n

表面上一切正常。但试试切换到夏令时。在切换到“夏令时”时,一天会缩短一小时,而在切换回来时则会延长。结果:得到9.04166或8.95833天,而不是精确的9天。

\n\n

如何修复

\n

使用DateTime对象和diff()方法。它们会考虑所有的时间跳跃:

\n\n
<?php\n$date1 = new DateTime('2024-01-01');\n$date2 = new DateTime('2024-01-10');\n$interval = $date1->diff($date2);\necho $interval->days; // 9 — 始终正确\n?>
\n\n

通过DateTime::diff处理PHP日期差是行业标准。请记住这个模式。

\n\n

错误#2:忽略时区

\n\n

想象一下:您的服务器位于欧洲/莫斯科,而来自纽约的用户输入了日期“2024-03-10”。您创建了一个DateTime对象,但没有指定时区。PHP会使用服务器的系统时区。结果:天数差可能会“漂移”一天。

\n\n

这在月份边界和夏令时切换时尤其关键。这个错误很少出现,但当它在生产环境中出现时,很难捕获。

\n\n

解决方案:明确指定时区

\n
<?php\n$tz = new DateTimeZone('UTC');\n$date1 = new DateTime('2024-03-10', $tz);\n$date2 = new DateTime('2024-03-20', $tz);\n$interval = $date1->diff($date2);\necho $interval->days; // 10 — 准确无误\n?>
\n\n

始终使用UTC进行内部计算。如果需要向用户显示日期,仅在输出阶段转换为他们的本地时区。

\n\n

错误#3:混淆 days 和 format('%a')

\n\n

DateInterval对象有一个days属性和一个format('%a')方法。看起来它们是一样的。但有一个细微差别:

\n\n
    \n
  • $interval->days — 总天数(考虑了所有月份和年份)。该值始终正确。
  • \n
  • $interval->format('%a') — 相同的内容,但以字符串形式返回。
  • \n
  • $interval->d — 仅天数,不考虑月份。如果差值是35天,那么d将返回4(减去一个月后的剩余天数)。
  • \n
\n\n

新手经常混淆d和days。结果得到4天而不是35天。这会导致报告、计费和任务计划器中的错误。

\n\n

始终检查您使用的是哪个属性

\n
<?php\n$date1 = new DateTime('2024-01-01');\n$date2 = new DateTime('2024-02-05');\n$interval = $date1->diff($date2);\n\necho $interval->days; // 35\necho $interval->d;    // 4 — 不一样!\n?>
\n\n

如果您需要的是两个日期之间的天数——请使用

博客

书籍推荐