![](/img/trans.png)
[英]Convert LocalDate to LocalDateTime or java.sql.Timestamp
[英]Strange behaviour when manually converting java.sql.Timestamp to LocalDate
我構建了一個將 TimeStamp 轉換為 LocalDate 的小函數,並偶然發現了奇怪的行為。 這是代碼:
import java.sql.Timestamp;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class Test {
private static void convert(long seconds) {
System.out.printf("At %d seconds%n", seconds);
Timestamp t = new Timestamp(seconds * 1000L);
System.out.format("Timestamp: %s%n", t);
Instant i = t.toInstant();
System.out.format("Instant: %s%n", i);
ZonedDateTime atZone = i.atZone(ZoneId.systemDefault());
System.out.format("at Zone: %s%n", atZone);
LocalDate localDate = atZone.toLocalDate();
System.out.format("LocalDate: %s%n", localDate);
}
}
我當地的時區是歐洲/柏林。 現在,當為 Timestamp 0 調用它時,我得到了正確的結果:
At 0 seconds
Timestamp: 1970-01-01 01:00:00.0
Instant: 1970-01-01T00:00:00Z
at Zone: 1970-01-01T01:00+01:00[Europe/Berlin]
LocalDate: 1970-01-01
一切都如預期的那樣。 但是當我用第 1 年的日期調用它時,它辜負了我的期望:
At -62135769600 seconds
Timestamp: 0001-01-01 01:00:00.0
Instant: 0000-12-30T00:00:00Z
at Zone: 0000-12-30T00:53:28+00:53:28[Europe/Berlin]
LocalDate: 0000-12-30
問題:
我在嘗試從 XMLGregorianCalendar 切換到 java.time.ZonedDateTime 時遇到了這個問題,我們的系統依賴於第 1 年來表示“最小”日期。 一旦您在 Julian-Gregorian 過渡之前開始在日期之間轉換,事情就會變得非常奇怪。 例如
這是 Javadoc 片段,它暗示了早年有些有趣的事情
GregorianCalendar 實現了可預測的格里高利歷和儒略歷。 也就是說,日期是通過在時間上向后和向前無限地外推當前規則來計算的。 因此,GregorianCalendar 可用於所有年份以生成有意義且一致的結果。 但是,使用 GregorianCalendar 獲得的日期僅從公元 4 年 3 月 1 日起才在歷史上准確,當時采用了現代儒略歷規則。 在此日期之前,閏年規則的應用是不規則的,在公元前 45 年之前,儒略歷甚至不存在。
https://docs.oracle.com/javase/8/docs/api/java/util/GregorianCalendar.html
如果你打開 GregorianCalendar 的源代碼,你會發現另一個可愛的“實施說明”,它暗示了更多的瘋狂:
* Likewise, with the Julian calendar, we assume a consistent
* 4-year leap year rule, even though the historical pattern of
* leap years is irregular, being every 3 years from 45 BCE
* through 9 BCE, then every 4 years from 8 CE onwards, with no
* leap years in-between. Thus date computations and functions
* such as isLeapYear() are not intended to be historically
* accurate.
我編寫了一個日期轉換庫,我相信它以“預期”的方式實現了日期類型之間的轉換: https : //github.com/beirtipol/date-converters 。 我希望能夠在 1582 年之前的 java.util 和 java.time 日期之間提供一致的轉換(Julian-> Gregorian shift),但它並不完整。
為了回答您的部分問題,我不確定是否有一種可靠的方法可以在不測試 1582 年之前的每個日期和時區的情況下執行此操作。 我正在嘗試這樣做,如果我弄明白了,我會回帖,但是前面還有很長的測試路!
以下是有關羅馬-朱利安-格里高利輪班的樂趣的更多信息: https : //www.timeanddate.com/calendar/julian-calendar.html
問題似乎是由您的輸入參數引起的轉換函數。 “在 -62135769600 秒”顯示您的輸入值超出了燒焦的長度限制。 下面是代表第一年時間戳的輸入值的測試輸出 (370 * 24 * 60 * 60)。
At 31968000 seconds
Timestamp: 1971-01-06 01:00:00.0
Instant: 1971-01-06T00:00:00Z
at Zone: 1971-01-06T01:00+01:00[Europe/Berlin]
LocalDate: 1971-01-06
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.