java - UTC 或时区时间戳的 SQL 标准

标签 java sql date datetime timestamp

我正在寻找一种标准的 SQL 方法,以确保独立于数据库的列具有 UTC 时间戳或作为时区信息的时间戳。 在数据库列中存储时间戳 UTC 的 UTC 示例:

  • 存储的 UTC 值 = 2014-01-01 15:30:00.000

    本地时间印度 21:00/9pm 作为本地时间戳“2014-01-01 21:00:00.000”

  • 存储的 UTC 值 = 2013-12-31 23:30:00.000

    本地时间印度 05:00/5am 作为本地时间戳“2014-01-01 05:00:00.000”

在 UTC 方式中,应用程序必须处理时区

现在我真的不知道是否可以使用具有上述值的时间戳和时区

  • 存储的本地值 = 2014-01-01 21:00:00.000

    本地时间印度 21:00/9pm 作为本地时间戳“2014-01-01 21:00:00.000”

    但是有时区信息?

    或者如何获取这个时间戳的时区信息?

  • 存储的本地值 = 2014-01-01 05:00:00.000

    本地时间印度 05:00/5am 作为本地时间戳“2014-01-01 05:00:00.000”

    但是有时区信息?

    或者如何获取这个时间戳的时区信息?

希望有人能帮我走出黑暗? 在时区问题和存储数据以供国际应用方面是否有良好做法?

最佳答案

tl;dr

要存储时间轴上的一个时刻,定义一个 SQL 标准类型的数据库列 TIMESTAMP WITH TIME ZONE

以 UTC 格式存储时刻。

Instant instant = Instant.now() ;  // Capture the current moment in UTC. 
myPreparedStatement.setObject( … , instant ) ;

以 UTC 格式检索时刻。

Instant instant = myResultSet.getObject( … , Instant.class ) ; 

从 UTC 调整到时区。同一时刻,不同的挂钟时间。

ZoneId z = ZoneId.of( "Asia/Kolkata" ) ;  // Specify time zone in proper `Continent/Region` name, never the ambiguous non-standard 3-4 letter pseudo-zone such as `IST` or `PST`. 
ZonedDateTime zdt = instant.atZone( z ) ;

从时区调整为 UTC。同一时刻,不同的挂钟时间。

Instant instant = zdt.toInstant() ;

日期时间不是字符串

严肃的数据库不会将日期时间值存储为字符串。不要将数据库或 Java 库生成的字符串表示与日期时间值本身混淆。

存储 UTC

最佳做法是使用 UTC用于您的数据库和其他存储,以及您的大部分业务逻辑。出现在 local time zones仅符合用户的预期。

参见维基百科 standard date-time types .就算不会用Postgres,也请教优秀documentation on date-time data types .但我确实推荐 Postgres,原因有很多,包括它对日期时间的出色支持。

使用TIMESTAMPZ

这位 Postgres 专家提出了简单而明智的建议:Always Use TIMESTAMP WITH TIME ZONE

该数据类型的名称用词不当,造成了很多困惑。时区信息存储。这意味着遵守传入数据指示的时区,存储的值将调整为 UTC .将 TIMESTAMP WITH TIME ZONE 视为 TIMESTAMP WITH RESPECT FOR TIME ZONE。大声重读这一段三遍,然后阅读上面的链接,并做一些实验以确保您理解。

您可能还想单独存储原始时区信息。不用于您的业务逻辑,而是用作调试的日志信息。

Java

至于 Java,一定要避免使用 java.util.Date 和 .Calendar 类。他们是出了名的麻烦。它们被替换为 Java 8通过新java.time package .使用该包和/或 Joda-Time 2.4 启发了 java.time 的库。

时区

并且在 Java 中始终指定所需的时区。如果省略,您将隐含地使用 JVM 当前的默认时区。这种隐含的默认意味着你的结果会随着时间和空间的不同而变化。这是日期时间工作中许多问题的根本原因。如果你想要 UTC,请使用 Joda-Time 中的常量,DateTimeZone.UTC .

忽略时区不会让您的生活更轻松。

ISO 8601

这个标准非常有用和明智。研究excellent Wikipedia page .应该是字符串表示的首选。

搜索 StackOverflow

这些问题已经包含在数百个(如果不是数千个)答案中。

关于java - UTC 或时区时间戳的 SQL 标准,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25227357/

相关文章:

PHP, MYSQL : Order by date but empty dates last not first

date - Grails:执行标签<g:formatDate>时出错:未知类:带有根本原因的java.lang.String

sql-server - 获取 SQL Server 中没有条目的日期列表

java - 如何在 hibernate 中映射 String[]

java - 将短语与全文进行比较

mysql - 事件记录 : LEFT OUTER self-JOIN with conditions on joined table

sql - 选择具有两种类型postgresql的不同ID

java - 如何制作与图像图标全尺寸的 JLabels?

java - 在Spring Boot中更新基础Spring版本

java - SQLite 在不使用循环的情况下获取结果查询中的单行位置