CodeGym /課程 /JAVA 25 SELF /日期格式化與解析:DateTimeFormatter

日期格式化與解析:DateTimeFormatter

JAVA 25 SELF
等級 13 , 課堂 4
開放

1. DateTimeFormatter:它是什麼、為什麼需要它

在真實的程式中,日期很少只待在程式碼裡。通常我們需要:

  • 轉成字串,用於輸出到主控台、畫面或檔案(例如,"01.06.2025 14:30")。
  • 解析字串,也就是把使用者輸入或來自檔案的字串轉回日期/時間物件。

為此,Java 提供了一個強大又好用的工具——類別 java.time.format.DateTimeFormatter

可以說,DateTimeFormatter 是時間物件(LocalDateLocalDateTimeZonedDateTimeInstant 等)與字串之間的翻譯器。它能:

  • 將日期/時間物件轉成指定格式的字串(format —— 格式化)。
  • 將字串轉成日期/時間物件(parse —— 解析)。

2. 標準格式化器:快速又簡單

Java 體貼地為我們準備了一組標準格式化器,涵蓋最常用的 ISO 格式(日期與時間的國際標準)。

其中一些如下:

格式化器 字串範例 說明
DateTimeFormatter.ISO_LOCAL_DATE
2025-06-01 僅日期(年-月-日)
DateTimeFormatter.ISO_LOCAL_TIME
14:30:00 僅時間(時:分:秒)
DateTimeFormatter.ISO_LOCAL_DATE_TIME
2025-06-01T14:30:00 日期與時間(不含時區)
DateTimeFormatter.ISO_ZONED_DATE_TIME
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

樣板範例

樣板 輸出範例
"dd.MM.yyyy"
01.06.2025
"yyyy/MM/dd"
2025/06/01
"dd.MM.yyyy HH:mm"
01.06.2025 14:30
"yyyy-MM-dd HH:mm:ss"
2025-06-01 14:30:00
"d MMMM yyyy"
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. 格式化:把日期/時間轉成字串

一般流程

  1. 建立所需的物件(LocalDateLocalDateTimeZonedDateTime 等)。
  2. 建立或選擇所需的格式化器。
  3. 在物件上呼叫 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. 解析:把字串轉成日期/時間

一般流程

  1. 取得字串(例如來自使用者)。
  2. 建立與該字串相同樣板的格式化器。
  3. 呼叫類別的靜態 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:在新專案中使用舊的類別(SimpleDateFormatDate)。
請記住:在現代程式碼中,請只使用 java.timeDateTimeFormatter

1
任務
JAVA 25 SELF, 等級 13, 課堂 4
上鎖
報告標準化:當前日期的 ISO 格式 📊
報告標準化:當前日期的 ISO 格式 📊
1
任務
JAVA 25 SELF, 等級 13, 課堂 4
上鎖
解析輸入資料:從字串解析日期 📝
解析輸入資料:從字串解析日期 📝
1
任務
JAVA 25 SELF, 等級 13, 課堂 4
上鎖
個人化:本地化日期顯示 🗓️
個人化:本地化日期顯示 🗓️
1
任務
JAVA 25 SELF, 等級 13, 課堂 4
上鎖
訂單追蹤:精確時間解析 📦
訂單追蹤:精確時間解析 📦
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION