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"
2025年6月1日(俄语本地化时)

示例:日期和时间的格式化

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)); // 2025 年 6 月 1 日
    }
}

示例:英文 Locale

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

评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION