天天看點

看山聊Java:Date 與 LocalDate 或 LocalDateTime 互相轉換

看山聊Java:Date 與 LocalDate 或 LocalDateTime 互相轉換

你好,我是看山。

從 Java1 到 Java8 将近 20 年,再加上 Java8 的普及時間、各種曆史 API 相容過渡時間。我們很多時候需要在舊時間 API 與新時間 API 之間切換,并行使用。今天就來說說,java.util.Date與java.time.LocalDate/LocalDateTime如何互相轉換。

java.util.Date轉為java.time.LocalDate

Java8 發行的時候,也考慮到了新舊 API 之間的轉換,是以在java.util.Date中增加了toInstance()方法,可以得到一個Instance執行個體。Instance沒有時區概念,是以我們需要通過atZone()指定時區,得到ZonedDateTime執行個體,然後轉換為java.time.LocalDate。如下:

public LocalDate convertToLocalDateViaInstant(Date dateToConvert) {
    return dateToConvert.toInstant()
            .atZone(ZoneId.systemDefault())
            .toLocalDate();
}
      

同樣的,我們也可以借助Instance的ofEpochMilli()方法建立執行個體。如下:

public LocalDate convertToLocalDateViaMilisecond(Date dateToConvert) {
    return Instant.ofEpochMilli(dateToConvert.getTime())
            .atZone(ZoneId.systemDefault())
            .toLocalDate();
}
      

Java 中,除了java.util.Date,還有一個 Date 對象是java.sql.Date,java8 給這個類增加了一個直接轉換為LocalDate的方法toLocalDate()。是以,我們也可以将java.util.Date轉換為java.sql.Date,然後借助toLocalDate()方法。如下:

public LocalDate convertToLocalDateViaSqlDate(Date dateToConvert) {
    return new java.sql.Date(dateToConvert.getTime()).toLocalDate();
}
      

java.util.Date轉為java.time.LocalDateTime

java.util.Date是包含年月日時分秒的,轉為java.time.LocalDate是把時分秒去掉,轉為java.time.LocalDateTime是精度保留,轉換方式完全一樣,隻不過要用到的是toLocalDateTime()方法。如下:

public LocalDateTime convertToLocalDateTimeViaInstant(Date dateToConvert) {
    return dateToConvert.toInstant()
            .atZone(ZoneId.systemDefault())
            .toLocalDateTime();
}

public LocalDateTime convertToLocalDateTimeViaMilisecond(Date dateToConvert) {
    return Instant.ofEpochMilli(dateToConvert.getTime())
            .atZone(ZoneId.systemDefault())
            .toLocalDateTime();
}
      

java.sql.Date精度隻有年月日,java.sql.Timestamp精度包含時分秒,是以還可以借助這個類的toLocalDateTime()方法實作轉換:

LocalDateTime convertToLocalDateTimeViaSqlTimestamp(Date dateToConvert) {
    return new java.sql.Timestamp(dateToConvert.getTime()).toLocalDateTime();
}
      

接下來,我們看看怎麼從新時間 API 轉舊時間 API。

java.time.LocalDate轉為java.util.Date

先來一個簡單的方法,借助java.sql.Date的valueOf()方法,如下:

public java.util.Date convertToDateViaSqlDate(LocalDate dateToConvert) {
    return java.sql.Date.valueOf(dateToConvert);
}
      

java.sql.Date.valueOf()方法的實作也比較簡單,我們也可以自己實作:

public static Date valueOf(LocalDate date) {
    return new Date(date.getYear() - 1900,
            date.getMonthValue() - 1,
            date.getDayOfMonth());
}
      

題外話:不知為何 Java8 這麼偏愛java.sql.Date,提供了各種好用的轉換方法。但是按照我的習慣,大部分時間用的都是java.util.Date類,是不是這個習慣得改改了。

還有一種方式,是借助java.util.Date的from(Instant instant)方法,如下:

public java.util.Date convertToDateViaInstant(LocalDate dateToConvert) {
    return java.util.Date.from(dateToConvert.atStartOfDay().atZone(ZoneId.systemDefault())
            .toInstant());
}
      

java.time.LocalDateTime轉為java.util.Date

介紹兩種方式。

一種是借助java.sql.Timestamp的valueOf()方法,如下:

public java.util.Date convertToDateViaSqlTimestamp(LocalDateTime dateToConvert) {
    return java.sql.Timestamp.valueOf(dateToConvert);
}
      

另一種方式是:

public java.util.Date convertToDateViaInstant(LocalDateTime dateToConvert) {
    return java.util.Date.from(dateToConvert.atZone(ZoneId.systemDefault())
            .toInstant());
}
      

文末總結

雖然 Java8 已經是行業底線,但是為了向下相容,很多類庫或者遺留代碼依然保留了舊 API,不可能一夜之間替換完畢,是以我們還是會有新舊 API 的轉換。本文提供幾種轉換方式,可供大家使用。當然,條條大路通羅馬,這些方法都不是唯一的方式。

參考

core-java-8-datetime

推薦閱讀

Java8 的時間庫(1):介紹 Java8 中的時間類及常用 API

Java8 的時間庫(2):Date 與 LocalDate 或 LocalDateTime 互相轉換