1. 概述

本文将系统性地介绍在 Java 中如何将 String 转换为 Date 对象的多种方法。我们首先从 Java 8 引入的现代日期时间 API —— java.time 包开始,然后回顾传统 java.util.Date 的处理方式。

最后,我们还会探讨一些常用的第三方库,如 Joda-Time 和 Apache Commons Lang 的 DateUtils,它们在某些场景下能显著简化日期处理的复杂度。

✅ 掌握这些技巧,能帮你避免大量“时区踩坑”和格式解析异常。


2. 将字符串转换为 LocalDate 或 LocalDateTime

LocalDateLocalDateTime 是不可变的时间对象,分别表示“日期”和“日期+时间”。它们属于 java.time 包,是 Java 8 之后推荐使用的日期类型。

默认情况下,Java 使用 ISO-8601 标准格式,因此如果字符串符合该标准,可直接使用 parse() 方法解析。

⚠️ 注意:LocalDateLocalDateTime 不包含时区信息。若需处理带时区的时间,请使用 ZonedDateTime

2.1 使用 parse() API

java.time 提供了 parse() 方法,用于将符合 ISO 格式的字符串直接转换为日期对象。

前提是字符串必须符合 ISO_LOCAL_DATE 或 ISO_LOCAL_DATE_TIME 格式,否则会抛出 DateTimeParseException

示例:将字符串转为 LocalDate

LocalDate date = LocalDate.parse("2018-05-05");

示例:将字符串转为 LocalDateTime

LocalDateTime dateTime = LocalDateTime.parse("2018-05-05T11:50:55");

示例:使用自定义格式解析带时区的时间

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z");
ZonedDateTime zonedDateTime = ZonedDateTime.parse("2015-05-05 10:15:30 Europe/Paris", formatter);

2.2 使用自定义 DateTimeFormatter

对于非 ISO 格式的字符串,必须使用 DateTimeFormatter 显式定义解析格式。

DateTimeFormatter 提供了丰富的预定义格式,也支持自定义模式。

示例:使用预定义格式 BASIC_ISO_DATE 解析 19590709

String dateInString = "19590709";
LocalDate date = LocalDate.parse(dateInString, DateTimeFormatter.BASIC_ISO_DATE);

示例:解析英文格式的日期字符串,如 "Mon, 05 May 1980"

String dateInString = "Mon, 05 May 1980";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE, d MMM yyyy", Locale.ENGLISH);
LocalDate dateTime = LocalDate.parse(dateInString, formatter);

2.3 常见日期时间格式符号

以下是一些常用的格式化符号,便于快速构建 DateTimeFormatter

  • y – 年份(1996 或 96)
  • M – 月份(July、Jul 或 07)
  • d – 月份中的天(1-31)
  • E – 星期几(Friday、Sun)
  • a – 上午/下午标记(AM、PM)
  • H – 24 小时制小时(0-23)
  • h – 12 小时制小时(1-12)
  • m – 分钟(0-59)
  • s – 秒(0-60,支持闰秒)

📌 完整符号列表参考官方文档:DateTimeFormatter Patterns

💡 提示:如果需要将 java.time 类型转为 java.util.Date,可参考类型转换文章,此处不再赘述。


3. 将字符串转换为 java.util.Date

在 Java 8 之前,日期处理依赖于 java.util.DateCalendarTimeZone 这些老 API。虽然现在不推荐使用,但在维护旧系统时仍需掌握。

示例:使用 SimpleDateFormat 解析

SimpleDateFormat formatter = new SimpleDateFormat("dd-MMM-yyyy", Locale.ENGLISH);

String dateInString = "7-Jun-2013";
Date date = formatter.parse(dateInString);

⚠️ 注意:

  • 必须先创建 SimpleDateFormat 实例,并指定格式模式。
  • 若字符串格式与模式不匹配,会抛出 ParseException
  • SimpleDateFormat 不是线程安全的,多线程环境下应使用 DateTimeFormatter 或加锁。

3.1 为 java.util.Date 添加时区信息

java.util.Date 本身不保存时区,它只是自 Unix 纪元(1970-01-01T00:00:00Z)以来的毫秒数。

但打印时会使用 JVM 默认时区进行格式化。

示例:指定时区格式化解析

SimpleDateFormat formatter = new SimpleDateFormat("dd-M-yyyy hh:mm:ss a", Locale.ENGLISH);
formatter.setTimeZone(TimeZone.getTimeZone("America/New_York"));

String dateInString = "22-01-2015 10:15:55 AM"; 
Date date = formatter.parse(dateInString);
String formattedDateString = formatter.format(date);

❌ 不推荐做法:修改 JVM 全局时区

TimeZone.setDefault(TimeZone.getTimeZone("GMT"));

这种操作会影响整个应用,极易引发“时区错乱”问题,属于高危操作,应避免。


4. 第三方库支持

除了 JDK 自带 API,一些成熟库也能简化日期解析。

4.1 Joda-Time 库

Joda-Time 曾是 Java 日期处理的事实标准。虽然其作者已建议迁移到 java.time(JSR-310),但在老项目中仍广泛使用。

Maven 依赖:

<dependency>
    <groupId>joda-time</groupId>
    <artifactId>joda-time</artifactId>
    <version>2.12.5</version>
</dependency>

示例:解析标准日期时间

DateTimeFormatter formatter = DateTimeFormat.forPattern("dd/MM/yyyy HH:mm:ss");

String dateInString = "07/06/2013 10:11:59";
DateTime dateTime = DateTime.parse(dateInString, formatter);

示例:设置特定时区

DateTimeFormatter formatter = DateTimeFormat.forPattern("dd/MM/yyyy HH:mm:ss");

String dateInString = "07/06/2013 10:11:59";
DateTime dateTime = DateTime.parse(dateInString, formatter);
DateTime dateTimeWithZone = dateTime.withZone(DateTimeZone.forID("Asia/Kolkata"));

✅ 优点:API 设计优雅,时区处理清晰。
⚠️ 建议:新项目直接用 java.time,老项目可继续使用。

4.2 Apache Commons Lang – DateUtils

DateUtils 是 Apache Commons Lang3 提供的工具类,极大简化了 DateCalendar 的操作。

Maven 依赖:

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.14.0</version>
</dependency>

示例:支持多格式自动匹配解析

String dateInString = "07/06-2013";
Date date = DateUtils.parseDate(dateInString, 
  new String[] { "yyyy-MM-dd HH:mm:ss", "dd/MM-yyyy" });

✅ 亮点:

  • 支持传入多个可能的格式,自动尝试匹配。
  • 避免了手动 try-catch 多个 SimpleDateFormat 的繁琐逻辑。
  • 在处理用户输入或不规范数据时非常实用。

5. 总结

本文覆盖了 Java 中字符串转日期的主要方式:

方式 适用场景 推荐度
LocalDate.parse() ISO 格式字符串 ✅✅✅
DateTimeFormatter 自定义格式 ✅✅✅
SimpleDateFormat 老系统维护 ⚠️(注意线程安全)
Joda-Time 遗留项目 ✅(但建议迁移)
DateUtils.parseDate() 多格式兼容解析 ✅✅

📌 最佳实践建议:

  • 新项目统一使用 java.time API
  • 避免 SimpleDateFormat 在多线程环境直接共享
  • 处理用户输入时优先考虑 DateUtils 的多格式支持

完整示例代码已托管至 GitHub:
https://github.com/baeldung/tutorials/tree/master/core-java-modules/core-java-datetime-string


原始标题:Convert String to Date in Java | Baeldung