【问题标题】:When is it ok to store datetimes as local time rathen than UTC?什么时候可以将日期时间存储为当地时间而不是 UTC?
【发布时间】:2014-02-03 14:58:15
【问题描述】:

这是一个类似于this one的问题。

我真的很想在我的应用程序中将日期时间存储为当地时间而不是 UTC(这被认为是最佳实践)。在应用程序中,我发生了许多事件,每个事件都分配到给定位置。当我向用户显示它们时,我总是想显示事件的本地时间。即:

====================================================================================
Event time (with TZ)   | As UTC           | As local time    | To be displayed  |
====================================================================================
2014-01-15 22:30 GMT   | 2014-01-15 22:30 | 2014-01-15 22:30 | 2014-01-15 22:30 |
2014-01-15 23:30 GMT+1 | 2014-01-15 22:30 | 2014-01-15 23:30 | 2014-01-15 23:30 |
2014-01-16 00:30 GMT+2 | 2014-01-15 22:30 | 2014-01-16 00:30 | 2014-01-16 00:30 |
====================================================================================

如果我决定以 UTC 存储事件时间:

  • 很难显示它们(因为对于每个事件,我都需要有事件的时区并格式化该时区的日期)。

  • 查询它们将非常困难(即,如果我想显示当地时间 2014 年 1 月 15 日发生的所有事件,我需要为每个事件将该事件的时间与 '2014-01- 15' 表示在该事件的时区中。不确定这在 SQL 中是否可行...)

如果我决定将事件时间存储为当地时间:

  • 我无法比较不同地点的活动时间(但这对我来说没问题)

因为在应用程序的绝大多数情况下,我对当地时间(通常显示所谓的“电视时间”)感兴趣,并且我创建新的日期时间对象的情况并不多(例如我需要位置时区),我相信在这种情况下将日期时间保存为本地时间是合理的。

你认为是吗?存储当地时间还有哪些其他缺点?

提前感谢您的关注和帮助。

【问题讨论】:

  • 您的目标是什么语言和数据库?
  • @Matt Johnson:Java + PostgreSQL
  • 那么请确保您熟悉Joda Time。那么事情应该为你排好队并且更有意义。
  • 是的,已经使用 Joda Time 了:)
  • 好。因此,只有在您拥有 Joda LocalDateTime 的情况下,您才应该在数据库中考虑当地时间。如果您有 InstantDateTime,那么您应该存储与 UTC 相关的数据。

标签: datetime time timezone utc dst


【解决方案1】:

使用 UTC 最常被忽视的情况是安排未来时间 - 尤其是在重复模式中。

想象一下,如果您的闹钟是由 UTC 安排的。假设您将其设置为每天早上 7:00。在 DST 转换后的第二天,您可能会在早上 6:00 或早上 8:00 醒来,具体取决于转换的方向。

此外,我们确定时区偏移和夏令时更改的规则会一直更新!因此,如果 保留本地时间本身,您就不能将未来的本地时间转换为 UTC。否则,当事情发生变化时,您将没有原始的事实来源,并且您的所有时间都将再次关闭。

我已经在thismanytimesbefore发帖。

当然,一旦事件发生,那么您当然希望以 UTC 或使用 DateTimeOffset 记录时间。

另一个常见的用例是没有时间的日期,尤其是出生日期和其他周年日期。这些应该始终存储为年、月、日(例如在大多数数据库中的 date 字段类型中) - 时区或 UTC 之间没有转换。

关于你的具体观点:

如果我决定以 UTC 格式存储事件时间......将很难显示它们......

其实这很容易。几乎每个编程环境都可以轻松做到这一点。唯一困难的地方是在非本地时区的 JavaScript 中,并且有一些库可以解决这个问题。

如果我决定以 UTC 存储事件时间......查询它们将非常困难(即,如果我想显示在当地时间 2014 年 1 月 15 日发生的所有事件,我需要对每个事件进行比较该事件的时间与“2014-01-15”在该事件的时区中的含义。不确定这在 SQL 中是否可行...)

确实如此。每个人的“今天”都不一样。如果您需要与浮动“日”相关的数据,那么这是另一种不存储在 UTC 中的情况。但是,DateTimeOffset 可以为您提供两者的优势。

如果我决定将事件时间存储为当地时间......我将无法比较不同位置的事件时间(但这对我来说没问题)

不止于此。对于daylight saving time fall-back transitions,没有偏移量的本地日期时间可能不明确。所以你可能有一个本地值,你无法区分它对应于两个时间点中的哪一个。

关于“电视时间” - 为真正“浮动”的事物保留这个概念。示例:一家公司在世界各地都有办事处,所有办事处都在上午 8:00 开始。那是一个漂浮的时间。

【讨论】:

  • 感谢您提供宝贵的见解。您提到 DateTimeOffset 会给我两者的优势。如果查询在数据库级别工作并且 DateTimeOffset 在应用程序级别,这怎么可能?您的意思是在 SQL 中获取更多行,然后在应用级别过滤掉它们?
  • 在 Postgres 中,您可以使用 TIMESTAMP WITH TIME ZONE 数据类型。然后,您可以查看本地值(原样)或 UTC 值(考虑到偏移后)任何一个。但是,使用 SQL Server 的 DATETIMEOFFSET 类型要容易得多。 Postgres 可能会妨碍您。
  • 如果您打算拥有大量数据,那么最好使用单独的字段,这样即使您存储的是 UTC 时间戳,您也可以按本地日期进行索引。因此,您将使用 TIMESTAMP WITHOUT TIME ZONE 作为 UTC 部分,可能只使用 DATE 作为本地日期值。
  • 另外,请务必通读 Postgres 文档的以下部分:herehere
  • 这本质上是一个悬而未决的问题,但我将其标记为答案,因为它是唯一的答案,而且很有帮助:)
猜你喜欢
  • 2016-04-11
  • 2021-09-28
  • 1970-01-01
  • 2012-10-07
  • 1970-01-01
  • 2018-05-08
  • 1970-01-01
  • 2016-08-07
  • 2013-07-09
相关资源
最近更新 更多