日期時間處理是一個爛攤子
在answer by Teo第一段是非常有見地的和正確的:在Java中的日期時間處理是一個爛攤子。所有其他語言的Ditto &我知道的開發環境。日期時間的工作是困難和棘手的,尤其是容易出錯和令人沮喪的,因爲我們認爲它是直觀的日期時間。但是,當涉及到數據類型,數據庫,序列化,本地化,跨時區調整以及計算機編程隨附的所有其他手續時,「直觀地」不會削減它。
不幸的是,計算機行業基本上選擇了忽略日期時間工作的這個問題。正如統一碼需要很長時間才能被髮明,因爲明顯的需求,業界也一直在解決日期處理問題上下功夫。
不依賴於計數紀元以來
但我必須和它的結論不同意。使用自數計數並不是最好的解決方案。使用count-since-epoch本質上是令人困惑,容易出錯和不兼容的。
我們做數學,而不是使用位創建數字數據類型。我們創建字符串類來處理處理文本的細節,而不是純粹的八位字節。我們也應該創建數據類型和類來處理日期時間值。
早期的Java團隊(和他們之前的IBM & Taligent)嘗試使用java.util.Date和java.util.Calendar及相關類。不幸的是,這種嘗試是不夠的。雖然日期時間本質上是令人困惑的,但這些課程更加混淆了。
喬達時間
據我所知,Joda-Time項目是採取的日期時間徹底,可靠和成功的方式,第一個項目。即便如此,Joda-Time的創造者並不完全滿意。他們繼續在Java 8中創建java.time package,並將其擴展爲threeten-extra project。 Joda-Time和java.time共享相似的概念,但是不同,每個都有一些優點。
數據庫問題
具體來說,java.util.Date & .Calendar類缺乏日期僅值,而時間的日和時區。他們缺乏沒有日期和時區的時間價值。在Java 8之前,Java團隊添加了被稱爲java.sql.Date
和java.sql.Time
類的攻擊,這些類是僞裝成僅限日期的日期時間值。 Joda-Time和java.time均提供LocalDate
和LocalTime
類。
另一個具體問題是java.util.Date的分辨率爲毫秒,但數據庫通常使用微秒或納秒。爲了消除這種差距,Java早期團隊創建了另一個黑客類別java.sql.Timestamp
。雖然技術上是一個java.util.Date子類,但它也可以跟蹤小數秒到納秒分辨率。所以在進入和退出這種類型時,您可能會失去或獲得更精細的秒數粒度,而不會意識到這一事實。所以這可能意味着你期望的平等值不是。
混淆的另一個來源是SQL數據類型TIMESTAMP WITH TIME ZONE
。由於時區信息是而不是存儲,該名稱是一個誤稱。將名稱設想爲TIMESTAMP WITH RESPECT FOR TIME ZONE
,因爲在將日期時間值轉換爲UTC時,會使用任何傳遞的時區偏移信息。
具有納秒級分辨率的java.time包具有一些特定功能,可以更好地與數據庫進行日期時間數據通信。
我可以寫更多,但是這些信息可以從搜索StackOverflow中搜索諸如joda,java.time,sql timestamp和JDBC等單詞。
使用Joda-Time和JDBC的例子Postgres。 Joda-Time使用immutable objects爲thread-safety。因此,我們不是修改一個實例(「mutate」),而是根據原始值創建一個新實例。
String sql = "SELECT now();";
…
java.sql.Timestamp now = myResultSet.getTimestamp(1);
DateTime dateTimeUtc = new DateTime(now , DateTimeZone.UTC);
DateTime dateTimeMontréal = dateTimeUtc.withZone(DateTimeZone.forID("America/Montreal"));
專注於UTC
在此之前,我還以爲在時間戳UTC是按照慣例始終。爲什麼人們會想要一個本地化時間戳而不是本地化表示呢?這不會讓每個人都感到困惑嗎?
確實。 SQL標準定義了一個TIMESTAMP WITHOUT TIME ZONE
,它忽略並刪除任何包含的時區數據。我無法想象這有用。這位Postgres專家David E. Wheeler,says as much in recommending總是使用TIMESTAMP WITH TIME ZONE
。 Wheeler引用了一個狹義的技術例外(分區),甚至在將數據保存到數據庫之前將所有值轉換爲UTC。
最佳做法是在調整到本地化時區以便呈現給用戶時以UTC來處理和存儲數據。您可能有時想記住其本地時區中的原始日期時間數據;如果是這樣,除了轉換爲UTC之外,還要保存該值。
準則
的第一步,以更好的日期時間處理是避免java.util.Date & .Calendar,使用喬達時間和/或java.time,專注於UTC,學習的行爲你特定的JDBC驅動程序和特定的數據庫(儘管SQL標準,數據庫在日期時間處理方面差別很大)。