我正在寻找一种标准的 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/