1. DateTimeFormatter:它是什麼、為什麼需要它
在真實的程式中,日期很少只待在程式碼裡。通常我們需要:
- 轉成字串,用於輸出到主控台、畫面或檔案(例如,"01.06.2025 14:30")。
- 解析字串,也就是把使用者輸入或來自檔案的字串轉回日期/時間物件。
為此,Java 提供了一個強大又好用的工具——類別 java.time.format.DateTimeFormatter。
可以說,DateTimeFormatter 是時間物件(LocalDate、LocalDateTime、ZonedDateTime、Instant 等)與字串之間的翻譯器。它能:
- 將日期/時間物件轉成指定格式的字串(format —— 格式化)。
- 將字串轉成日期/時間物件(parse —— 解析)。
2. 標準格式化器:快速又簡單
Java 體貼地為我們準備了一組標準格式化器,涵蓋最常用的 ISO 格式(日期與時間的國際標準)。
其中一些如下:
| 格式化器 | 字串範例 | 說明 |
|---|---|---|
|
2025-06-01 | 僅日期(年-月-日) |
|
14:30:00 | 僅時間(時:分:秒) |
|
2025-06-01T14:30:00 | 日期與時間(不含時區) |
|
2025-06-01T14:30:00+03:00[Europe/Minsk] | 日期、時間與時區 |
使用標準格式化器的範例
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
public class FormatterDemo {
public static void main(String[] args) {
LocalDate date = LocalDate.now();
// 將日期格式化為字串
String text = date.format(DateTimeFormatter.ISO_LOCAL_DATE);
System.out.println(text); // 例如:2025-06-01
// 將字串再解析回日期
LocalDate parsed = LocalDate.parse("2025-06-01", DateTimeFormatter.ISO_LOCAL_DATE);
System.out.println(parsed); // 2025-06-01
}
}
類比
如果把 Java 比作咖啡店,標準格式化器就像「美式」、「拿鐵」與「義式濃縮」。快速、標準,但有時你會想要一些更特別的東西!
3. 自訂樣板:DateTimeFormatter.ofPattern
有時候標準格式不夠用。比如需要把日期輸出成 "01.06.2025 14:30",而不是 "2025-06-01T14:30:00"。此時可以使用方法 DateTimeFormatter.ofPattern(String pattern) 建立自己的樣板。
樣板語法
樣板中會用到特殊字母:
- y —— 年(yyyy —— 2025)
- M —— 月(MM —— 06)
- d —— 日(dd —— 01)
- H —— 小時(24 小時制,HH —— 14)
- m —— 分(mm —— 30)
- s —— 秒(ss —— 00)
樣板範例
| 樣板 | 輸出範例 |
|---|---|
|
01.06.2025 |
|
2025/06/01 |
|
01.06.2025 14:30 |
|
2025-06-01 14:30:00 |
|
1 iyunya 2025(使用俄文在地化) |
範例:格式化日期與時間
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class CustomFormatDemo {
public static void main(String[] args) {
LocalDateTime dt = LocalDateTime.of(2025, 6, 1, 14, 30);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm");
String text = dt.format(formatter);
System.out.println(text); // 01.06.2025 14:30
}
}
範例:將字串解析為日期
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class ParseDemo {
public static void main(String[] args) {
String input = "01.06.2025 14:30";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm");
LocalDateTime dt = LocalDateTime.parse(input, formatter);
System.out.println(dt); // 2025-06-01T14:30
}
}
注意:樣板必須與字串完全一致!如果字串中有秒數,請在樣板中加入 :ss。
4. 格式化:把日期/時間轉成字串
一般流程
- 建立所需的物件(LocalDate、LocalDateTime、ZonedDateTime 等)。
- 建立或選擇所需的格式化器。
- 在物件上呼叫 format(DateTimeFormatter) 方法,取得字串。
範例:以不同格式輸出日期
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
public class MultiFormatDemo {
public static void main(String[] args) {
LocalDate date = LocalDate.of(2025, 6, 1);
// 標準 ISO
System.out.println(date.format(DateTimeFormatter.ISO_LOCAL_DATE)); // 2025-06-01
// 自訂格式
DateTimeFormatter rusFormat = DateTimeFormatter.ofPattern("dd.MM.yyyy");
System.out.println(date.format(rusFormat)); // 01.06.2025
// 英語風格
DateTimeFormatter usFormat = DateTimeFormatter.ofPattern("MM/dd/yyyy");
System.out.println(date.format(usFormat)); // 06/01/2025
}
}
時間格式化
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
public class TimeFormatDemo {
public static void main(String[] args) {
LocalTime time = LocalTime.of(14, 30, 5);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss");
System.out.println(time.format(formatter)); // 14:30:05
}
}
5. 解析:把字串轉成日期/時間
一般流程
- 取得字串(例如來自使用者)。
- 建立與該字串相同樣板的格式化器。
- 呼叫類別的靜態 parse() 或格式化器物件的 parse() 方法。
範例:解析日期
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
public class ParseDateDemo {
public static void main(String[] args) {
String input = "01.06.2025";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy");
LocalDate date = LocalDate.parse(input, formatter);
System.out.println(date); // 2025-06-01
}
}
範例:解析日期與時間
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class ParseDateTimeDemo {
public static void main(String[] args) {
String input = "01.06.2025 14:30";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm");
LocalDateTime dateTime = LocalDateTime.parse(input, formatter);
System.out.println(dateTime); // 2025-06-01T14:30
}
}
6. 解析錯誤的處理
解析很容易出錯。若字串不符合樣板,Java 會拋出例外 DateTimeParseException。這是常見情況,例如使用者輸入了錯誤的日期。
範例:解析時的錯誤處理
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
public class ParseErrorDemo {
public static void main(String[] args) {
String input = "32.13.2025"; // 無效的日期
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy");
try {
LocalDate date = LocalDate.parse(input, formatter);
System.out.println(date);
} catch (DateTimeParseException ex) {
System.out.println("解析錯誤: " + ex.getMessage());
}
}
}
重要:只要處理使用者輸入,就務必處理此類錯誤!
7. 實作:為使用者轉換日期
假設在教學應用中有這樣一個任務:使用者以 "dd.MM.yyyy" 格式輸入生日,而程式需輸出為 "yyyy/MM/dd",並顯示星期幾。
範例
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.Scanner;
public class BirthdayFormatDemo {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("請輸入生日(dd.MM.yyyy):");
String input = scanner.nextLine();
DateTimeFormatter inputFormat = DateTimeFormatter.ofPattern("dd.MM.yyyy");
DateTimeFormatter outputFormat = DateTimeFormatter.ofPattern("yyyy/MM/dd");
try {
LocalDate birthday = LocalDate.parse(input, inputFormat);
String formatted = birthday.format(outputFormat);
System.out.println("你的日期(新格式): " + formatted);
System.out.println("星期: " + birthday.getDayOfWeek()); // 例如:SATURDAY
} catch (DateTimeParseException ex) {
System.out.println("錯誤:日期格式不正確!");
}
}
}
8. 在地化:語言如何影響格式化
借助 DateTimeFormatter,不僅可以調整數字順序,還能輸出月份名稱、星期幾等,同時會考慮地區設定(語言與地區)。
範例:以俄文輸出月份名稱
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class LocaleDemo {
public static void main(String[] args) {
LocalDate date = LocalDate.of(2025, 6, 1);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d MMMM yyyy", new Locale("ru"));
System.out.println(date.format(formatter)); // 1 iyunya 2025
}
}
範例:英文地區設定
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class LocaleEnDemo {
public static void main(String[] args) {
LocalDate date = LocalDate.of(2025, 6, 1);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d MMMM yyyy", Locale.ENGLISH);
System.out.println(date.format(formatter)); // 1 June 2025
}
}
小技巧:若希望月份與星期幾顯示為指定語言——請務必明確設定 Locale!
9. 日期格式化與解析的常見錯誤
錯誤 1:樣板與字串不一致。
如果字串 "01.06.2025 14:30",而樣板是 "dd.MM.yyyy",解析會失敗。樣板必須與字串完全一致。
錯誤 2:樣板字元混淆。
MM 是月份,mm 是分鐘。若寫成 "dd.mm.yyyy",Java 會把它當作分鐘而報錯。月份請一律使用大寫的 M。
錯誤 3:未處理解析時的例外。
如果不攔截 DateTimeParseException,當使用者輸入錯誤時程式可能會突然終止。務必處理這類錯誤。
錯誤 4:使用文字月份/星期時未指定 Locale。
若樣板中包含以文字表示的月份(MMMM),但沒有指定 Locale,Java 可能會使用預設語言(例如英文)。請務必明確設定所需的 Locale。
錯誤 5:在新專案中使用舊的類別(SimpleDateFormat、Date)。
請記住:在現代程式碼中,請只使用 java.time 與 DateTimeFormatter。
GO TO FULL VERSION