夏令时废除 - 我是否正确保存日期时间?

Daylight saving time abolition - am I saving datetimes correctly?

我目前正在开发一个 PHP/mySQL 网络应用程序,我们将日期作为 unix 时间戳存储在 UNSIGNED INT(10) 列中。每当我们需要在 Web 视图中显示日期时,我们都会获取该数字并使用 moment.js.

对其进行解析

虽然我的一位同事对这种解决任务的方式表示怀疑(他更喜欢将日期存储为 "YYYY-MM-DD hh:mm:ss" VARCHAR),但到目前为止我们的问题为零。

我最近读到欧盟正在推进废除夏令时。根据我存储日期的特定方式,这会以任何方式影响我的网络应用程序吗?

我要出来说不应该没关系。我不是专家,但我也将日期存储为 UNIX 时间戳,如果您要生成 10 位数字时间戳,则类似于:

getSecondsSinceEpoch = ((date) => Math.floor(date.getTime()/1000));

(或依赖于 Date.prototype.getTime() 的任何东西),那么您将存储一个不关心时区的通用日期,这很好,因为如果用户从不同的时区登录,您不返回基于它们曾经所在位置的 varchars。这同样适用于夏令时更改其所在时区的时钟(或废除后未能更改)。

要获取用户当前位置的正确人类可读字符串,Javascript 依赖 timezoneOffset,它不是日期对象的一部分,而是回答问题 "how many timezones away from London is this browser right now?" (除了以分钟而不是小时为单位,并且在考虑夏令时之后。)据推测,用户的设备将意识到更改,他们的浏览器也是如此,并且您的脚本将能够采取相应的行动。 (如果他们的设备使用了错误的时区,在他们解决问题之前,您的应用将不会是唯一出现问题的应用。)

正如我所说,我不是这方面的专家,所以我可能已经说服自己相信 Javascript 处理日期的方式是不正确的,但就我而言目前的理解是,我认为你的解决方案应该没问题。我希望如果我弄错了,其他书呆子会立即插话让我们都知道。

几件事:

  • MySQL 具有内置的日期和时间标准数据类型。它们是 DATEDATETIMETIMESTAMP。您可以阅读更多有关它们的信息 in the MySQL documentation here。您应该从这些类型中选择一种,而不是存储整数或 varchars。

  • 这与 DST 的关系在很大程度上取决于上下文。没有一种正确的方法可以存储所有日期和时间。对 "always store in UTC" 的任何建议都是 shortsigted,应该劝阻。相反,请考虑日期和时间所代表的上下文。详细说明:

    • Unix 时间戳始终基于 UTC,因此与 DST 或时区的其他影响没有任何关系。当某事发生在现在或过去发生时,这是表示时间戳的好方法。在 MySQL 中,TIMESTAMP 类型很好地符合这个概念。

    • 如果您要存储未来事件的预定时间,那么 本地 日期和时间在上下文中更为重要。在 MySQL 中,您可以将其存储在 DATETIME 类型中。如果您正在处理多个时区,那么您还需要该事件的时区标识符(例如 America/New_York),您可以将其存储在 VARCHAR 中。在这种情况下,DST 非常依赖于与该时区关联的基本规则。 MySQL 具有类似于 CONVERT_TZ 的功能,可以理解这些标识符并使​​用基础 OS 时区数据或它自己的时区表来了解 DST 是否有效。

    • 如果您要处理整个日期,例如出生日期、周年纪念日期、雇用日期或按给定工作日汇总数据,那么您需要将其保留为没有时间的日期或时区。这就像您在纸质日历上查看日期方块一样。 MySQL 有 DATE 类型。 DST 在这种情况下不相关,除了确定某个时间点属于哪个日期。例如,当我们询问 "today" 是哪一天时,我们也会考虑包括 DST 在内的时间和时区 - 但是一旦我们声明 "April 4th 2019",那么所有这些信息都会被删除。

  • 您问题的最后一部分涉及基础时区数据的实施方式,以及在欧盟废除夏令时时如何更新这些数据。为此,我将向您推荐 ,它解释了 IANA 时区数据库并直接解决了当前欧盟关注的问题。