一、介绍

Java 8引入了新的时间日期API,其中DateTimeFormatter是对日期时间格式化的实用类。它提供了一种简便的方法来格式化日期和时间,同时还可以将日期和时间字符串解析为Java对象。

二、特性

DateTimeFormatter具有以下特性:

1. 线程安全:在多线程应用程序中使用DateTimeFormatter时,无需考虑同步问题。

2. 不可变性:DateTimeFormatter对象创建后不可修改,确保了线程安全性。

3. 支持各种日期时间格式:DateTimeFormatter支持多种日期时间格式,同时还支持自定义格式。

4. 扩展性:可以用DateTimeFormatterBuilder类创建自定义格式。

三、原理

DateTimeFormatter类使用基于模式的方法来格式化日期和时间字符串。它使用预定义的格式指令来识别和象征化日期和时间字段。这些指令可以组合在一起,形成各种期望的格式化日期和时间字符串。

四、使用场景

DateTimeFormatter可应用于以下场景:

1. 日期和时间字符串转换为Java对象:使用DateTimeFormatter将字符串解析为日期时间对象。

2. 格式化日期和时间:使用DateTimeFormatter按指定格式将日期和时间格式化为字符串。

3. 多语言支持:根据不同的语言环境,使用不同的DateTimeFormatter格式化日期时间。

五、注意事项

1. 与SimpleDateFormat相比,DateTimeFormatter是线程安全的,可以放心地在多线程环境中使用。

2. 合理使用DateTimeFormatterBuilder类创建自定义格式,以确保应用程序满足用户的要求,并提高用户体验。

六、补充内容

除了基本的日期、时间、时区等格式化选项,DateTimeFormatter还提供了一些额外的功能,如本地化,ISO格式日期时间格式,精度控制等。

七、实际应用

1. 案例一

(1) 场景

以下是在Java中使用DateTimeFormatter进行日期时间格式化

(2) 代码

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
 * DateTimeFormatter使用案例
 *
 * @author wxy
 * @since 2023-05-29
 */
public class DateTimeFormatterCase1 {
    private static final DateTimeFormatter SECOND_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    private static final DateTimeFormatter DAY_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    public static void main(String[] args) {
        // 获取现在日期时间
        LocalDateTime nowDateTime = LocalDateTime.now();
        System.out.println("格式化前(LocalDateTime): " + nowDateTime);
        System.out.println("格式化后(String): " + nowDateTime.format(SECOND_FORMATTER));

        // 解析字符串为日期
        String dateStr = "1990-01-01";
        LocalDate dateTime = LocalDate.parse(dateStr, DAY_FORMATTER);
        System.out.println("转换前(String): " + dateStr);
        System.out.println("转换后(LocalDate): " + dateTime);
    }
}

掌握DateTimeFormatter,让你的时间格式化更简单_时间格式化工具类

2. 案例二

(1) 场景

验证DateTimeFormatter是否线程安全,对比多线程下SimpleDateFormat和DateTimeFormatter区别。

(2) 代码

import java.text.SimpleDateFormat;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * DataTimeFormatterCase2: 对比多线程下SimpleDateFormat和DateTimeFormatter区别
 *
 * @author wxy
 * @since 2023-05-29
 */
public class DataTimeFormatterCase2 {
    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 2; i++) {
            new Thread(() -> {
                for (int j = 0; j < 3; j++) {
                    try {
                        // 休眠100ms
                        TimeUnit.MILLISECONDS.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    try {
                        /// 使用DateTimeFormatter将字符串转换为日期格式
                        //LocalDate dateTime = LocalDate.parse("2022-01-01 10:00:00", DATE_TIME_FORMATTER);
                        /// 使用SimpleDateFormat将字符串转换为日期格式(多线程报错: java.lang.NumberFormatException: multiple points)
                        Date dateTime = DATE_FORMAT.parse("2022-01-01 10:00:00");

                        System.out.println("转换后: " + dateTime);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }

        // 休眠1000ms
        TimeUnit.MILLISECONDS.sleep(1000);
    }
}

输出结果1:多线程下,使用SimpleDateFormat报错(线程不安全)

掌握DateTimeFormatter,让你的时间格式化更简单_java_02

主要是因为SimpleDateFormat在多线程环境下,是线程不安全的,所以如果你在多线程环境中共享了SimpleDateFormat的实例。

输出结果2:多线程下使用DateTimeFormatter,无报错(线程安全)

掌握DateTimeFormatter,让你的时间格式化更简单_java_03