理解Java8中的時間API

在Java8之前,在Java開發過程中,如果要操作時間,是使用Date這個類,在Java8中新增了LocalTime、LocalDate和LocalDateTime,日期和時間的處理變得更加方便和容易。用了一段時間,剛開始每次用的時候都要上網查一波才能找到要的答案,後來認真看一下官網的API,發現也不是那麼難理解,現在能夠通過自己的理解找到自己想要的表達式,在這裏做個小小的學習總結。

爲什麼要有新的時間API

既然Date類已經存在了那麼多年,爲什麼要花那麼大的精力去做這個改動?收益是什麼呢?

首先,因爲Date類真的很難用,有很多過於Geek的設計,比如月份是從0開始,0是一月,11是十二月。好吧,我已經知道程序員是從0開始計數了,但是每次用的時候都要做各種轉換,特別是跟其他輸出端有交互的時候,改錯一個地方就凌亂了。在新的APIjava.time裏,這些都用常量表示了,不會用錯,代碼看起來也更加清晰。

在業務代碼中,往往有很多種需求,獲取某一天的0點,獲取下一天的中午時間,將當前時間往前或者往後移動幾天,等等這類的需求,這些功能使用Date類配合Calendar要寫好多代碼,代碼簡潔性也不夠好。

另外一個,Date裏面的很多方法都棄用了,如果新的項目還敢用這些類,那就是給自己埋坑了,還是趁早改了爲好。

舊的時間類java.util.Date和格式化類SimpleDateFormatter都是可變類,不是線程安全的,在多線程環境下對共享變量Date進行操作時,需要自己保證線程安全。而新的時間APILocalTimeLocalDate和格式化類DateTimeFormatter都是final類(不可變)且是線程安全的。

基於上面的這些原因,就沒有理由不使用新的時間API了。

從一個用着習慣了很多年的工具切換到新的工具總是很不習慣,過程是痛苦的,但是結果是美好的。

怎麼理解新的時間API

在新的時間API裏,有LocalTimeLocalDateLocalDateTime三個類,LocalTime只處理時間,無法包含日期,LocalDate只處理日期,無法包含時間,只有LocalDateTime能同時處理日期和時間。

怎麼使用?

如果理解了三個類的區別,那麼在使用上,需要根據具體情況來處理,下面看看比較常遇到的場景。

LocalDate

只取日期,年月日。

獲取今天的日期

LocalDate today = LocalDate.now();// 2020-05-20

使用年月日構造一個日期

// 月份和日期是從1開始
LocalDate valentineDay = LocalDate.of(2020, 5, 20);

指定對象,獲取年、月、日、星期幾

int year = localDate.getYear();
Month month = localDate.getMonth();int day = localDate.getDayOfMonth();
DayOfWeek dayOfWeek = localDate.getDayOfWeek();

或者

int year = localDate.get(ChronoField.YEAR);
int month = localDate.get(ChronoField.MONTH_OF_YEAR);
int day = localDate.get(ChronoField.DAY_OF_MONTH);
int dayOfWeek = localDate.get(ChronoField.DAY_OF_WEEK);

LocalTime

獲取時間,只取幾點幾分幾秒。

初始化時間對象

LocalTime localTime = LocalTime.now();

使用時分秒構造一個對象

LocalTime localTime = LocalTime.of(12, 0, 0);

指定對象,獲取時分秒

LocalTime localTime = LocalTime.now();
int hour = localTime.getHour();
int minute = localTime.getMinute();
int second = localTime.getSecond();
int hour = localTime.get(ChronoField.HOUR_OF_DAY);
int minute = localTime.get(ChronoField.MINUTE_OF_HOUR);
int second = localTime.get(ChronoField.SECOND_OF_MINUTE);

LocalDateTime

獲取日期+時間,年月日+時分秒,含義等於LocalDate+LocalTime

創建時間對象

LocalDateTime localDateTime = LocalDateTime.now();

使用LocalDate結合LocalTime構造時間對象

LocalDateTime localDateTime = LocalDateTime.of(localData, localTime);
LocalDateTime localDateTime = localDate.atTime(localTime);
LocalDateTime localDateTime = localTime.atDate(localDate);

通過LocalDateTime獲取LocalDate和LocalTime

LocalDate localDate = localDateTime.toLocalDate();
LocalTime localDate = localDateTime.toLocalTime();

Instant

這個類是表示時間軸上的某一個時刻的時間點。從1970-01-01 00:00:00這個時間開始計算,主要用於獲取時間戳,與System.currentTimeMillis()(精確到毫秒)類似,但是Instant類可以精確到納秒。

創建Instant對象

Instant instant = Instant.now();

使用時間戳創建Instant對象

Instant instant = Instant.ofEpochSecond(100, 100000);

獲取秒數和毫秒

instant.getEpochSecond();
instant.getEpochMill();

舉例子加深印象

介紹了這幾個類的基本API後,再通過實現某些具體的需求來加深印象。

獲取當前時間戳

// 獲取當前時間對象->設置時->轉換成時間戳
public static long getCurrentSeconds() {
  return Instant.now().atZone(ZoneOffset.of("+8")).toEpochSecond();
}

獲取當天零點/結束時間的時間戳

// 使用日期和時間構造日期時間對象->指定時區轉換成時間戳
public static long getTodayStartTime() {
  return LocalDateTime.of(LocalDate.now(), LocalTime.MIN).toEpochSecond(ZoneOffset.of("+8"));
}
public static long getTodayEndTime() {
  return LocalDateTime.of(LocalDate.now(), LocalTime.MAX).toEpochSecond(ZoneOffset.of("+8"));
}

獲取前一天零點

// 使用日期和時間構造日期時間對象->修改日期->指定時區轉換成時間戳
public static long getYesterdayStartTime() {
  return LocalDateTime.of(LocalDate.now(), LocalTime.MIN).minusDays(1).toEpochSecond(ZoneOffset.of("+8"));
}

根據時間戳獲取時間戳表示的時間當天0點

// 使用時間戳構造日期時間對象->修改日期->指定時區轉換成時間戳
public static long getDayStartTime(long ) {
  return LocalDateTime.of(LocalDate.now(), LocalTime.MIN).minusDays(1).toEpochSecond(ZoneOffset.of("+8"));
}

判斷是否月初第一天

public static boolean isFirstDayOfMonth(String ymd) {
    LocalDate localDate = LocalDate.parse(ymd, DateTimeFormatter.ofPattern("yyyyMMdd"));    return localDate.equals(localDate.withDayOfMonth(1));
}

總結

Java新的時間API很強大,這裏只能舉幾個自己遇到比較多的場景給大家介紹,所講的只是最基礎最皮毛的東西,要熟練的掌握所有的細節,還是需要去看看API或源碼的實現,然後在平時具體的需求場景中慢慢積累。

原創文章,文筆有限,才疏學淺,文中若有不正之處,萬望告知。

如果本文對你有幫助,請點個贊吧,謝謝

更多精彩內容,請關注個人公衆號。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章