我在数据库中有一个列(postgresql) 我想在此列中插入GMT中的当前时间 获取当前时间并将其插入数据库 它被插入服务器时区GMT-5,虽然那个时间是GMT + 0 任何想法如何在GMT时区的数据库中插入这个时间?
答案 0 :(得分:2)
了解 Postgres 总是 将值存储在 TIMESTAMP WITH TIME ZONE
中 UTC 类型的列中,即 offset from UTC 为零时-分-秒.
所以这个名字有点用词不当,因为实际上没有存储时区。相反,Postgres 使用任何随输入到达的时区或偏移指示符来调整到 UTC。调整后,UTC 值被存储到表中,而区域/偏移指示符被丢弃。如果您关心原始时区,则必须自己将其写入第二列。
令人困惑的是工具和中间件,例如 psql 控制台客户端应用程序。这些通常是自以为是,选择将一些默认时区调整注入检索到的值。因此,虽然 Postgres 数据库总是从任何 TIMESTAMP WITH TIME ZONE
列中检索 UTC 日期时间,但您可能会在接收端看到其他情况。这样的功能虽然是善意的,但在我看来却是不幸的反功能。
幸运的是,我还没有看到任何 JDBC driver 执行这样的调整。从 TIMESTAMP WITH TIME ZONE
列(如下所述)检索 OffsetDateTime
时,您应该始终获得 UTC 值。但请务必测试您的特定 JDBC 驱动程序。
Java 中处理日期时间的现代解决方案是 java.time 类。
要捕捉当前时刻,请使用 Instant
。此类表示以 UTC 格式显示的时刻。
Instant instant = Instant.now() ; // Capture the current moment as seen in UTC.
然而,尽管 Instant
是最基本也可能是最常用的 java.time 类,JDBC 4.2 团队做出了莫名其妙的决定,不 需要它的支持。 (顺便说一下,也不需要 ZonedDateTime
支持。)
相反,JDBC 4.2 规范要求支持 OffsetDateTime
。幸运的是,Instant
和 OffsetDateTime
之间的转换是微不足道的。
OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;
或者你可以跳过 Instant
类就是这种情况。
OffsetDateTime odt = OffsetDateTime.now( ZoneOffset.UTC ) ;
写入数据库。
myPreparedStatement.setObject( … , odt ) ;
从数据库中检索。
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
此 OffsetDateTime
对象将携带从 UTC 零时分秒的指定偏移量 — 通常简称为“UTC”作为缩写。
如果需要,提取一个 Instant
。
Instant instant = odt.toInstant() ;
或者调整到时区。
ZoneId z = ZoneId.of( "Asia/Tokyo" ) ;
ZonedDateTime zdt = odt.atZoneSameInstant( z ) ;
关于可能丢失数据的警告:java.time 中的分辨率是 nanoseconds。捕捉当前时刻可能仅限于微秒,因为当今常用的硬件时钟再好不过了。尽管如此,诸如 OffsetDateTime
之类的 java.time 对象可能会携带纳秒。同时,Postgres 日期时间值的分辨率为 microseconds。因此,如果使用带有任何 nanos 的 java.time 对象,使用 Postgres 写入该值将截断 nanos,从而导致稍后检索不同的值。
答案 1 :(得分:1)
我认为manual的第8.5.1.2段可能具有启发性。它声明默认情况下,假定时间没有时区,如果给出一个,则会默默忽略。
为了清楚说明,我认为最好明确表示时间:
pti=> select timestamp with time zone '20100610T180000-5';
timestamptz
------------------------
2010-06-11 01:00:00+02
(1 row)
pti=> select timestamp with time zone '20100610T180000PST';
timestamptz
------------------------
2010-06-11 04:00:00+02
(1 row)
很明显,时区的时间已从本地时间正确转换为服务器时间。
答案 2 :(得分:0)
SELECT current_timestamp AT TIME ZONE 'gmt-5';