天天看點

介紹 Java 8 Date/Time API介紹 Java 8 Date/Time API

介紹 Java 8 Date/Time API

1.概述

java8 引入新的日期時間API,為了解決原來

java.util.Date , java.util.Calendar

的一些缺陷。

本文首先介紹原Date,Calendar API的問題,然後來說明java8 Date , Time API是如何解決的。

同時,我們也了解java8中java.time包中一些常用類及其API,如

LocalDate, LocalTime, LocalDateTime, ZonedDateTime, Period, Duration

.

2.原Date/Time APIs問題

  • 線程安全 —— Date和Calendar類不是線程安全的,在調試并發程式時讓人頭痛,開發者必須自己寫額外的代碼處理線程安全。相反,java8中引入新的Date和Time API是不可變且線程安全的,是以開發者無需擔心并發問題。
  • 簡單易懂 —— Date和Calendar類
  • 時區和時間 —— 使用原來的API開發者不得不寫額外邏輯處理時區邏輯,是以新的API可以使用Local、ZoneDate/TimeAPI處理時區問題。

3.使用LocalDate,LocalTime,LocalDateTime類API

最常用的類是

LocalDate, LocalTime, LocalDateTime

,見名思意,它們分别表示目前上下文的本地日期/時間。

這些類主要用在時區無需顯示指定的場景。本節讓介紹其最常用的API.

3.1.使用LocalDate

LocalDate 表示ISO格式日期 (yyyy-MM-dd),沒有時間。

可以用來存儲日期,如生日,付款日期等。目前日期可以用系統時鐘建立:

LocalDate localDate = LocalDate.now();

LocalDate表示特定年,月,日,可以使用of方法或parse方法建立。舉例:

LocalDate.of(2015, 02, 20);

LocalDate.parse("2015-02-20");
           

LocalDate提供多個工具方法可以獲得不同資訊。讓我們快速了解下。

下面代碼片段獲得本地日期,然後加一天:

LocalDate tomorrow = LocalDate.now().plusDays(1);LocalDate tomorrow = LocalDate.now().plusDays(1);
           

下面代碼獲得目前日期,然後減去一個月。注意其枚舉時間機關參數:

LocalDate previousMonthSameDay = LocalDate.now().minus(1, ChronoUnit.MONTHS);
           

下面兩行代碼解析“2016-06-12”,然後擷取星期幾和月中那一天。注意其傳回值,第一個為DayOfWeek,第二個是int。

DayOfWeek sunday = LocalDate.parse("2016-06-12").getDayOfWeek();

int twelve = LocalDate.parse("2016-06-12").getDayOfMonth();
           

也可以輕松測試閏年,示例代碼如下:

boolean leapYear = LocalDate.now().isLeapYear();
           

兩個日期比較,before和after很便捷:

boolean notBefore = LocalDate.parse("2016-06-12").isBefore(LocalDate.parse("2016-06-11"));

boolean isAfter = LocalDate.parse("2016-06-12").isAfter(LocalDate.parse("2016-06-11"));
           

可以從日期中擷取邊界。下面示例分别擷取當天的開始及當月的第一天。

LocalDateTime beginningOfDay = LocalDate.parse("2016-06-12").atStartOfDay();
LocalDate firstDayOfMonth = LocalDate.parse("2016-06-12").with(TemporalAdjusters.firstDayOfMonth());
           

下面我們看看LocalTime類。

3.2 使用LocalTime

LocalTime表示時間,沒有日期。與LocalDate類似,LocalTime能通過of和parse方法從系統時鐘建立。

下面通過示例了解下常用API.

LocalTime now = LocalTime.now();
           

下面代碼示例,我們通過解析字元串建立LocalTime表示06:30AM。

LocalTime sixThirty = LocalTime.parse("06:30");
           

也可以使用工廠方法建立LocalTime。示例如下:

LocalTime sixThirty = LocalTime.of(6, 30);
           

通過plus方法增加一小時。servenThirth為07:30AM.

LocalTime sevenThirty = LocalTime.parse("06:30").plus(1, ChronoUnit.HOURS);
           

提供便捷的方法擷取時間單元。

int six = LocalTime.parse("06:30").getHour();
           

比較日期,是否晚于或早于特定時間。示例代碼:

boolean isbefore = LocalTime.parse("06:30").isBefore(LocalTime.parse("07:30"));
           

LocalTime類中通過常量可以獲得max,min,noon時間。在執行資料庫時間範圍查詢時非常有用。下面代碼表示23:59:59.99.

LocalTime maxTime = LocalTime.MAX
           

下面看看LocalDateTime類。

3.3使用LocalDateTime

LocalDateTime表示日期和時間組合。這時最常用的類,提供了豐富的API.

通過從系統時鐘建立:

LocalDateTime.now();
           

通過工廠方法of或parse建立:

LocalDateTime.of(2015, Month.FEBRUARY, 20, 06, 30);

LocalDateTime.parse("2015-02-20T06:30:00");
           

提供了工具API實作增加或減少單元日期或時間。如年,月,日,分鐘等。

localDateTime.plusDays(1);

localDateTime.minusHours(2);
           

通過get方法擷取時間單元。

localDateTime.getMonth();
           

4.使用ZonedDateTime

java8提供了ZonedDateTime類,用于處理帶時區的日期和時間。ZoneId表示不同的時區。大約有40不同的時區。

下面代碼建立一個時區:

ZoneId zoneId = ZoneId.of("Europe/Paris");
           

擷取所有時區集合:

Set allZoneIds = ZoneId.getAvailableZoneIds();

把LocalDateTime轉換成特定的時區:

ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, zoneId);
           

ZonedDateTime提供parse方法獲得特定時區的dateTime:

ZonedDateTime.parse("2015-05-03T10:15:30+01:00[Europe/Paris]");
           

另外和時區一起使用的類是OffsetDateTime類,OffsetDateTime是不變的,表示date-time偏移,存儲所有日期和時間字段,精确至納秒,從UTC/Greenwich計算偏移。

可以通過

OffSetDateTime

執行個體結合

ZoneOffset

建立LocalDateTime。

LocalDateTime localDateTime = LocalDateTime.of(2015, Month.FEBRUARY, 20, 06, 30);

我們建立ZoneOffset,增加兩個小時:

ZoneOffset offset = ZoneOffset.of("+02:00");

OffsetDateTime offSetByTwo = OffsetDateTime.of(localDateTime, offset);
           

先localDateTime的值為 2015-02-20 06:30 +02:00.

下面我們看如何通過Period和Duration類修改日期和時間值。

5.使用Period 和 Duration

Period類代表年,月,日的時間量,Duration類代表秒和納秒的數量。

5.1使用Period

Period類主要用來修改給定日期值,或擷取兩日期之間的內插補點:

LocalDate initialDate = LocalDate.parse("2007-05-10");
           

通過Period可以操作日期:

LocalDate finalDate = initialDate.plus(Period.ofDays(5));
           

Period類有不同的get方法,如getYears,getMonths,getDays可以獲得不同周期值。下面代碼傳回5,反應日期間隔:

int five = Period.between(finalDate, initialDate).getDays();
           

也可以通過ChronoUnit實作通用功能:

int five = ChronoUnit.DAYS.between(initialDate , initialDate);
           

使用Duration

與Period類似, Duration類用于處理時間, 下面代碼建立LocalTime然後增加30秒。

LocalTime initialTime = LocalTime.of(6, 30, 0);

LocalTime finalTime = initialTime.plus(Duration.ofSeconds(30));
           

兩個時間之間間隔通過Duration類獲得時間單元。

int thirty = Duration.between(finalTime, initialTime).getSeconds();

通用可以通過ChronoUnit 類獲得。

int thirty = ChronoUnit.SECONDS.between(finalTime, initialTime);

相容原Date and Calendar

java8已經提供了toInstant方法,可以轉換Date和Calendar執行個體至新的DateTime。

下面是原Date類中新增的方法:

public static Date from(Instant instant) {
    try {
        return new Date(instant.toEpochMilli());
    } catch (ArithmeticException ex) {
        throw new IllegalArgumentException(ex);
    }
}

public Instant toInstant() {
    return Instant.ofEpochMilli(getTime());
}
           

示例轉換:

LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());

LocalDateTime.ofInstant(calendar.toInstant(), ZoneId.systemDefault());

也可以通過Epoch時間建構LocalDateTime,Epoch指的是一個特定的時間:1970-01-01 00:00:00 UTC。

結果為2016-06-13T11:34:50:

LocalDateTime.ofEpochSecond(1465817690, 0, ZoneOffset.UTC);

7.Date and Time 格式化

java8提供了非常簡單的方式格式化日期和時間:

LocalDateTime localDateTime = LocalDateTime.of(2015, Month.JANUARY, 25, 6, 30);
           

下面代碼傳入一個ISO日期格式去格式化一個本地時間,結果為2015-01-25:

LocalDate localDate = localDateTime.format(DateTimeFormatter.ISO_DATE);
           

DateTimeFormatter 類提供了多個标準格式選項。也支援自定義的格式。下面示例代碼結果為2015/01/25:

localDateTime.format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));
           

也可以通過格式樣式格式化,如SHORT, LONG or MEDIUM 。下面代碼輸出為25-Jan-2015 06:30:00:

localDateTime
  .format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)
  .withLocale(Locale.UK);
           

總結

java8提供了豐富的API操作日期時間,相比較原來的API,使用更容易更便捷。如果使用jdk較低版本,可以使用joda庫實作,本來java8API就是由joda提供。joda可以通過maven引入:

<dependency>
    <groupId>joda-time</groupId>
    <artifactId>joda-time</artifactId>
    <version>2.9.4</version>
</dependency>