簡體   English   中英

使用正確的DST將UTC java.sql.Time轉換為java.time.localtime

[英]Convert UTC java.sql.Time to java.time.localtime with correct DST

我有一個問題,要將從數據庫中獲取的java.sql.Time(UTC)轉換為java.time.LocalTime(GMT + 1 DST)。 它總是缺少夏令時。 因此,將03:00的時間僅轉換為04:00的LocalTime而不是05:00。

//Saved UTC time in DB: 03:00
LocalTime.ofInstant(Instant.ofEpochMilli(sqlTime.getTime()), ZoneId.of("Europe/Berlin"));
=> 04:00 //expected 05:00

我猜問題是java.sql.Time使用默認日期1970-01-01保存時間,並且在1970年德國沒有DST。 但是當然應該顯示今天的時間,而不是1970年的時間。

那么,如何為該示例獲取正確的時間?

假設您至少使用JDBC 4.2,則應該能夠從結果集中檢索LocalTime

    LocalTime timeInUtc = yourResultSet.getObject(yourTimeColumn, LocalTime.class);

這樣就不必為過時且設計不佳的java.sql.Time類所困擾。 當然,您獲得的時間仍將是UTC。 轉換方法如下:

    LocalTime timeInUtc = LocalTime.of(3, 0);

    ZoneId zone = ZoneId.of("Europe/Berlin");
    LocalTime timeInGermany = OffsetDateTime.now(ZoneOffset.UTC)
            .with(timeInUtc)
            .atZoneSameInstant(zone)
            .toLocalTime();

    System.out.println("Zeit heute in Deutschland: " + timeInGermany);

今天運行代碼時,我得到了您期望的輸出:

德國的Zeit heute heute:05:00

編輯:如果沒有辦法可以避免獲取java.sql.Time ,請先將其轉換為LocalTime 假設Time使用UTC,並且我們不想依賴於脆弱的JVM時區設置進行轉換,那么您正確地需要使用getTime方法:

    Time sqlTimeInUtc = // Get from database
    LocalTime timeInUtc 
            = LocalTime.MIDNIGHT.plus(sqlTimeInUtc.getTime(), ChronoUnit.MILLIS);

如果您可以將JVM時區設置也設置為UTC,那么以下內容會更好:

    LocalTime timeInUtc = sqlTimeInUtc.toLocalTime();

在這兩種情況下,其余均如上所述。

在所有情況下,當您說“應該顯示今天的時間”時,您是否想要“今天是UTC”還是“今天是歐洲/柏林時區”,這都是一個棘手的問題。 如果時間在凌晨2點至3點之間,而今天是三月的最后一個星期日,則還有一個極端的情況,在那兒,時鍾從2點變為3點,以啟動德國的夏令時(DST)。 請仔細考慮這些極端情況,並確定您想要什么。

順便說一句,您的診斷是完全正確的: Time.getTime返回1970年1月1日的一天中的時間,因此,當您將其輸入Instant ,您將轉換該日期中的一天中的時間,即沒有夏令時。

據我了解,您的問題是:給定UTC時間,請根據當前時間將其轉換為本地時間。 此時間偏移量取決於DST是否有效。

一種可能的方法是使用TimeZone確定當前偏移量:

    TimeZone tz = TimeZone.getTimeZone("Europe/Berlin");
    int timeZoneOffsetMillis = tz.getOffset(new Date().getTime());

現在, timeZoneOffsetMillis包含您必須添加到UTC時間以獲取本地時間的毫秒數。

您可以這樣獲得LocalTime

    LocalTime localTime = LocalTime.ofNanoOfDay((sqlTime.getTime() + timeZoneOffsetMillis) * 1000000L);

如果您的時間僅精確到秒而不是納秒,那么您可能想要使用LocalTime.ofSecondOfDay

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM