jdbc时区_什么比日期和时区更难? SQL / JDBC中的日期和时区!
jdbc時區
在jOOQ郵件列表上,最近有一個有趣的討論,關于jOOQ當前缺乏對TIMESTAMP WITH TIME ZONE數據類型的現成支持。
沒有人說日期,時間和時區很容易! 這里有一個有趣的文章,我建議閱讀: 虛假的程序員相信時間
當那還不夠時,還請閱讀: 更多的虛假程序員相信時間
我個人喜歡程序員錯誤地認為“ Unix時間是自1970年1月1日以來的秒數”。 …Unix時間無法代表leap秒;)
返回JDBC
這是Jaybird開發人員(Firebird JDBC驅動程序) Mark Rotteveel提出的一個有趣的Stack Overflow答案: java.sql.Timestamp時區是否特定?
可以按照以下方式觀察Mark的解釋(我在這里使用PostgreSQL):
Connection c = getConnection(); Calendar utc = Calendar.getInstance(TimeZone.getTimeZone("UTC"));try (PreparedStatement ps = c.prepareStatement("select"+ " ?::timestamp,"+ " ?::timestamp,"+ " ?::timestamp with time zone,"+ " ?::timestamp with time zone" )) {ps.setTimestamp(1, new Timestamp(0));ps.setTimestamp(2, new Timestamp(0), utc);ps.setTimestamp(3, new Timestamp(0));ps.setTimestamp(4, new Timestamp(0), utc);try (ResultSet rs = ps.executeQuery()) {rs.next();System.out.println(rs.getTimestamp(1) + " / " + rs.getTimestamp(1).getTime());System.out.println(rs.getTimestamp(2, utc)+ " / " + rs.getTimestamp(2, utc).getTime());System.out.println(rs.getTimestamp(3) + " / " + rs.getTimestamp(3).getTime());System.out.println(rs.getTimestamp(4, utc)+ " / " + rs.getTimestamp(4, utc).getTime());} }上面的程序使用Java和DB中使用時區而不使用時區的所有排列,并且輸出始終相同:
1970-01-01 01:00:00.0 / 0 1970-01-01 01:00:00.0 / 0 1970-01-01 01:00:00.0 / 0 1970-01-01 01:00:00.0 / 0如您所見,在每種情況下,UTC時間戳0均已正確存儲并從數據庫中檢索到。 我自己的語言環境是瑞士,即CET / CEST,在Epoch是UTC + 1,這是在Timestamp.toString()上獲得的輸出。
當您在SQL和/或Java中使用時間戳文字時,事情會變得很有趣。 如果這樣替換綁定變量:
Timestamp almostEpoch = Timestamp.valueOf("1970-01-01 00:00:00");ps.setTimestamp(1, almostEpoch); ps.setTimestamp(2, almostEpoch, utc); ps.setTimestamp(3, almostEpoch); ps.setTimestamp(4, almostEpoch, utc);這又是我在CET / CEST上獲得的機器上的東西
1970-01-01 00:00:00.0 / -3600000 1970-01-01 00:00:00.0 / -3600000 1970-01-01 00:00:00.0 / -3600000 1970-01-01 00:00:00.0 / -3600000即不是Epoch,而是我首先發送到服務器的時間戳文字。 請注意,綁定/獲取的四種組合仍然始終產生相同的時間戳。
讓我們看看如果寫入數據庫的會話使用與從數據庫獲取會話不同的時區(假設您在PST中)(我再次使用CET或UTC),會發生什么。 我正在運行此程序:
Calendar utc = Calendar.getInstance(TimeZone.getTimeZone("UTC"));Calendar pst = Calendar.getInstance(TimeZone.getTimeZone("PST"));try (PreparedStatement ps = c.prepareStatement("select"+ " ?::timestamp,"+ " ?::timestamp,"+ " ?::timestamp with time zone,"+ " ?::timestamp with time zone" )) {ps.setTimestamp(1, new Timestamp(0), pst);ps.setTimestamp(2, new Timestamp(0), pst);ps.setTimestamp(3, new Timestamp(0), pst);ps.setTimestamp(4, new Timestamp(0), pst);try (ResultSet rs = ps.executeQuery()) {rs.next();System.out.println(rs.getTimestamp(1)+ " / " + rs.getTimestamp(1).getTime());System.out.println(rs.getTimestamp(2, utc)+ " / " + rs.getTimestamp(2, utc).getTime());System.out.println(rs.getTimestamp(3)+ " / " + rs.getTimestamp(3).getTime());System.out.println(rs.getTimestamp(4, utc)+ " / " + rs.getTimestamp(4, utc).getTime());} }它產生以下輸出:
1969-12-31 16:00:00.0 / -32400000 1969-12-31 17:00:00.0 / -28800000 1970-01-01 01:00:00.0 / 0 1970-01-01 01:00:00.0 / 0第一個時間戳記是將Epoch存儲為PST(16:00),然后數據庫中刪除了時區信息,這將Epoch轉換為您在Epoch處的本地時間(-28800秒/ -8h),即真的存儲了。
現在,當我從自己的時區CET獲取此時間時,我仍然想要獲取當地時間(16:00)。 但是在我的時區,這不再是-28800秒,而是-32400秒(-9h)。 夠古怪嗎?
當我獲取存儲的本地時間(16:00)時,事情反過來了,但是我強迫獲取發生在UTC中,這將產生您存儲的時間戳,最初是PST(-28800)秒)。 但是,在我的時區CET中打印此時間戳(-28800秒)時,現在是17:00。
當我們在數據庫中使用TIMESTAMP WITH TIME ZONE數據類型時,將保持時區(PST),并且當我獲取Timestamp值時,無論使用CET還是UTC,我仍然會得到Epoch,它已安全地存儲到了數據庫,在CET中打印為01:00。
ew。
TL; DR:
使用jOOQ時 ,如果正確的UTC時間戳對您很重要,請使用TIMESTAMP WITH TIMEZONE,但是您必須實現自己的數據類型Binding ,因為jOOQ當前不支持該數據類型。 一旦使用了自己的數據類型Binding,就可以使用Java 8的time API,它比java.sql.Timestamp +丑陋的Calendar更好地表示了這些不同的類型。
如果當地時間對您很重要,或者您不在跨時區工作,則可以使用TIMESTAMP和jOOQ的Field <Timestamp>。
幸運的是,如果您像我一樣,可以在一個只有一個時區的很小的國家/地區進行操作,而大多數本地軟件都不會遇到此問題。
翻譯自: https://www.javacodegeeks.com/2015/07/whats-even-harder-than-dates-and-timezones-dates-and-timezones-in-sql-jdbc.html
jdbc時區
總結
以上是生活随笔為你收集整理的jdbc时区_什么比日期和时区更难? SQL / JDBC中的日期和时区!的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 人民法院备案(法院备案单)
- 下一篇: 淘宝客静态单页_单页应用程序的Sprin