- 使用
SimpleDateFormat(传统方式,适用于 Java 8 之前) - 使用
java.time.format.DateTimeFormatter(现代方式,推荐,Java 8 及以上)
下面我将详细介绍这两种方法,并提供完整的代码示例。

(图片来源网络,侵删)
使用 SimpleDateFormat (传统方式)
SimpleDateFormat 是一个具体的类,用于以区域设置敏感的方式格式化和解析日期,它允许你定义一个“模式”(pattern)来指定日期和时间的输出格式。
核心步骤:
- 创建
SimpleDateFormat的实例,并传入你想要的日期格式字符串。 - 调用
format()方法,将Date对象作为参数传入,它会返回格式化后的String。
常用格式模式字符:
| 字符 | 含义 | 示例 |
|---|---|---|
y |
年 | yyyy (2025), yy (23) |
M |
月 | MM (01-12), MMM (Jan-Dec), MMMM (January-December) |
d |
月中的天 | dd (01-31) |
H |
小时 (24小时制) | HH (00-23) |
h |
小时 (12小时制) | hh (01-12) |
m |
分钟 | mm (00-59) |
s |
秒 | ss (00-60) |
S |
毫秒 | SSS (000-999) |
代码示例:
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateToStringSimpleDateFormat {
public static void main(String[] args) {
// 1. 获取当前的 Date 对象
Date now = new Date();
// 2. 创建 SimpleDateFormat 实例,定义输出格式
// 格式: 年-月-日 时:分:秒
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String formattedDate1 = sdf1.format(now);
System.out.println("格式化后的日期 (yyyy-MM-dd HH:mm:ss): " + formattedDate1);
// 格式: 年/月/日 时:分:秒
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
String formattedDate2 = sdf2.format(now);
System.out.println("格式化后的日期 (yyyy/MM/dd HH:mm:ss): " + formattedDate2);
// 格式: 月-日-年 时:分 AM/PM
SimpleDateFormat sdf3 = new SimpleDateFormat("MM-dd-yyyy hh:mm a");
String formattedDate3 = sdf3.format(now);
System.out.println("格式化后的日期 (MM-dd-yyyy hh:mm a): " + formattedDate3);
// 格式: 简体中文,星期几
SimpleDateFormat sdf4 = new SimpleDateFormat("yyyy年MM月dd日 EEEE");
String formattedDate4 = sdf4.format(now);
System.out.println("格式化后的日期 (yyyy年MM月dd日 EEEE): " + formattedDate4);
}
}
⚠️ 重要注意事项:线程安全
SimpleDateFormat 是非线程安全的,如果在多线程环境下共享同一个 SimpleDateFormat 实例,可能会导致数据错乱或程序异常。
解决方案:

(图片来源网络,侵删)
- 每次使用都创建新实例(如上例所示):简单但性能较差,因为创建对象有开销。
- 使用
ThreadLocal:为每个线程维护一个独立的实例,这是多线程环境下的最佳实践。 - 使用 Java 8 的新 API:
java.time包下的类是线程安全的,从根本上解决了这个问题。
使用 java.time.format.DateTimeFormatter (现代方式 - 强烈推荐)
从 Java 8 开始,Java 引入了全新的日期和时间 API (java.time),它更强大、更安全、更易于使用。java.time 包下的 Date 类已经被 java.time.LocalDate, java.time.LocalDateTime, java.time.Instant 等类取代。
如果你还在使用旧的 java.util.Date,你需要先将其转换为新的时间类。
核心步骤:
- 将
java.util.Date转换为java.time.Instant。 - 从
Instant转换为你需要的具体时间类(如ZonedDateTime或LocalDateTime)。 - 创建
DateTimeFormatter实例,定义格式。 - 调用
format()方法进行格式化。
代码示例:
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
public class DateToStringJava8 {
public static void main(String[] args) {
// 1. 获取当前的 java.util.Date 对象
Date now = new Date();
// 2. 将 java.util.Date 转换为 java.time.Instant
// Instant 是一个时间线上的瞬时点,不包含时区信息
Instant instant = now.toInstant();
// 3. 将 Instant 转换为带有时区的 ZonedDateTime
// 通常使用系统默认时区或指定时区(如 "Asia/Shanghai")
ZonedDateTime zonedDateTime = instant.atZone(ZoneId.systemDefault());
// 或者指定时区:
// ZonedDateTime zonedDateTime = instant.atZone(ZoneId.of("Asia/Shanghai"));
// 4. 创建 DateTimeFormatter 实例
DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z");
String formattedDate1 = zonedDateTime.format(formatter1);
System.out.println("格式化后的日期 (yyyy-MM-dd HH:mm:ss z): " + formattedDate1);
DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH时mm分ss秒");
String formattedDate2 = zonedDateTime.format(formatter2);
System.out.println("格式化后的日期 (中文格式): " + formattedDate2);
// 如果不需要时区信息,可以转换为 LocalDateTime
// LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
// DateTimeFormatter formatter3 = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm");
// String formattedDate3 = localDateTime.format(formatter3);
// System.out.println("格式化后的日期 (无时区): " + formattedDate3);
}
}
为什么推荐使用 java.time?
- 不可变:所有
java.time类都是不可变的,因此是线程安全的。 - 设计更优秀:API 设计更清晰,类之间的关系更合理(
LocalDate只处理日期,LocalTime只处理时间)。 - 功能更强大:内置了许多方便的方法,如计算日期差、处理不同时区等。
- 官方推荐:是 Java 8 及以上版本处理日期和时间的标准方式。
总结与对比
| 特性 | SimpleDateFormat |
java.time.format.DateTimeFormatter |
|---|---|---|
| 所属包 | java.text |
java.time.format |
| Java 版本 | Java 1.1 及以上 | Java 8 及以上 |
| 线程安全 | 不安全 | 安全 (不可变类) |
| API 设计 | 功能相对单一,易用性一般 | API 清晰,功能强大,易于理解 |
| 推荐度 | 不推荐(除非在旧代码库或 Java 8 以下环境) | 强烈推荐 |
最终建议
- 如果你正在开发新的项目,并且使用的是 Java 8 或更高版本,请务必使用
java.timeAPI。 这是业界标准和最佳实践。 - 如果你需要维护一个旧的 Java 7 或更早版本的项目,那么继续使用
SimpleDateFormat,但要特别注意线程安全问题,最好在每次使用时都创建新实例。

(图片来源网络,侵删)
