1 回答

TA貢獻1884條經驗 獲得超4個贊
您的系統時間不是格林威治標準時間,而是歐洲/倫敦(或類似時間)。三月倫敦時間與格林威治標準時間一致。不是在四月。這就是為什么。
getWorkingHour()返回一個實例Date(另一個設計糟糕且過時的類,但現在讓它成為一個不同的故事)。當您將其附加到空字符串時,會Date.toString被隱式調用并使用您的系統時區構建字符串。在標準時間,它打印GMT為時區縮寫。夏令時 (DST) 于 3 月的最后一個星期日在倫敦開始,在本例中為 3 月 31 日。因此,在 4 月Date.toString,您的 JVM 使用英國夏令時及其縮寫BST來打印時間。
好的解決方案包括兩個變化:
不要依賴 JVM 的默認時區。它可以隨時從您程序的另一部分或在同一 JVM 中運行的另一個程序進行更改,因此太脆弱了。而是為您的日期時間操作提供明確的時區。
跳過舊的日期時間類Calendar,Date而是使用 java.time,現代 Java 日期和時間 API。使用起來更好,并提供更清晰的代碼,尤其是在時區之間的轉換方面。
而不是Calendar使用ZonedDateTime。根據 JDBC 驅動程序的功能,將其轉換為UTCInstant或OffsetDateTimeUTC 以保存到數據庫。
要創建ZonedDateTime,一種選擇是使用其of方法之一(有幾種):
ZonedDateTime initial = ZonedDateTime.of(2019, 3, 10, 9, 0, 0, 0, ZoneId.of("America/Sao_Paulo"));
這將在圣保羅創建日期時間 2019 年 3 月 10 日 09:00。添加 2 小時:
int appointmentDuration = 2;
ZonedDateTime current = initial.plusHours(appointmentDuration);
System.out.println(current);
輸出:
2019-03-10T11:00-03:00[美國/圣保羅]
要Instant為您的數據庫轉換為:
Instant inst = current.toInstant();
System.out.println(inst);
輸出:
2019-03-10T14:00:00Z
瞬間是時區中立的,只是一個時間點,但以 UTC 打印。某些 JDBC 驅動程序在 UTC 時間接受它們。如果你的沒有發生,你需要給它一個OffsetDateTime。像這樣轉換:
OffsetDateTime odt = current.toOffsetDateTime().withOffsetSameInstant(ZoneOffset.UTC);
System.out.println(odt);
輸出:
2019-03-10T14:00Z
請注意,我明確給出了 UTC 而不是依賴于 JVM 默認值。所以這在UTC中是明確的。您注意到日期和時間與從Instant.
添加回答
舉報