日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

什么比日期和时区更难? SQL / JDBC中的日期和时区!

發(fā)布時(shí)間:2023/12/3 数据库 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 什么比日期和时区更难? SQL / JDBC中的日期和时区! 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

在jOOQ郵件列表上,最近有一個(gè)有趣的討論,關(guān)于jOOQ當(dāng)前缺乏對TIMESTAMP WITH TIME ZONE數(shù)據(jù)類型的現(xiàn)成支持。

沒有人說日期,時(shí)間和時(shí)區(qū)很容易! 這里有一個(gè)有趣的部分,我建議閱讀: 虛假的程序員相信時(shí)間

當(dāng)那還不夠時(shí),還請閱讀: 更多的虛假程序員相信時(shí)間

我個(gè)人喜歡程序員錯(cuò)誤地認(rèn)為“ Unix時(shí)間是自1970年1月1日以來的秒數(shù)”。 …Unix時(shí)間無法代表leap秒;)

返回JDBC

這是Jaybird開發(fā)人員(Firebird JDBC驅(qū)動(dòng)程序) Mark Rotteveel提出的一個(gè)有趣的Stack Overflow答案: java.sql.Timestamp時(shí)區(qū)是否特定?

可以按照以下方式觀察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中使用時(shí)區(qū)而不使用時(shí)區(qū)的所有排列,并且輸出始終相同:

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時(shí)間戳0均已正確存儲并從數(shù)據(jù)庫中檢索到。 我自己的語言環(huán)境是瑞士,即CET / CEST,在Epoch是UTC + 1,這就是在Timestamp.toString()上獲取輸出的地方。

當(dāng)您在SQL和/或Java中使用時(shí)間戳文字時(shí),事情會(huì)變得很有趣。 如果這樣替換綁定變量:

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,而是我首先發(fā)送到服務(wù)器的時(shí)間戳文字。 請注意,綁定/獲取的四種組合仍然始終產(chǎn)生相同的時(shí)間戳。

讓我們看看如果寫入數(shù)據(jù)庫的會(huì)話使用與從數(shù)據(jù)庫中獲取會(huì)話不同的時(shí)區(qū)(假設(shè)您在PST中)(我再次使用CET或UTC),會(huì)發(fā)生什么情況。 我正在運(yùn)行此程序:

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());} }

它產(chǎn)生以下輸出:

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

第一個(gè)時(shí)間戳記是將Epoch存儲為PST(16:00),然后數(shù)據(jù)庫中刪除了時(shí)區(qū)信息,這將Epoch變成了您在Epoch處的本地時(shí)間(-28800秒/ -8h),即真正存儲。

現(xiàn)在,當(dāng)我從自己的時(shí)區(qū)CET獲取該時(shí)間時(shí),我仍然想要獲取當(dāng)?shù)貢r(shí)間(16:00)。 但是在我的時(shí)區(qū)中,這不再是-28800秒,而是-32400秒(-9h)。 夠古怪嗎?

當(dāng)我獲取存儲的本地時(shí)間(16:00)時(shí),事情發(fā)生了相反的變化,但是我強(qiáng)迫獲取發(fā)生在UTC中,這將產(chǎn)生您存儲的時(shí)間戳,最初是PST(-28800)秒)。 但是,在我的時(shí)區(qū)CET中打印此時(shí)間戳(-28800秒)時(shí),現(xiàn)在是17:00。

當(dāng)我們在數(shù)據(jù)庫中使用TIMESTAMP WITH TIME ZONE數(shù)據(jù)類型時(shí),將保持時(shí)區(qū)(PST),并且當(dāng)我獲取Timestamp值時(shí),無論使用CET還是UTC,我仍然會(huì)得到Epoch,它已安全地存儲到了數(shù)據(jù)庫,在CET中打印為01:00。

ew。

TL; DR:

使用jOOQ時(shí) ,如果正確的UTC時(shí)間戳對您很重要,請使用TIMESTAMP WITH TIMEZONE,但是您必須實(shí)現(xiàn)自己的數(shù)據(jù)類型Binding ,因?yàn)閖OOQ當(dāng)前不支持該數(shù)據(jù)類型。 一旦使用了自己的數(shù)據(jù)類型Binding,就可以使用Java 8的time API,它比java.sql.Timestamp +丑陋的Calendar更好地表示了這些不同的類型。

如果當(dāng)?shù)貢r(shí)間對您很重要,或者您不在跨時(shí)區(qū)工作,則可以使用TIMESTAMP和jOOQ的Field <Timestamp>。

幸運(yùn)的是,如果您像我一樣,可以在一個(gè)只有一個(gè)時(shí)區(qū)的很小的國家/地區(qū)進(jìn)行操作,而大多數(shù)本地軟件都不會(huì)遇到此問題。

翻譯自: https://www.javacodegeeks.com/2015/07/whats-even-harder-than-dates-and-timezones-dates-and-timezones-in-sql-jdbc.html

總結(jié)

以上是生活随笔為你收集整理的什么比日期和时区更难? SQL / JDBC中的日期和时区!的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。