1.简介
DateTimeFormatter
和 SimpleDateFormat
都是用于格式化日期和时间的类,但是它们有一些区别。
SimpleDateFormat
是 Java 早期版本中提供的日期格式化类,他是线程不安全的。由于 SimpleDateFormat
是线程不安全的,所以如果在多线程环境中使用会出现异常,通常的解决方法要么是每个线程独立维护一份 SimpleDateFormat
对象实例,要么是将 SimpleDateFormat
放到 ThreadLocal
中。
在Java 8中新增了DateTimeFormatter
类,它比 SimpleDateFormat
更加灵活和安全。DateTimeFormatter
是不变对象,且是线程安全的。所以在使用 DateTimeFormatter
的时候,可以以静态成员变量的方式,在一个类中只维护一份对象实例,用于格式化多个日期和时间值,而无需担心线程安全问题。
2.区别
DateTimeFormatter
和 SimpleDateFormat
都是 Java 中用于日期和时间格式化的类,但它们之间存在以下区别:
-
线程安全性:
DateTimeFormatter
是线程安全的,而SimpleDateFormat
不是。 -
类型支持:
DateTimeFormatter
支持多种日期和时间类型,例如LocalDate
、LocalTime
、LocalDateTime
、ZonedDateTime
、OffsetDateTime
等。而SimpleDateFormat
只支持Date
类型。 -
解析能力:
DateTimeFormatter
可以将字符串解析为日期和时间类型,而SimpleDateFormat
不支持解析操作。 -
本地化:
DateTimeFormatter
支持本地化,可以根据不同的语言和国家的习惯格式化日期和时间。而SimpleDateFormat
也支持本地化,但使用较为麻烦。
例如,要将日期格式化为法国本地化格式,可以使用以下代码:
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM).withLocale(Locale.FRANCE);
LocalDate date = LocalDate.now();
String formattedDate = date.format(formatter);
System.out.println(formattedDate);
- API 设计:
DateTimeFormatter
提供了更加流畅的 API 设计,使用起来更加简便和易读。
总的来说,虽然 SimpleDateFormat
用于简单的日期和时间格式化是很方便的,但是 DateTimeFormatter
在灵活性、线程安全、类型支持、解析能力和本地化方面都更加强大和安全。在 Java 8 及以上的版本中,建议使用 DateTimeFormatter
。
3.SimpleDateFormat
SimpleDateFormat
支持一些常用的格式化选项,例如:
格式化选项 | 描述 |
---|---|
yyyy |
年份,例如 2023 |
MM |
月份,例如 05 |
dd |
日期,例如 04 |
HH |
小时(24小时制),例如 13 |
mm |
分钟,例如 30 |
ss |
秒钟,例如 45 |
S |
毫秒,例如 789 |
E |
星期几,例如 Tue |
Z |
时区,例如 +0800 |
3.1 字符串转日期
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String timeStr = "2023-05-04 21:54:27";
Date date = sdf.parse(timeStr);
System.out.println(date);
输出结果为:
2023-05-04 22:15:21
如上所示,SimpleDateFormat
字符串转日期的方法主要是 parse
这个方法,可以将符合定义的字符串转成 Date
类型。
3.2 日期转字符串
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date now = new Date();
String formattedDate = sdf.format(now);
System.out.println(formattedDate);
输出结果为:
Thu May 04 21:54:27 CST 2023
如上所示,日期转字符串的方法是 format
可以将日期 Date
类型的对象转化成字符串的日期格式来展示。
4.DateTimeFormatter
DateTimeFormatter
除了和 SimpleDateFormat
一样支持一些常用的格式化选项以外,还支持一些额外的格式化选项,例如:
格式化选项 | 描述 |
---|---|
uuuu |
年份,与 yyyy 类似,但是对于 BC 纪元来说是负数 |
G |
纪元,例如 AD 或 BC |
q |
季度,例如 Q1 |
L |
月份,例如 1 或者 |
DateTimeFormatter
可以用于格式化不同的日期和时间类型,例如 LocalDate
、LocalTime
、LocalDateTime
、ZonedDateTime
、OffsetDateTime
等。
4.1 字符串转日期
例如,要将字符串 “2023-05-04 13:30:45” 解析为 LocalDateTime
类型,可以使用以下代码:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String dateString = "2023-05-04 13:30:45";
LocalDateTime dateTime = LocalDateTime.parse(dateString, formatter);
System.out.println(dateTime);
输出的结果的格式为:
2023-05-04T13:30:45
如上所示,使用 parse
方法将字符串转化成 LocalDateTime
类型,这里是直接使用 LocalDateTime
的静态方法 parse
,然后将日期的字符串和format的格式当作入参传入。
4.2 日期转字符串
例如,要将 LocalDate 格式化为 “yyyy-MM-dd” 格式的字符串,可以使用以下代码:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
LocalDate date = LocalDate.now();
String formattedDate = date.format(formatter);
System.out.println(formattedDate);
输出结果为:
2023-05-04
注意:
和 SimpleDateFormat
的使用不同,使用 SimpleDateFormat
的时候是直接用的SimpleDateFormat
的对象sdf
来parse
或者format
。
而使用DateTimeFormatter
并不是直接用DateTimeFormatter
的对象来进行parse
或者format
。则是通过LocalDateTime.parse(dateString, formatter)
来转成日期,通过LocalDate
的对象date.format(formatter)
来转成字符串。
扩展
类似于LocalDate
的日期类,可以通过下面的方式创建一个日期:
LocalDate newDate = LocalDate.of(2022, 1, 1);
LocalDate now = LocalDate.now();
当需要在当前日期上加减的时候,可以采用下面的方法:
Period oneMonth = Period.ofMonths(1);
newDate = newDate.plus(oneMonth);
这样newDate的日期会加上一个月。
LocalDate
类中还有很多实用的静态或者普通方法,可以根据实际使用场景选择使用。