【问题标题】:Should we store date in date or in datetime format if want to run the application on multiple timezone?如果要在多个时区运行应用程序,我们应该将日期存储为日期还是日期时间格式?
【发布时间】:2018-03-14 06:59:43
【问题描述】:

我的客户想在多个国家/时区运行他的网站。我们在应用程序中使用 MySQL。因此,在 MySQL 中存储日期字段时,我应该使用 datedatetime 来存储简单的日期字段。

让我举一个我在这里面临的问题的例子。我今天在印度创建了 2017 年 10 月 3 日的订单,但在美国创建了 2017 年 10 月 2 日的订单。我已经要求用户设置他们的时区。但是我们是否可以简单地通过使用日期字段来解决上述问题,或者我们应该使用日期时间?

谢谢

【问题讨论】:

    标签: php mysql date datetime timezone


    【解决方案1】:

    UTC

    将 UTC 视为 一个真实时间tm。所有其他区域和偏移只是变化。

    以 UTC 时间线存储时刻。以 UTC 存储实际历史记录。

    TIMESTAMP WITH TIME ZONE

    在标准 SQL 中,这意味着使用数据类型 TIMESTAMP WITH TIME ZONE。数据库通常将输入调整为 UTC。有的也保存原来的时区,有的如 Postgres 用于 UTC 调整后的时区不一致。

    听起来这是你需要的类型。

    虽然我不使用 MySQL,但 it looks like 等效于标准类型是 TIMESTAMP

    在 Java 中,您可以将该值作为 Instant 对象检索。然后通过分配ZoneIdZonedDateTime 的形式呈现给用户。

    在 SQL 中,您可以在检索期间指定时区。在我看来,通常最好让应用从 UTC 调整到一个区域,但请使用您自己的判断。

    TIMESTAMP WITHOUT TIME ZONE

    在讨论跨时区的一般时刻时,例如“我们全球所有工厂在中午 12:30 停下来吃午饭”,请使用标准类型 TIMESTAMP WITHOUT TIME ZONE

    也可以使用这种类型来安排未来的事件,该事件在未来的时区定义可能会发生变化。世界各地的政客们都表现出搞乱时区的嗜好。他们通常会在没有注意到的情况下这样做,有时只需几个星期。检索值时动态应用时区。

    虽然我不使用 MySQL,但 it looks like 等效于标准类型是 DATETIME

    DATE

    标准类型DATE 表示仅日期值,没有时间和时区。

    如您所见,仅日期值是不明确的。对于任何给定的时刻,日期在全球范围内因区域而异。

    听起来这符合您的需求。当你提到一个日期时,你是在暗示一个时刻。无论您的业务规则是什么,也许印度时间 (Asia/Kolkata) 或芝加哥时间中午 (America/Chicago) 或 UTC 一天的第一刻开始营业。

    您需要进行调查以确定您试图以数据形式表示的信息的实际含义。

    所有这些都已经在 Stack Overflow 上讨论过很多次了。请在发帖前彻底搜索,现在就了解更多。

    请注意,日期时间工作很棘手,而且往往违反直觉。如果您天真地认为日期时间工作应该快速简单,那么您需要了解更多信息。慢下来,学习和实验。

    示例

    如果您记录的是 10 月 3 日上午 8:00 在印度接受的订单,请将其存储为 UTC:2017-10-03 02:30Z,因为印度比 UTC 早五个半小时。提示:Z 是 Zulu 的缩写,表示 UTC。

    如果用户想要查看与另一个时区相同的时刻,请进行调整。对于America/Chicago,这将比 UTC 5 小时,因此上一个日期是 10 月 2 日而不是 3 日:2017-10-02 21:30。这是与其他两个同时发生的时刻。我们有三种查看同一时刻的方式。

    【讨论】:

      【解决方案2】:

      您可以使用时间戳。它会自动转换为 UTC。然后在正在运行的服务器上计算时间差。但这需要您在访问日期的任何地方将该逻辑放入代码(或选择语句)中。 See this post

      否则,使用 date 或 datetime 可能是相同的,因为两者都不存储时区。日期时间似乎更精确,因为它记录到秒而不是当天。

      查看documentation

      只需转到链接并按 Ctrl + F,然后搜索“时区”,您就可以确切地看到时区是如何处理的。

      似乎时区不会转换为日期时间。但是,如果您的服务器在不同的时区运行,这仍然可能是一个问题,因为当您读取时,使用服务器的日期时间,并且不能保证正在读取记录的服务器在同一时区写入记录的服务器 - 这可能会引入错误。

      为了解决这个问题。我曾经在一个团队工作,该团队将日期时间存储为字符串,时区附加到末尾。

      // In this format
      Mon, 17 Apr 2006 21:22:48 GMT
      

      然后,当我们从数据库中读取数据时,我们将它们转换为 Java 8 String Datetime 对象。但是,我知道这是一个非常具体的实现。

      【讨论】:

      • 如果我们将日期存储在 varchar 中,我们不能在检索记录时对该字段设置条件。但是是的,如果我们以上述格式存储日期,我们的问题将得到解决,但它会在检索查询期间产生问题。
      • 也许 convert_tz() 函数可以解决你的问题:dev.mysql.com/doc/refman/5.7/en/…
      【解决方案3】:

      DATE, DATETIME, and TIMESTAMP MySQL之间的区别

      1. DATE 类型用于具有日期部分但没有时间部分的值。 MySQL 以 'YYYY-MM-DD' 格式检索和显示 DATE 值。这 支持的范围是“1000-01-01”到“9999-12-31”。
      2. DATETIME 类型用于同时包含日期和时间的值 部分。 MySQL 检索并显示 'YYYY-MM-DD 中的 DATETIME 值 HH:MM:SS' 格式。支持的范围是 '1000-01-01 00:00:00' 到 '9999-12-31 23:59:59'。
      3. TIMESTAMP 数据类型用于包含两个日期的值 和时间部分。 TIMESTAMP 的范围为 '1970-01-01 00:00:01' UTC 到 '2038-01-19 03:14:07' UTC。

      【讨论】:

      • 你忘记了相关部分:MySQL converts TIMESTAMP values from the current time zone to UTC for storage, and back from UTC to the current time zone for retrieval. (This does not occur for other types such as DATETIME.)
      猜你喜欢
      • 1970-01-01
      • 2012-05-18
      • 2016-11-20
      • 1970-01-01
      • 2021-12-04
      • 1970-01-01
      • 2019-01-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多