日期格式化大全:Java SimpleDateFormat vs DateTimeFormatter

全面介绍日期格式化的方法,对比新旧 API 的区别,提供最佳实践。

时间与日期 2026-06-04 8 分钟

日期格式化大全:Java SimpleDateFormat vs DateTimeFormatter

日期格式化是开发中的常见需求。本文介绍 Java 中日期格式化的方法和最佳实践。

SimpleDateFormat(旧 API)

基本用法

import java.text.SimpleDateFormat;
import java.util.Date;

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String formatted = sdf.format(new Date());
// "2024-01-01 12:00:00"

Date parsed = sdf.parse("2024-01-01 12:00:00");

常用格式

模式 说明 示例
yyyy 2024
MM 01
dd 01
HH 时(24小时) 12
mm 00
ss 00
SSS 毫秒 000
E 星期 周一
a AM/PM 下午

线程安全问题

// ❌ SimpleDateFormat 不是线程安全的
private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

// 多线程并发调用会导致错误
public String formatDate(Date date) {
    return sdf.format(date); // 危险!
}

// ✅ 方案1:每次创建新实例
public String formatDate(Date date) {
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    return sdf.format(date);
}

// ✅ 方案2:使用 ThreadLocal
private static final ThreadLocal<SimpleDateFormat> sdfLocal = 
    ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd"));

// ✅ 方案3:使用 Java 8+ API(推荐)

DateTimeFormatter(新 API)

基本用法

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

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String formatted = LocalDateTime.now().format(formatter);
// "2024-01-01 12:00:00"

LocalDateTime parsed = LocalDateTime.parse("2024-01-01 12:00:00", formatter);

线程安全

// ✅ DateTimeFormatter 是线程安全的
private static final DateTimeFormatter FORMATTER = 
    DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

// 可以安全地在多线程中使用
public String formatDateTime(LocalDateTime dateTime) {
    return dateTime.format(FORMATTER);
}

预定义格式

// ISO 格式
DateTimeFormatter.ISO_LOCAL_DATE;      // 2024-01-01
DateTimeFormatter.ISO_LOCAL_TIME;      // 12:00:00
DateTimeFormatter.ISO_LOCAL_DATE_TIME; // 2024-01-01T12:00:00

// 自定义格式
DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH时mm分ss秒");

新旧 API 对比

特性 SimpleDateFormat DateTimeFormatter
线程安全
不可变
性能
推荐度 ❌ 不推荐 ✅ 推荐

常见格式化场景

1. 中文日期

DateTimeFormatter.ofPattern("yyyy年MM月dd日");
// "2024年01月01日"

DateTimeFormatter.ofPattern("yyyy年MM月dd日 EEEE", Locale.CHINA);
// "2024年01月01日 星期一"

2. 时间戳转日期

Instant instant = Instant.ofEpochSecond(1704067200);
LocalDateTime dateTime = LocalDateTime.ofInstant(instant, ZoneId.of("Asia/Shanghai"));
String formatted = dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

3. 日期计算

LocalDateTime now = LocalDateTime.now();

// 加 7 天
LocalDateTime nextWeek = now.plusDays(7);

// 减 1 小时
LocalDateTime oneHourAgo = now.minusHours(1);

// 获取本月第一天
LocalDateTime firstDay = now.withDayOfMonth(1);

JavaScript 日期格式化

原生 API

const now = new Date();

// toLocaleString
now.toLocaleString('zh-CN', {
  year: 'numeric',
  month: '2-digit',
  day: '2-digit',
  hour: '2-digit',
  minute: '2-digit',
  second: '2-digit'
});
// "2024/01/01 12:00:00"

使用 Day.js(推荐)

import dayjs from 'dayjs';

dayjs().format('YYYY-MM-DD HH:mm:ss');
// "2024-01-01 12:00:00"

dayjs().format('YYYY年MM月DD日');
// "2024年01月01日"

最佳实践

  1. 使用 Java 8+ API:DateTimeFormatter 线程安全
  2. 预定义格式:常用格式定义为常量
  3. 使用 Locale:处理国际化日期
  4. 存储 UTC:数据库存储 UTC 时间
  5. 显示本地化:前端根据用户地区显示

总结

Java 8 引入的 DateTimeFormatter 完全取代了 SimpleDateFormat。新 API 线程安全、不可变、性能更好,推荐所有新项目使用。

📚 相关文章