Java日期时间格式化
外观
Java日期时间格式化[编辑 | 编辑源代码]
Java日期时间格式化是将日期或时间对象转换为可读字符串(格式化)或反向解析的过程。Java 8引入的`java.time.format.DateTimeFormatter`类提供了线程安全且灵活的格式化工具,取代了旧版`SimpleDateFormat`。
核心概念[编辑 | 编辑源代码]
格式化与解析[编辑 | 编辑源代码]
- 格式化:将`LocalDate`、`LocalDateTime`等对象 → 字符串(如`"2023-12-25"`)
- 解析:将字符串 → 日期时间对象
预定义格式器[编辑 | 编辑源代码]
Java提供了三种常用格式器:
// 预定义常量示例
DateTimeFormatter.ISO_LOCAL_DATE // 格式:2023-12-31
DateTimeFormatter.ISO_LOCAL_TIME // 格式:23:59:59.999
DateTimeFormatter.ISO_LOCAL_DATE_TIME // 格式:2023-12-31T23:59:59.999
基础用法[编辑 | 编辑源代码]
自定义模式[编辑 | 编辑源代码]
通过模式字符串定义格式:
符号 | 含义 | 示例 |
---|---|---|
y | 年份 | 2023 → "23"或"2023" |
M | 月份 | 7 → "7"或"07" |
d | 日 | 5 → "5"或"05" |
H | 小时(24小时制) | 15 → "15" |
m | 分钟 | 8 → "8"或"08" |
s | 秒 | 45 → "45" |
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime now = LocalDateTime.now();
// 格式化
String formatted = now.format(formatter); // 输出如:"2023-08-15 14:30:45"
// 解析
LocalDateTime parsed = LocalDateTime.parse("2023-08-15 14:30:45", formatter);
本地化格式[编辑 | 编辑源代码]
结合`Locale`实现地区特定显示:
DateTimeFormatter frenchFormatter = DateTimeFormatter
.ofPattern("EEEE, d MMMM yyyy", Locale.FRENCH);
String frenchDate = LocalDate.now().format(frenchFormatter);
// 输出:"mercredi, 15 août 2023"
高级特性[编辑 | 编辑源代码]
格式器构建器[编辑 | 编辑源代码]
使用`DateTimeFormatterBuilder`实现复杂格式:
DateTimeFormatter complexFormatter = new DateTimeFormatterBuilder()
.appendLiteral("订单创建时间:")
.appendValue(ChronoField.YEAR)
.appendLiteral("/")
.appendValue(ChronoField.MONTH_OF_YEAR)
.appendLiteral("/")
.appendValue(ChronoField.DAY_OF_MONTH)
.appendLiteral(" ")
.appendValue(ChronoField.HOUR_OF_DAY)
.appendLiteral("时")
.toFormatter();
// 输出示例:"订单创建时间:2023/8/15 14时"
解析宽松模式[编辑 | 编辑源代码]
处理非严格匹配的输入:
DateTimeFormatter lenientFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd")
.withResolverStyle(ResolverStyle.LENIENT);
LocalDate.parse("2023-02-30", lenientFormatter); // 自动调整为2023-03-02
新旧API对比[编辑 | 编辑源代码]
特性 | 新API | 旧API |
---|---|---|
线程安全 | ✔️ 是 | ❌ 否 |
默认严格解析 | ✔️ 是 | ❌ 否 |
支持纳秒 | ✔️ 是 | ❌ 仅到毫秒 |
旧版代码示例(不推荐新项目使用):
SimpleDateFormat oldFormatter = new SimpleDateFormat("yyyy-MM-dd");
Date oldDate = oldFormatter.parse("2023-08-15"); // 返回java.util.Date
实际应用案例[编辑 | 编辑源代码]
案例1:日志时间戳格式化[编辑 | 编辑源代码]
DateTimeFormatter logFormatter = DateTimeFormatter.ofPattern("[yyyy-MM-dd HH:mm:ss.SSS]");
System.out.println(logFormatter.format(LocalDateTime.now()) + " 用户登录成功");
// 输出示例:[2023-08-15 14:30:45.123] 用户登录成功
案例2:多语言日期显示[编辑 | 编辑源代码]
public String getLocalizedDate(LocalDate date, Locale locale) {
return date.format(DateTimeFormatter
.ofLocalizedDate(FormatStyle.LONG)
.withLocale(locale));
}
// 调用示例:
// getLocalizedDate(LocalDate.now(), Locale.US) → "August 15, 2023"
// getLocalizedDate(LocalDate.now(), Locale.CHINA) → "2023年8月15日"
常见问题[编辑 | 编辑源代码]
问题1:解析失败处理[编辑 | 编辑源代码]
使用`DateTimeParseException`处理错误输入:
try {
LocalDate.parse("2023/08/15", DateTimeFormatter.ISO_LOCAL_DATE);
} catch (DateTimeParseException e) {
System.err.println("日期格式错误,请使用yyyy-MM-dd格式");
}
问题2:时区处理[编辑 | 编辑源代码]
格式化带时区的时间:
ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("America/New_York"));
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z");
// 输出:"2023-08-15 02:30:45 EDT"
最佳实践[编辑 | 编辑源代码]
1. 对于频繁使用的格式器,应声明为`static final`常量 2. 优先使用`ISO-8601`标准格式(如`2023-08-15T14:30:45Z`)进行数据交换 3. 用户界面显示时再转换为本地化格式 4. 时间戳存储推荐使用`Instant`类型
页面模块:Message box/ambox.css没有内容。
旧版`SimpleDateFormat`不是线程安全的!在多线程环境中必须为每个线程创建独立实例。 |
延伸学习[编辑 | 编辑源代码]
- 日期时间算术运算(如`plusDays()`、`minusHours()`)
- 时区转换(`ZoneId`和`ZonedDateTime`)
- 时间段计算(`Period`和`Duration`)