【问题标题】:Want to store utc time in my database, and at the UI level a timezone specific timestamp [duplicate]想要将UTC时间存储在我的数据库中,并在UI级别存储特定于时区的时间戳[重复]
【发布时间】:2014-07-11 17:11:27
【问题描述】:

对于我的数据库中基于事件的列,例如 createdDate,我想存储一个 UTC 值。

如果我目前正在做的事情能正确解决我的问题,我正在寻求建议。

  1. 在 postgresql 中,我将使用没有时区列的时间戳
  2. 在我的 scala(类似于 java)代码中,我将生成一个时间戳,例如:

    val currentMs: Long = System.currentTimeMillis
    new java.sql.Timestamp(currentMs)
    
  3. 我会将该值保存到数据库中。我所有的服务器时间都将同步。 现在在数据库级别,我存储的是纯 UTC 值。

  4. 当我从数据库中检索数据时,我将使用Joda-Time 从数据库中获取时间戳值,然后将该值转换为特定时区。

这是执行 UTC 的正确方法吗? 我是否在这里遗漏了一些东西,因为当您在谷歌上搜索时,这个主题令人困惑:)

注意:这是一个全新的项目,因此我可以毫无问题地进行更改。

更新

在步骤#2 中,如果我只是将原始 currentMs 值存储在一个长列中,而不是存储来自 java.sql.Timestamp 的值,该怎么办。然后在 UI 中,我会根据登录的用户将 unix 时间转换为特定的时区。

这样合适吗?

【问题讨论】:

  • 我对 Scala 或您提到的 Jodatime 一无所知。但是,对于 PostgreSQL,使用“带时区的时间戳”并在存储时间戳时提供时区。这将存储一个绝对时间戳。然后,在检索时只需指定您的客户端时区(或使用AT TIME ZONE t)。不知道这一切将如何与您的框架层一起使用。
  • @RichardHuxton 为什么我要在 postgresql 中指定时区,我不只需要原始 utc/unix 时间吗?我不明白。
  • timestamp without time zone 与 UTC 时间相同。它是一个被解释为“本地时间”的值。含义取决于您当前的时区设置(并随其变化)。这个相关的答案可能会有所帮助:stackoverflow.com/questions/9571392/…
  • @RichardHuxton JodaTime 将变得非常重要 - 它是新的日期/时间 API 的基础,最终被引入 Java 以取代 java.util.Date 的古老恐怖和不太好 @987654327 @类。
  • 我强烈建议在数据库中使用 timestamp with time zone,尤其是在您存储 UTC 瞬间时。否则听起来不错。

标签: java postgresql scala jodatime utc


【解决方案1】:

(a) 搜索 StackOverflow,因为这已被多次询问和回答。

(b) 关于您的第 1 项:不,不要使用TIMESTAMP WITHOUT TIME ZONE。该数据类型意味着 Postgres 将忽略任何指定的时区。

Postgres 专家David E Wheeler advises 始终使用TIMESTAMP WITH TIME ZONE(有一个罕见的例外)。

仔细阅读the doc不要假设数据类型如何工作。 “有/无时区”的名称用词不当,因为 Postgres 时间戳从来没有时区信息(它们以 UTC 为框架)。 “有/无时区”之间的区别在于在插入/选择数据时是否尊重/应用时区。

做一些实验来澄清你的理解。

(c) 是的,通常最好将您的日期时间值存储为 UTC,同时转换为本地时间(时区)仅用于演示。

(d) Postgres 具有捕获当前日期时间的功能。您可以在适当的情况下调用这些函数,而不是在 Java/Scala 代码中这样做。

(e) 不确定第 3 项第二句是什么意思。如果您指的是计算机上的时钟,则几乎总是最好将服务器的时区设置为 UTC(或冰岛雷克雅未克)。但是你的数据库和编程永远不应该依赖于此。

Postgres 对日期时间工作有很好的支持(在所有数据库中最好的),但请仔细阅读文档,以便了解其中的细微差别。

【讨论】:

  • 我很困惑的是,为什么我不能将 unix time/utc 存储在数据库中的一个长字段中,然后当我在我的 UI 中显示时间时,只需将其转换为当前登录的用户时区?
  • @Blankman 出于同样的原因,您不会将文本作为八位字节数组处理,而是自己进行 Latin-1、UTF-8 和 UTF-16 翻译。你可以,但我敢打赌你不会。您在编程语言/库、数据库字段和数据库驱动程序中使用文本数据类型来帮助您处理处理文本的琐碎琐事。所以对日期时间做同样的事情。直接将日期时间作为长整数处理会使您难以验证值,从而导致错误和混乱。
  • 立即第一个问题,滚动你自己的日期时间为 longs:旧的 java.util.Date 类和 Joda-Time 跟踪时间为 毫秒,因为Unix 时代。 Java 8 中的新 java.time 包跟踪自 Unix 纪元以来的 纳秒。较旧的日期时间实用程序跟踪自纪元以来的整秒。而且,如果您确实遇到了任何 Postgres TIMESTAMP 值,那么这些值是来自不同时期 2000-01-01 的小数秒。你知道有many more epochs 被各种系统和库使用吗?日期时间是杂乱无章的工作;尽你所能获得帮助。
  • 有趣,感谢您对此有所了解。我的头已经很痛了:)
【解决方案2】:

What is the most recommended way to store time in PostgreSQL using Java? 可能重复

请注意,无论数据类型名称如何,postgresql 实际上并不存储时区。

另请参阅我的博客文章http://greybeardedgeek.net/2012/11/24/java-dates/

【讨论】:

    【解决方案3】:

    是的,自数据库中的纪元以来保存毫秒并仅在本地将它们转换为时区是一个好方法。这也使您可以忘记保持日期/时间的数据库类型,而只需将毫秒存储为数字。这也是我的首选方法,而且它很酷:它适用于多种类型的数据库。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-10-10
      • 2016-08-24
      • 2015-04-06
      • 2011-04-17
      • 2014-02-05
      • 1970-01-01
      • 2018-08-19
      相关资源
      最近更新 更多