【问题标题】:What is proper way to persist time or date -type of information into database?将时间或日期类型的信息保存到数据库中的正确方法是什么?
【发布时间】:2014-08-21 07:46:17
【问题描述】:

在数据库中保存基于日期或时间的数据的正确方法是什么? java到postgresql(或其他数据库)的正确“字段映射”是什么?

该数据应以没有时区的 utc 格式存储。

-> 基于时间戳和日期的东西在这里失败,它们将添加当前时区 (http://docs.oracle.com/javase/7/docs/api/java/util/Date.html)

-> 其他选项是什么?

我应该使用“plain epoch/integer”列和其他列作为时区吗?但是我无法使用数据库为我提供的所有功能等。

我可以通过一些 jodatime 魔法来使用休眠,但在我当前的堆栈中,我没有使用休眠。

可能的解决方案:

1)。更改计算机/java 时区 -> Java 将在 UCT 中(例如 export TZ="GMT" 或 -Duser.timezone=UCT)

2)。在日期/时间字段/类型中使用 epoch/Integer/Long 值 -> 有效,但现在我无法使用内置数据库函数。

3)。将 Jodatime 与自定义休眠数据类型一起使用?

4)。使用 Java8 新的时间和日期 API?

【问题讨论】:

  • Java 中的日期没有时区。一旦您将其格式化为字符串(或转换为 java.util.Calendar),它就只有一个时区。日期只是一个很长的包装(自纪元以来的毫秒数,1970 年 1 月 1 日,格林威治标准时间 00:00:00)。
  • 如果您将日期保存/保存到数据库中,它将转换为时间+时区
  • Postgres 确实支持timestamp without time zone。你试过吗?我认为在这种情况下,当您将其读入java.sql.Timestamp 时不会发生任何转换(但我不完全确定)
  • 这是一个java问题,数据库没有问题:)

标签: java postgresql date time persist


【解决方案1】:

在大多数情况下,在处理多个时区或要将所有时间戳保存为 UTC 时,最好使用 Postgres 数据类型 timestamptztimestamp with time zone 的缩写)。

不要让名字误导你,时区实际上并没有被保存。但是(与timestamp [without time zone] 不同)来自文本输入的时区被考虑为修饰符来计算实际的 UTC 时间戳值,该值被保存。
输出上,值的文本表示会根据您的当前时区设置进行格式化:时间戳会发生偏移并附加相应的时区修饰符。

请注意,没有附加时区的时间戳将根据会话的当前时区设置进行解释。如果您想输入 不考虑当前时区的文字 UTC 值,它必须是:

'2014-08-21 16:39:09+0'::timestamptz

不是:

'2014-08-21 16:39:09'::timestamptz  -- would assume current time zone

此相关答案中的详细说明:

【讨论】:

    【解决方案2】:

    正如您所说,最好将日期作为 UTC 存储在数据库中。在 oracle 中,您可以使用 DATE 或 TIMESTAMP 数据类型。然后,您可以使用 java 层以本地时间和 java.sql.timestamp 列向用户显示您的日期。 Joda 本质上内置于最新版本的 java 中,因此绝对将其用于任何转换等。替代方法是将时间戳与时区存储在 oracle 中,并可能在您的 sql 和存储过程中使用 oracle 日期函数来根据需要转换日期。我们做前者,但这可能取决于您的团队(db 人员与 java 人员)和您的受众 - 用户群中可能有很多不同的时区,或者 DST 转换的时间是否会破坏您的应用程序。

    如果您能描述您担心的特定情况,我相信有人会提供帮助。以 UTC 存储您的数据至少可以确保您的数据是可靠的,但可能需要在表示层进行多次转换。

    【讨论】:

    • 但是在 oracle 的情况下,如果你使用的是不一样的,例如。持久化时刻的时间戳,它会自动添加时区偏移量..
    • pasuna - 请将 TIMESTAMP 与 TIMESTAMP WITH TIMEZONE 进行比较,时间戳通常包含服务器返回的 UTC 值,例如 SELECT SYSTIMESTAMP FROM DUAL 例如docs.oracle.com/cd/B19306_01/server.102/b14225/ch4datetime.htm
    • 我说的是java类,不是数据库字段类型:docs.oracle.com/javase/7/docs/api/java/sql/Timestamp.html
    • 没错,但如果您的底层数据结构没有单独存储时区,那么在多个区域之间轻松呈现时区可能会遇到很多麻烦
    【解决方案3】:

    没有一种正确的方法,但我认为您应该将时间存储为长 unix 时间戳,将单个日期存储为纪元日。 Java 8 有很好的函数来处理它们。避免仅仅为了管理约会而使用 jodatime 和休眠来锁定自己。

    数据库为您提供的功能是什么意思? 您始终可以使用整数和 long 进行 SQL 选择,因为它们是从您的程序中调用的。

    如果您需要大量手动使用数据库(非编程),那么您可能希望使用人类可读的日期。

    【讨论】:

    • 是的,java 8 中有很好的功能等,但是早期版本的 java 呢? oracle.com/technetwork/articles/java/…
    • 如果您希望能够使用任何数据库服务器,您将不得不像我使用 android 和 sqlite 一样使用它。如果您想使用带有时区的 db 时间戳的某些功能将为您做很多工作。我们目前使用 joda 作为 Java 7 的库
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多