我的一些 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);

关于如何解决这个问题有什么想法吗?

有帮助吗?

解决方案

那是因为使用mktime这是特定于语言环境。也就是说,将其转换为秒数从00:00:00 GMT 1970-1-1,和通过1小时,一个时区偏移。

您也应该记住,JavaScript并使用相同的时区的浏览器,而不是网页。

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

这将确保的时间,是从每一个时区的每个观看者相同。

或者你可以使用gmmktime并使用UTC方法日期。

其他提示

好吧,我只是想通了,为什么它会打乱一个日期,但不是其他。夏令不是效力于八月。 捂脸

  1. 始终以 GMT/UTC 格式存储日期/日期时间
  2. 仔细查看检索这些值的查询,正在调整的值有什么不同吗?
  3. 如果不是,它们都是时间戳或日期或日期时间吗?

有mosly可能是日光节能问题。 为什么这样做只为resultDate和certDate的原因是dateEnrolled是在八月,夏令时通常开始于9月底或10月初/结束。

设置date.timezone INI设定为应用的时区,使用的apache.conf,htaccess的或函数ini_set()。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top