Java 日期格式化方法:SimpleDateFormat 和 DateTimeFormatter
·
一、SimpleDateFormat(传统方式)
1. 基本用法
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateFormatExample {
public static void main(String[] args) {
// 创建 SimpleDateFormat 实例
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// 格式化当前日期
String formattedDate = sdf.format(new Date());
System.out.println("当前时间: " + formattedDate); // 2023-12-15 14:30:25
}
}
2. 常用模式字符
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy年MM月dd日"); // 2023年12月15日
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy/MM/dd"); // 2023/12/15
SimpleDateFormat sdf3 = new SimpleDateFormat("dd-MM-yyyy"); // 15-12-2023
SimpleDateFormat sdf4 = new SimpleDateFormat("HH:mm:ss"); // 14:30:25
SimpleDateFormat sdf5 = new SimpleDateFormat("hh:mm:ss a"); // 02:30:25 下午
SimpleDateFormat sdf6 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); // 2023-12-15T14:30:25.123+0800
SimpleDateFormat sdf7 = new SimpleDateFormat("EEEE, MMMM dd, yyyy"); // 星期五, 十二月 15, 2023
3. 完整示例
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
public class SimpleDateFormatDemo {
public static void main(String[] args) {
try {
// 1. 日期转字符串
Date now = new Date();
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
System.out.println("日期: " + sdf1.format(now));
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");
System.out.println("详细时间: " + sdf2.format(now));
SimpleDateFormat sdf3 = new SimpleDateFormat("EEEE", Locale.CHINA);
System.out.println("星期: " + sdf3.format(now));
// 2. 字符串转日期
String dateStr = "2023-12-15 14:30:00";
SimpleDateFormat sdf4 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date parsedDate = sdf4.parse(dateStr);
System.out.println("解析后的日期: " + parsedDate);
// 3. 带时区的格式化
SimpleDateFormat sdf5 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
System.out.println("ISO格式: " + sdf5.format(now));
} catch (ParseException e) {
e.printStackTrace();
}
}
}
4. 线程安全问题及解决方案
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadSafeDateFormat {
// 方案1: 每次创建新的实例(开销大但安全)
public String formatDate1(Date date) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
return sdf.format(date);
}
// 方案2: 使用ThreadLocal(推荐用于多线程)
private static final ThreadLocal<SimpleDateFormat> threadLocalSdf =
ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
public String formatDate2(Date date) {
return threadLocalSdf.get().format(date);
}
// 方案3: 同步代码块
private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
public synchronized String formatDate3(Date date) {
return sdf.format(date);
}
}
二、DateTimeFormatter(Java 8+ 推荐)
1. 基本用法
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class DateTimeFormatterDemo {
public static void main(String[] args) {
// 获取当前时间
LocalDateTime now = LocalDateTime.now();
// 预定义格式器
DateTimeFormatter isoFormatter = DateTimeFormatter.ISO_DATE_TIME;
System.out.println("ISO格式: " + now.format(isoFormatter));
// 自定义格式器
DateTimeFormatter customFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
System.out.println("自定义格式: " + now.format(customFormatter));
DateTimeFormatter chineseFormatter = DateTimeFormatter.ofPattern("yyyy年M月d日 EEEE HH:mm");
System.out.println("中文格式: " + now.format(chineseFormatter));
}
}
2. 完整示例
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.util.Locale;
public class Java8DateFormatExample {
public static void main(String[] args) {
// 1. 各种日期时间类型的格式化
LocalDate date = LocalDate.now();
LocalTime time = LocalTime.now();
LocalDateTime dateTime = LocalDateTime.now();
ZonedDateTime zonedDateTime = ZonedDateTime.now();
// 2. 使用预定义格式
System.out.println("基本ISO日期: " + date.format(DateTimeFormatter.BASIC_ISO_DATE));
System.out.println("ISO日期时间: " + dateTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
System.out.println("ISO时区时间: " + zonedDateTime.format(DateTimeFormatter.ISO_ZONED_DATE_TIME));
// 3. 本地化格式化
DateTimeFormatter shortFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT);
DateTimeFormatter mediumFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM);
DateTimeFormatter longFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG);
DateTimeFormatter fullFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL)
.withLocale(Locale.CHINA);
System.out.println("短格式: " + dateTime.format(shortFormatter));
System.out.println("中格式: " + dateTime.format(mediumFormatter));
System.out.println("长格式: " + dateTime.format(longFormatter));
System.out.println("完整格式: " + dateTime.format(fullFormatter));
// 4. 自定义格式
DateTimeFormatter customFormatter1 = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm");
DateTimeFormatter customFormatter2 = DateTimeFormatter.ofPattern("dd-MMM-yyyy", Locale.US);
DateTimeFormatter customFormatter3 = DateTimeFormatter.ofPattern("'日期:' yyyy年MM月dd日 '时间:' HH时mm分");
System.out.println("斜杠格式: " + dateTime.format(customFormatter1));
System.out.println("英文月份: " + date.format(customFormatter2));
System.out.println("带文字格式: " + dateTime.format(customFormatter3));
// 5. 解析字符串为日期
String dateStr = "2023-12-15 14:30:00";
DateTimeFormatter parser = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime parsedDateTime = LocalDateTime.parse(dateStr, parser);
System.out.println("解析后的时间: " + parsedDateTime);
// 6. 带时区的格式化
DateTimeFormatter zonedFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z")
.withZone(ZoneId.systemDefault());
System.out.println("带时区: " + zonedFormatter.format(zonedDateTime));
}
}
3. 实用工具类
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAccessor;
import java.util.Date;
public class DateUtil {
// 预定义的格式化器(线程安全,可以全局使用)
public static final DateTimeFormatter DATE_FORMATTER =
DateTimeFormatter.ofPattern("yyyy-MM-dd");
public static final DateTimeFormatter TIME_FORMATTER =
DateTimeFormatter.ofPattern("HH:mm:ss");
public static final DateTimeFormatter DATETIME_FORMATTER =
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
public static final DateTimeFormatter TIMESTAMP_FORMATTER =
DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS");
/**
* 格式化 LocalDateTime
*/
public static String format(LocalDateTime dateTime, String pattern) {
return dateTime.format(DateTimeFormatter.ofPattern(pattern));
}
/**
* 格式化 LocalDate
*/
public static String format(LocalDate date, String pattern) {
return date.format(DateTimeFormatter.ofPattern(pattern));
}
/**
* 解析字符串为 LocalDateTime
*/
public static LocalDateTime parseDateTime(String dateStr, String pattern) {
return LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern(pattern));
}
/**
* Date 转 LocalDateTime
*/
public static LocalDateTime toLocalDateTime(Date date) {
return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
}
/**
* LocalDateTime 转 Date
*/
public static Date toDate(LocalDateTime dateTime) {
return Date.from(dateTime.atZone(ZoneId.systemDefault()).toInstant());
}
/**
* 生成时间戳字符串
*/
public static String generateTimestamp() {
return LocalDateTime.now().format(TIMESTAMP_FORMATTER);
}
/**
* 获取中文日期格式
*/
public static String getChineseDate(LocalDate date) {
return date.format(DateTimeFormatter.ofPattern("yyyy年M月d日 E")
.withLocale(Locale.CHINA));
}
/**
* 格式化持续时间(如:01:23:45)
*/
public static String formatDuration(Duration duration) {
long hours = duration.toHours();
long minutes = duration.toMinutesPart();
long seconds = duration.toSecondsPart();
return String.format("%02d:%02d:%02d", hours, minutes, seconds);
}
/**
* 获取日期范围
*/
public static String getDateRange(LocalDate start, LocalDate end, String pattern) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
return start.format(formatter) + " 至 " + end.format(formatter);
}
public static void main(String[] args) {
// 使用示例
LocalDateTime now = LocalDateTime.now();
System.out.println("标准格式: " + format(now, "yyyy-MM-dd HH:mm:ss"));
System.out.println("中文格式: " + getChineseDate(now.toLocalDate()));
System.out.println("时间戳: " + generateTimestamp());
System.out.println("使用预定义格式器: " + now.format(DATETIME_FORMATTER));
// 解析示例
LocalDateTime parsed = parseDateTime("2023-12-15 14:30:00", "yyyy-MM-dd HH:mm:ss");
System.out.println("解析结果: " + parsed);
}
}
三、对比与选择建议
| 特性 | SimpleDateFormat | DateTimeFormatter |
|---|---|---|
| 线程安全 | ❌ 不安全 | ✅ 安全 |
| Java 版本 | 1.1+ | Java 8+ |
| 性能 | 较好 | 优秀 |
| 易用性 | 简单 | 更直观 |
| 功能 | 基础 | 丰富 |
| 推荐度 | 旧项目维护 | 新项目首选 |
四、常见问题解决
1. 时区处理
// SimpleDateFormat 时区设置
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
sdf.setTimeZone(TimeZone.getTimeZone("GMT+8"));
// DateTimeFormatter 时区设置
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
.withZone(ZoneId.of("Asia/Shanghai"));
2. 语言环境(Locale)
// 中文环境
SimpleDateFormat sdfCN = new SimpleDateFormat("yyyy年MM月dd日 EEEE", Locale.CHINA);
// 英文环境
DateTimeFormatter formatterEN = DateTimeFormatter.ofPattern("EEEE, MMMM dd, yyyy", Locale.US);
3. 性能优化建议
// 缓存 DateTimeFormatter 实例
public class FormatterCache {
private static final Map<String, DateTimeFormatter> FORMATTER_CACHE = new ConcurrentHashMap<>();
public static DateTimeFormatter getFormatter(String pattern) {
return FORMATTER_CACHE.computeIfAbsent(pattern, DateTimeFormatter::ofPattern);
}
public static String format(LocalDateTime dateTime, String pattern) {
return dateTime.format(getFormatter(pattern));
}
}
4. 错误处理
public class SafeDateParser {
public static Date safeParse(String dateStr, String pattern) {
try {
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
sdf.setLenient(false); // 严格模式,防止"2023-02-30"被接受
return sdf.parse(dateStr);
} catch (ParseException e) {
// 记录日志,返回默认值或抛出业务异常
return null;
}
}
public static LocalDateTime safeParseDateTime(String dateStr, String pattern) {
try {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
return LocalDateTime.parse(dateStr, formatter);
} catch (DateTimeParseException e) {
// 处理解析失败
return null;
}
}
}
总结建议
- 新项目:优先使用
DateTimeFormatter(Java 8+) - 旧项目维护:继续使用
SimpleDateFormat,注意线程安全 - 多线程环境:使用
ThreadLocal<SimpleDateFormat>或DateTimeFormatter - 复杂日期操作:使用
java.time包(Java 8+)
更多推荐



所有评论(0)