夏令时的PHP日期问题

Posted

技术标签:

【中文标题】夏令时的PHP日期问题【英文标题】:PHP date issues with daylight saving 【发布时间】:2010-09-27 23:17:48 【问题描述】:

我的一些 php 代码中出现了一个非常奇怪的错误。该页面正在管理课程中的学生注册。页面上是学生的课程表,每一行都有多个日期:他们注册的时间、完成时间、通过评估的时间以及领取证书的时间。

表格数据由PHP生成(从DB中提取数据),javascript实际渲染表格。 PHP 的输出是 JS 代码,看起来像这样:

var e = new Enrolment();
e.contactId = 5801;
e.enrolId = 14834;
e.courseId = 3;
e.dateEnrolled = new Date(1219672800000);
e.dateCompleted = new Date(-1000);  // magic value meaning they haven't completed.
e.resultDate = new Date(1223647200000);
e.certDate = new Date(1223560800000);
e.result = 95;
e.passed = true;
enrolments[14834] = e;

在数据库中,所有日期字段都存储为DATE(不是DATETIME)字段。

错误是日期显示为休息日。我怀疑这与服务器位于有夏令时的区域有很大关系,而这里没有(意味着服务器时间关闭一小时)。这解释了很多,尤其是数据准备和渲染是如何在两个不同的时区完成的。即:服务器告诉客户端此人在 8 月 15 日午夜完成,客户端将其解释为 14 日晚上 11 点,因此显示为 8 月 14 日。

但这是令人困惑的部分:它只对 resultDate 和 certDate 字段这样做!我已将数据复制到本地服务器,并发现生产服务器实际上只是为这两个字段发送了不同的时间戳(一个延迟 1 小时),而 dateEnrolled 字段是相同的。

这是使用数据库中完全相同的代码和数据的输出:

// local server (timezone GMT+1000)
e.dateEnrolled = new Date(1219672800000);   // 26 Aug 2008 00:00 +10:00
e.dateCompleted = new Date(-1000);
e.resultDate = new Date(1223647200000);     // 11 Oct 2008 00:00 +10:00
e.certDate = new Date(1223560800000);       // 10 Oct 2008 00:00 +10:00

// production server (timezone GMT+1100)
e.dateEnrolled = new Date(1219672800000);   // 26 Aug 2008 00:00 +10:00
e.dateCompleted = new Date(-1000);
e.resultDate = new Date(1223643600000);     // 10 Oct 2008 23:00 +10:00 **
e.certDate = new Date(1223557200000);       // 09 Oct 2008 23:00 +10:00 **

我可以理解这是否是夏令时未考虑的问题,但请注意 dateEnrolled 是如何相同的?

mysql 日期转换为 unix 时间戳的 PHP 代码如下:

list ($year, $month, $day) = explode ('-', $mysqlDT);
$timestamp = mktime (0,0,0, $month, $day, $year);

关于如何解决这个问题的任何想法?

【问题讨论】:

【参考方案1】:

那是因为您使用的是特定于语言环境的 mktime。也就是说,它会将其转换为格林威治标准时间 1970 年 1 月 1 日 00:00:00 开始的秒数,并在一个时区偏移 1 小时。

您还应该记住,javascript 确实使用与浏览器相同的时区,而不是网页。

e.resultDate = new Date(year, month - 1, day);

这将确保每个时区的每个观看者的日期都相同。

或者您可以使用 gmmktime 并在 Date 中使用 UTC 方法。

【讨论】:

【参考方案2】:

好的,我刚刚弄清楚为什么它搞砸了一个约会而不是另一个。夏时制在八月没有生效。 掌心

【讨论】:

【参考方案3】:
    始终以 GMT/UTC 存储日期/日期时间 仔细查看检索这些值的查询,正在调整的值有什么不同吗? 如果不是,它们都是时间戳还是日期或日期时间?

【讨论】:

【参考方案4】:

这很可能是夏令时问题。 它只为 resultDate 和 certDate 这样做的原因是 dateEnrolled 是在 8 月,夏令时通常在 9 月下旬或 10 月初开始/结束。

【讨论】:

【参考方案5】:

使用 apache.conf、.htaccess 或 ini_set() 将 date.timezone ini 设置设置为应用的时区。

【讨论】:

以上是关于夏令时的PHP日期问题的主要内容,如果未能解决你的问题,请参考以下文章

没有夏令时的日期计算

仅从日期计算夏令时

确定日期夏令时的算法?

UTC 时间、时区、夏令时和夏令时切换日期

在 Javascript 中使用夏令时检查日期范围

夏令时更改为绝对日期