Java 8 - 新的日期時間API

你好啊,未來的Java大師!? 今天,我們將踏上一段令人興奮的旅程,探索Java的日期時間API這個神奇領域。別擔心如果你之前從未寫過一行代碼 - 我們將從最基本的開始,一起逐步學習。在本課結束時,你將能像專家一樣輕鬆應對日期和時間!那麼,我們就開始吧!

Java - Datetime Api

Java日期時間API的介紹

想像一下你正在建造一台時間機(很酷吧?)。要讓它運作,你需要精確地處理日期和時間。這正是Java的日期時間API在我們程序中幫助我們做到的。它就像一個超級精準的時鐘和日歷合而為一!

為什麼要有新的API?

在我們深入細節之前,你可能會好奇,“Java為什麼要創造一個新的日期時間API?”讓我給你講一個小故事。

從前(在Java 8之前),開發者必須使用老舊的java.util.Datejava.util.Calendar類。這些就像使用一個舊的、生鏽的時鐘 - 它們能夠工作,但有很多問題。它們難以使用,不是線程安全的(這意味著它們可能在複雜的程序中引起問題),並且不擅長處理時區。

因此,Java團隊決定創造一個全新的、閃亮的API,以解決所有這些問題。於是,java.time包在Java 8中誕生了!

Java本地日期時間API

讓我們從基礎開始。本地日期時間API讓我們在不考慮時區的情況下處理日期和時間。這就像在辦公桌上有一個簡單的時鐘和日歷。

LocalDate

LocalDate代表一個沒有時區的日期。讓我們看看如何使用它:

import java.time.LocalDate;

public class DateExample {
public static void main(String[] args) {
LocalDate today = LocalDate.now();
System.out.println("今天的日期是: " + today);

LocalDate specificDate = LocalDate.of(2023, 6, 15);
System.out.println("一個特定的日期: " + specificDate);
}
}

在這個例子中,我們做了兩件事:

  1. 我們使用LocalDate.now()獲取今天的日期。
  2. 我們使用LocalDate.of()創建一個特定的日期(2023年6月15日)。

當你運行這段代碼時,你將看到今天的日期和我們創建的特定日期被打印出來。

LocalTime

LocalTime代表一個沒有日期或時區的時間。這是我們如何使用它:

import java.time.LocalTime;

public class TimeExample {
public static void main(String[] args) {
LocalTime now = LocalTime.now();
System.out.println("當前時間是: " + now);

LocalTime specificTime = LocalTime.of(14, 30, 45);
System.out.println("一個特定的時間: " + specificTime);
}
}

在這個例子中:

  1. 我們使用LocalTime.now()獲取當前時間。
  2. 我們使用LocalTime.of()創建一個特定的時間(下午2:30:45)。

LocalDateTime

LocalDateTime結合了日期和時間,但仍然沒有時區。這就像一個同時顯示日期和時間的時鐘。這是如何使用它:

import java.time.LocalDateTime;

public class DateTimeExample {
public static void main(String[] args) {
LocalDateTime now = LocalDateTime.now();
System.out.println("當前的日期和時間: " + now);

LocalDateTime specificDateTime = LocalDateTime.of(2023, 6, 15, 14, 30, 45);
System.out.println("一個特定的日期和時間: " + specificDateTime);
}
}

在這個例子中:

  1. 我們使用LocalDateTime.now()獲取當前的日期和時間。
  2. 我們使用LocalDateTime.of()創建一個特定的日期和時間(2023年6月15日下午2:30:45)。

Java時區日期時間API

現在,讓我們為我們的時間機添加一些調味料 - 時區!時區日期時間API讓我們在考慮不同時區的情況下處理日期和時間。

ZonedDateTime

ZonedDateTime代表一個帶有時區的日期時間。這就像一個世界時鐘,為世界不同地區顯示不同的時間。

import java.time.ZonedDateTime;
import java.time.ZoneId;

public class ZonedDateTimeExample {
public static void main(String[] args) {
ZonedDateTime nowInSystemTZ = ZonedDateTime.now();
System.out.println("系統時區的當前日期時間: " + nowInSystemTZ);

ZonedDateTime nowInParis = ZonedDateTime.now(ZoneId.of("Europe/Paris"));
System.out.println("巴黎的當前日期時間: " + nowInParis);
}
}

在這個例子中:

  1. 我們使用ZonedDateTime.now()獲取系統默認時區的當前日期時間。
  2. 我們使用ZonedDateTime.now(ZoneId.of("Europe/Paris"))獲取巴黎的當前日期時間。

Java時間單位枚舉

ChronoUnit枚舉提供了一組標準的日期周期和時間單位。這就像有不同時間測量工具一樣 - 秒、分鐘、小時、天、周、月、年等。

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;

public class ChronoUnitExample {
public static void main(String[] args) {
LocalDateTime now = LocalDateTime.now();
LocalDateTime futureDateTime = now.plus(1, ChronoUnit.WEEKS);

long daysBetween = ChronoUnit.DAYS.between(now, futureDateTime);
System.out.println("從現在到一周之後的天數: " + daysBetween);
}
}

在這個例子中:

  1. 我們將當前日期時間加上一周使用plus(1, ChronoUnit.WEEKS)
  2. 我們計算從現在到一周之後的天數使用ChronoUnit.DAYS.between()

Java Period 和 Duration

PeriodDuration用於表示時間量。將Period看作是日歷上兩個日期之間的差異,將Duration看作是秒表上顯示的時間。

import java.time.LocalDate;
import java.time.Period;
import java.time.Duration;
import java.time.LocalTime;

public class PeriodDurationExample {
public static void main(String[] args) {
LocalDate date1 = LocalDate.of(2023, 1, 1);
LocalDate date2 = LocalDate.of(2023, 12, 31);
Period period = Period.between(date1, date2);
System.out.println("從 " + date1 + " 到 " + date2 + " 的時間段: " + period);

LocalTime time1 = LocalTime.of(9, 0);
LocalTime time2 = LocalTime.of(17, 30);
Duration duration = Duration.between(time1, time2);
System.out.println("從 " + time1 + " 到 " + time2 + " 的持續時間: " + duration);
}
}

在這個例子中:

  1. 我們計算兩個日期之間的時間段使用Period.between()
  2. 我們計算兩個時間之間的持續時間使用Duration.between()

Java時間調整器

時間調整器就像魔杖一樣,讓你可以以有用的方式調整日期,例如找到下個星期一或月份的最後一天。

import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;

public class TemporalAdjustersExample {
public static void main(String[] args) {
LocalDate date = LocalDate.now();
LocalDate nextMonday = date.with(TemporalAdjusters.next(DayOfWeek.MONDAY));
System.out.println("下個星期一: " + nextMonday);

LocalDate lastDayOfMonth = date.with(TemporalAdjusters.lastDayOfMonth());
System.out.println("這個月的最後一天: " + lastDayOfMonth);
}
}

在這個例子中:

  1. 我們使用TemporalAdjusters.next(DayOfWeek.MONDAY)找到下個星期一。
  2. 我們使用TemporalAdjusters.lastDayOfMonth()找到這個月的最後一天。

向後兼容性

現在,你可能會好奇,“那麼所有使用舊日期時間類的舊代碼怎麼辦?”別擔心!Java已經考慮到這一點。新API提供了方法來在舊的和新的日期時間類之間進行轉換。

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;

public class BackwardCompatibilityExample {
public static void main(String[] args) {
// 將舊的Date轉換為新的LocalDateTime
Date oldDate = new Date();
LocalDateTime newDateTime = LocalDateTime.ofInstant(oldDate.toInstant(), ZoneId.systemDefault());
System.out.println("舊的Date: " + oldDate);
System.out.println("新的LocalDateTime: " + newDateTime);

// 將新的LocalDateTime轉換為舊的Date
LocalDateTime localDateTime = LocalDateTime.now();
Date date = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
System.out.println("新的LocalDateTime: " + localDateTime);
System.out.println("舊的Date: " + date);
}
}

在這個例子中:

  1. 我們將一個舊的Date對象轉換為一個新的LocalDateTime對象。
  2. 我們將一個新的LocalDateTime對象轉換回一個舊的Date對象。

這種向後兼容性確保了你可以在享受新日期時間API的優勢的同時,繼續與舊的Java代碼一起工作。

結論

恭喜你!你已經邁出了進入Java日期時間API世界的第一步。我們已經覆蓋了很多內容,從基本的日期和時間處理到更複雜的概念,如時區和時間調整器。

記住,像任何技能一樣,精通Java中的日期和時間需要練習。如果起初感覺過於複雜,別氣餒 - 即使有經驗的開發者有时也需要查閱如何使用這些類!

繼續試驗這些例子,嘗試修改它們,並觀察結果。在你意識到之前,你將會像一個真正的Java時間旅行者一樣操作日期和時間!

快樂編程,願你的時間永遠準確!⏰?

Credits: Image by storyset