简体   繁体   English

如何使用时区保存时间戳

[英]How to save timestamp with timezone

My Project support Postgres and SQLServer DB.我的项目支持 Postgres 和 SQLServer DB。 I have a timestamp with a timezone column in my table x.我的表 x 中有一个带有时区列的时间戳。 When I save timestamp value in the DB.当我在数据库中保存时间戳值时。 I'm getting as "2022-07-01 00:00:00.000000 +05:30" in the Postgres but in SQL server it is saving as "2022-07-01 00:00:00.000000 +00:00".我在 Postgres 中得到“2022-07-01 00:00:00.000000 +05:30”,但在 SQL 服务器中它保存为“2022-07-01 00:00:00.000000 +00:00”。 Can someone help me on how to get the value as Postgres in SQL server also?有人可以帮助我如何在 SQL Server 中获得 Postgres 的价值吗? Here is my java code这是我的java代码

   DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd'T'HH:mm:ss");
   Date parsedDate = dateFormat.parse("20220701T00:00:00") //this value comes as argument for this method. 
   return new Timestamp(parsedDate.getTime());

I'm getting as "2022-07-01 00:00:00.000000 +05:30" in the Postgres我在 Postgres 中得到“2022-07-01 00:00:00.000000 +05:30”

No, you're not.不你不是。

A TIMESTAMP WITH TIME ZONE column in Postgres stores its values “in UTC”, meaning an offset from UTC of zero hours-minutes-seconds. Postgres 中的TIMESTAMP WITH TIME ZONE列以“UTC 格式”存储其值,这意味着与 UTC 的偏移量为零小时-分钟-秒。 Any time zone or offset supplied with an input is used to adjust to UTC, then discarded.输入提供的任何时区或偏移量都用于调整到 UTC,然后被丢弃。

Unfortunately, some tools and middleware have the anti-feature of applying a current default time zone to the retrieved value.不幸的是,一些工具和中间件具有将当前默认时区应用于检索值的反特性。 pgAdmin is one such tool, I'm sad to report. pgAdmin就是这样一种工具,我很遗憾地报告。

Another problem is that the toString method of java.util.Date also has the same anti-feature, applying the JVM's current default time zone.另一个问题是java.util.DatetoString方法也有同样的反特性,应用JVM当前的默认时区。

Fortunately, the terrible Date class was supplanted years ago by the modern java.time classes defined in JSR 310. JDBC 4.2 and later requires support for java.time .幸运的是,可怕的Date类在几年前被 JSR 310 中定义的现代java.time类所取代。JDBC 4.2 及更高版本需要对java.time的支持。 No need to ever use Date , Calendar , and Timestamp .无需使用DateCalendarTimestamp

To retrieve a value from a TIMESTAMP WITH TIME ZONE column:要从TIMESTAMP WITH TIME ZONE列中检索值:

OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ; 

👉 You'll see that object has an offset of zero, the true value stored in Postgres. 👉 您会看到该对象的偏移量为零,即存储在 Postgres 中的真实值。

To write:来写:

myPreparedStatement.setObject( … , odt ) ;

As for your input string, it lacks an indicator of time zone or offset.至于您的输入字符串,它缺少时区或偏移量的指示符。 So parse as a LocalDateTime .所以解析为LocalDateTime

DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuuMMdd'T'HH:mm:ss" ) ;
String input = "20220701T00:00:00" ; 
LocalDateTime ldt = LocalDateTime.parse( input , f ) ;

Now assign the intended time zone or offset to get a ZonedDateTime or OffsetDateTime respectively.现在分配预期的时区或偏移量以分别获得ZonedDateTimeOffsetDateTime I'll assume you intend an offset of zero.我假设您打算将偏移量设为零。

OffsetDateTime odt = ldt.atOffset( ZoneOffset.UTC ) ; 

I suggest you educate the publisher of your data about proper use of standard ISO 8601 format.我建议您对数据的发布者进行有关正确使用标准ISO 8601格式的教育。

Your input string is mixing the full format for the time-of-day portion with its COLON characters with the abbreviated “basic” format for the date portion.您的输入字符串将时间部分的完整格式与其冒号字符与日期部分的缩写“基本”格式混合在一起。

I recommend sticking with the full expanded format.我建议坚持使用完整的扩展格式。

2022-07-01T00:00:00 2022-07-01T00:00:00

And if the publisher of that data intended an offset of zero, they should say so.如果该数据的发布者打算将偏移量设为零,他们应该这么说。 Append a Z , pronounced Zulu .附加一个Z ,发音为Zulu Or append +00:00 , though I'd recommend the Z .或附加+00:00 ,但我推荐Z

2022-07-01T00:00:00Z 2022-07-01T00:00:00Z


All this has been covered many times on Stack Overflow.所有这些都在 Stack Overflow 上多次介绍过。 Search to learn more.搜索以了解更多信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM