杰瑞科技汇

java datetime格式

  1. 旧版 API (java.util.Datejava.text.SimpleDateFormat):不推荐在新代码中使用,但维护旧项目时必须了解。
  2. 新版 API (java.time 包):自 Java 8 引入,是目前官方推荐、功能强大且线程安全的现代日期时间 API。
  3. 第三方库 (Joda-Time):在 Java 8 之前是事实上的标准,现在仍被广泛使用,但新项目应优先考虑 java.time

下面我们分点详细介绍。


旧版 API (已过时,但需了解)

核心类

  • java.util.Date: 表示一个特定的瞬间,精确到毫秒,它同时包含了日期和时间信息,但很多方法(如 getYear(), getMonth())已被废弃,且设计上存在缺陷。
  • java.text.SimpleDateFormat: 用于 Date 对象的格式化和解析。

格式化示例

SimpleDateFormat 通过模式字母来定义格式。

字母 含义 示例
y yyyy (2025), yy (23)
M MM (08), MMM (Aug), MMMM (August)
d dd (15)
H 小时 (24小时制) HH (14)
h 小时 (12小时制) hh (02)
m 分钟 mm (30)
s ss (05)
S 毫秒 SSS (123)
E 星期几 EEE (Tue), EEEE (Tuesday)
a 上午/下午标记 AMPM

代码示例:

import java.text.SimpleDateFormat;
import java.util.Date;
public class LegacyDateTimeFormat {
    public static void main(String[] args) {
        // 1. 创建一个 Date 对象,代表当前时间
        Date now = new Date();
        // 2. 创建 SimpleDateFormat 实例,定义格式
        // yyyy-MM-dd HH:mm:ss 是最常见的格式
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        // yyyy年MM月dd日 HH时mm分ss秒
        SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");
        // EEE, MMM d, yyyy
        SimpleDateFormat sdf3 = new SimpleDateFormat("EEE, MMM d, yyyy");
        // 3. 格式化 Date 对象为字符串
        String formattedDate1 = sdf1.format(now);
        String formattedDate2 = sdf2.format(now);
        String formattedDate3 = sdf3.format(now);
        System.out.println("标准格式: " + formattedDate1);
        System.out.println("中文格式: " + formattedDate2);
        System.out.println("英文格式: " + formattedDate3);
        // 4. 解析字符串为 Date 对象
        String dateStr = "2025-08-15 14:30:00";
        try {
            Date parsedDate = sdf1.parse(dateStr);
            System.out.println("解析后的 Date 对象: " + parsedDate);
            System.out.println("解析后再次格式化: " + sdf1.format(parsedDate));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

⚠️ 重要缺点:

  • SimpleDateFormat非线程安全的,如果在多线程环境中共享同一个实例,会导致数据错乱,每次使用都 new 一个新实例又会影响性能。
  • Date 类设计混乱,同时包含日期和时间,且时区处理不直观。

新版 API (Java 8+, 强烈推荐)

自 Java 8 起,引入了全新的 java.time 包,彻底解决了旧版 API 的所有问题,它是不可变的,并且是线程安全的。

核心类

  • LocalDate: 表示一个日期(年、月、日),如 2025-08-15
  • LocalTime: 表示一个时间(时、分、秒、纳秒),如 14:30:00
  • LocalDateTime: 表示一个日期和时间,但不包含时区信息,如 2025-08-15T14:30:00
  • ZonedDateTime: 表示一个带时区的日期和时间,如 2025-08-15T14:30:00+08:00[Asia/Shanghai]
  • DateTimeFormatter: 新的格式化工具类,用于替代 SimpleDateFormat

格式化示例

DateTimeFormatter 同样使用模式字母,但更清晰、更强大。

代码示例:

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
public class ModernDateTimeFormat {
    public static void main(String[] args) {
        // 1. 获取当前日期时间
        LocalDateTime now = LocalDateTime.now();
        // 2. 创建 DateTimeFormatter 实例
        // 预定义的格式,如 ISO 标准格式
        DateTimeFormatter isoFormatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
        // 自定义格式
        DateTimeFormatter customFormatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        DateTimeFormatter customFormatter2 = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH时mm分ss秒");
        DateTimeFormatter customFormatter3 = DateTimeFormatter.ofPattern("EEE, MMM d, yyyy HH:mm");
        // 3. 格式化 LocalDateTime 为字符串
        String formattedIso = now.format(isoFormatter);
        String formattedCustom1 = now.format(customFormatter1);
        String formattedCustom2 = now.format(customFormatter2);
        String formattedCustom3 = now.format(customFormatter3);
        System.out.println("ISO 格式: " + formattedIso);
        System.out.println("自定义格式1: " + formattedCustom1);
        System.out.println("自定义格式2: " + formattedCustom2);
        System.out.println("自定义格式3: " + formattedCustom3);
        // 4. 解析字符串为 LocalDateTime
        String dateTimeStr = "2025-08-15 14:30:00";
        try {
            LocalDateTime parsedDateTime = LocalDateTime.parse(dateTimeStr, customFormatter1);
            System.out.println("解析后的 LocalDateTime: " + parsedDateTime);
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 5. 处理带时区的日期时间
        ZonedDateTime shanghaiTime = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));
        DateTimeFormatter zoneFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z");
        System.out.println("上海时间: " + shanghaiTime.format(zoneFormatter));
    }
}

DateTimeFormatter 的优势:

  • 线程安全: DateTimeFormatter 是不可变的,可以安全地在多线程环境中共享。
  • API 设计优秀: LocalDate, LocalTime 等类职责单一,API 更清晰易用。
  • 功能强大: 内置了许多有用的格式(如 ISO_*),并支持轻松地进行日期时间的加减、比较等操作。

第三方库 (Joda-Time)

虽然 Java 8 的 java.time 已经非常优秀,但在 Java 8 之前,Joda-Time 是业界标准,许多现有项目仍在使用它。

核心类

  • org.joda.time.DateTime: 表示一个带时区的日期时间。
  • org.joda.time.format.DateTimeFormat: 用于格式化和解析。
  • org.joda.time.format.DateTimeFormatter: 格式化器。

代码示例:

import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
public class JodaTimeFormat {
    public static void main(String[] args) {
        // 1. 获取当前日期时间
        DateTime now = new DateTime();
        // 2. 创建 DateTimeFormatter 实例
        // forPattern() 是最常用的方式
        DateTimeFormatter formatter1 = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");
        DateTimeFormatter formatter2 = DateTimeFormat.forPattern("yyyy年MM月dd日 HH时mm分ss秒");
        // 3. 格式化
        String formatted1 = now.toString(formatter1);
        String formatted2 = now.toString(formatter2);
        System.out.println("Joda-Time 格式1: " + formatted1);
        System.out.println("Joda-Time 格式2: " + formatted2);
        // 4. 解析
        String dateStr = "2025-08-15 14:30:00";
        DateTime parsedDateTime = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss").parseDateTime(dateStr);
        System.out.println("Joda-Time 解析后: " + parsedDateTime);
    }
}

java.time 的关系: Joda-Time 的设计理念直接影响了 Java 8 的 java.time API,如果你熟悉 Joda-Time,学习 java.time 会非常快,对于新项目,请直接使用 java.time


总结与对比

特性 旧版 API (SimpleDateFormat) 新版 API (DateTimeFormatter) Joda-Time (DateTimeFormat)
推荐度 不推荐 (仅维护旧代码) 强烈推荐 可接受 (旧项目)
线程安全 非线程安全 线程安全 线程安全
核心类 java.util.Date java.time.LocalDate, LocalDateTime org.joda.time.DateTime
API 设计 混乱,职责不清 清晰,职责单一 优秀,与 java.time 类似
时区处理 复杂 简单 (ZonedDateTime) 简单
Java 版本 所有版本 Java 8+ 所有版本 (需引入依赖)

最佳实践

  1. 新项目必须使用 java.time: 除非你被迫使用旧版 Java,否则请优先选择 java.time 包。
  2. 维护旧项目时: 如果遇到 java.util.DateSimpleDateFormat,理解其工作原理和线程安全问题即可,可以考虑使用 java.time 中的转换工具(如 Date.from(localDateTime.toInstant(ZoneOffset.UTC)))逐步进行迁移。
  3. 明确需求: 在格式化时,首先确定你需要的是纯日期、纯时间还是日期时间,以及是否需要包含时区信息,然后选择合适的类(LocalDate, LocalTime, LocalDateTime, ZonedDateTime)。
  4. 复用 DateTimeFormatter: 由于它是线程安全的,可以在应用启动时创建好,然后作为单例或静态常量复用,避免重复创建。
分享:
扫描分享到社交APP
上一篇
下一篇