【Java第39集】java SimpleDateFormat类详解

【Java第39集】java SimpleDateFormat类详解

文章目录

一、核心功能1. 格式化(Date → String)2. 解析(String → Date)

二、常用构造方法三、日期格式模式四、格式化与解析操作1. 格式化日期2. 解析日期字符串

五、线程安全性问题1. 问题描述2. 原因3. 解决方案

六、区域设置与时区1. 设置区域2. 设置时区

七、高级功能1. 自定义格式2. 修改格式

八、常见错误与解决方案1. 日期解析失败2. 区域设置问题

九、与 Java 8+ 的 `DateTimeFormatter` 对比1. 线程安全性2. API 设计3. 示例代码

十、总结

SimpleDateFormat 是 Java 中用于格式化和解析日期时间的核心类,属于 java.text 包。它允许开发者将 Date 对象转换为特定格式的字符串(如 2025-05-24 23:55:43),或将字符串解析为 Date 对象。由于其灵活性和易用性,SimpleDateFormat 在早期 Java 项目中广泛使用。但需注意,它不是线程安全的,在多线程环境下需谨慎使用。

一、核心功能

1. 格式化(Date → String)

将 Date 对象转换为符合指定格式的字符串,例如:

Date now = new Date();

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

String formatted = sdf.format(now); // 输出: 2025-05-24 23:55:43

2. 解析(String → Date)

将符合特定格式的字符串解析为 Date 对象,例如:

String dateStr = "2025-05-24 23:55:43";

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

Date date = sdf.parse(dateStr); // 解析成功返回 Date 对象

二、常用构造方法

SimpleDateFormat(String pattern)

按指定模式创建格式化器。示例:SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");

SimpleDateFormat(String pattern, Locale locale)

指定区域设置(如语言、月份名称)。示例:SimpleDateFormat sdf = new SimpleDateFormat("EEEE", Locale.US); // 输出星期几(如 "Saturday")

SimpleDateFormat(String pattern, TimeZone zone)

指定时区(如 TimeZone.getTimeZone("GMT+8"))。示例:SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", TimeZone.getTimeZone("Asia/Shanghai"));

三、日期格式模式

SimpleDateFormat 使用特定的模式符号表示日期时间的各个部分。以下是常用符号及其含义:

符号含义示例说明G时代(Era)AD公元后(AD)或公元前(BC)y年份2025支持 yy(如 25 表示 2025)M月份05、MayMM 表示两位数(如 05)d日期24dd 表示两位数(如 24)H小时(24小时制)23HH 表示两位数(如 23)h小时(12小时制)11hh 表示两位数(如 11)m分钟55mm 表示两位数(如 55)s秒43ss 表示两位数(如 43)S毫秒123SSS 表示三位数(如 123)E星期几Sat支持长格式(如 Saturday)a上午/下午标识PM区分大小写(如 AM/PM)z时区CST支持长格式(如 China Standard Time)

示例模式"yyyy-MM-dd HH:mm:ss" // 2025-05-24 23:55:43

"yyyy年MM月dd日 EEEE" // 2025年05月24日 星期六

"MMM dd, yyyy h:mm a z" // May 24, 2025 11:55 PM CST

四、格式化与解析操作

1. 格式化日期

Date now = new Date();

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss E");

String formatted = sdf.format(now);

System.out.println("当前时间: " + formatted);

// 输出: 当前时间: 2025-05-24 23:55:43 Saturday

2. 解析日期字符串

String dateStr = "2025-05-24 23:55:43";

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

try {

Date date = sdf.parse(dateStr);

System.out.println("解析后的日期: " + date);

} catch (ParseException e) {

e.printStackTrace();

}

// 输出: 解析后的日期: Sat May 24 23:55:43 GMT+08:00 2025

五、线程安全性问题

1. 问题描述

SimpleDateFormat 不是线程安全的。在多线程环境中共享同一个 SimpleDateFormat 实例可能导致以下问题:

数据不一致或解析错误。抛出 ArrayIndexOutOfBoundsException 或 NumberFormatException。

2. 原因

SimpleDateFormat 内部使用可变状态(如 Calendar 对象),多个线程同时访问时可能破坏其内部状态。

3. 解决方案

每次使用时创建新实例(性能较低):

public String formatDate(Date date) {

return new SimpleDateFormat("yyyy-MM-dd").format(date);

}

使用 ThreadLocal 保存每个线程的实例:

private static final ThreadLocal tl = ThreadLocal.withInitial(() ->

new SimpleDateFormat("yyyy-MM-dd"));

public String formatDate(Date date) {

return tl.get().format(date);

}

使用 Java 8+ 的 DateTimeFormatter(推荐):

import java.time.LocalDate;

import java.time.format.DateTimeFormatter;

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

LocalDate date = LocalDate.now();

String formatted = date.format(formatter);

六、区域设置与时区

1. 设置区域

示例:显示星期几的中文名称:

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd EEEE", Locale.CHINESE);

System.out.println(sdf.format(new Date())); // 输出: 2025-05-24 星期六

示例:显示英文月份名称:

SimpleDateFormat sdf = new SimpleDateFormat("MMMM yyyy", Locale.ENGLISH);

System.out.println(sdf.format(new Date())); // 输出: May 2025

2. 设置时区

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");

sdf.setTimeZone(TimeZone.getTimeZone("UTC"));

System.out.println(sdf.format(new Date()));

// 输出: 2025-05-24 15:55:43 UTC

七、高级功能

1. 自定义格式

使用单引号包裹文本:

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd 'at' HH:mm:ss");

System.out.println(sdf.format(new Date())); // 输出: 2025-05-24 at 23:55:43

处理特殊字符:

SimpleDateFormat sdf = new SimpleDateFormat("HH:mm 'and' ss 'seconds'");

System.out.println(sdf.format(new Date())); // 输出: 23:55 and 43 seconds

2. 修改格式

动态修改模式:SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

sdf.applyPattern("dd/MM/yyyy"); // 修改为 dd/MM/yyyy

System.out.println(sdf.format(new Date()));

八、常见错误与解决方案

1. 日期解析失败

原因:输入字符串与模式不匹配。解决方案:检查模式是否与字符串格式完全一致。// 错误示例:模式与字符串格式不匹配

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

sdf.parse("2025/05/24"); // 抛出 ParseException

2. 区域设置问题

原因:未指定区域导致解析失败(如英文格式的月份名称)。解决方案:显式指定区域。SimpleDateFormat sdf = new SimpleDateFormat("MMM dd, yyyy", Locale.ENGLISH);

sdf.parse("May 24, 2025"); // 正确解析

九、与 Java 8+ 的 DateTimeFormatter 对比

1. 线程安全性

SimpleDateFormat:非线程安全。DateTimeFormatter:线程安全(推荐用于新项目)。

2. API 设计

SimpleDateFormat:方法分散,需手动处理异常。DateTimeFormatter:链式调用,支持更丰富的日期时间类型(如 LocalDate、LocalDateTime)。

3. 示例代码

// 使用 DateTimeFormatter 替代 SimpleDateFormat

import java.time.LocalDateTime;

import java.time.format.DateTimeFormatter;

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

LocalDateTime now = LocalDateTime.now();

String formatted = now.format(formatter);

System.out.println("当前时间: " + formatted);

十、总结

SimpleDateFormat 是 Java 中处理日期格式化的经典工具,但其线程安全性和区域设置问题需引起重视。对于新项目,建议优先使用 Java 8 引入的 java.time 包(如 DateTimeFormatter),以获得更安全、直观的 API。对于旧代码维护,可通过 ThreadLocal 或重新设计线程逻辑来规避风险。

🎀 相关推荐

北京这次的风为什么这么大,气象局研究员详解三个原因_北京时间
中国十大好听的低音歌曲 超低音歌曲有哪些 低音经典歌曲盘点
日月盈昃意思
🎯 beat365娱乐网址

日月盈昃意思

📅 08-25 👀 6050