java8新日期时间API的使用

本文深入探讨Java8中全新的日期时间API,包括LocalDate、LocalTime、LocalDateTime及ZonedDateTime等类的使用方法,同时讲解了DateTimeFormatter的格式化与解析功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

跳转页尾1

获取当前时间:

ZonedDateTime now = ZonedDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
System.out.println("当前时间:" + now.format(formatter));
当前时间:2020-07-08 16:32:35

作为开发者,经常需要处理日期时间。如果你跟随者 Java 5 一路走来,那么一定会对 java.util.Datejava.util.Calendarjava.util.GregoiranCalendarjava.text.SimpleDateFormat 四大类非常熟悉,它们分别用于处理日期、日历、日历表示、日期时间格式化

这四个类,对于编程老人来讲,应该是习惯了,但对于编程新人来讲,就有好多疑问,有好多陷阱和坑等着它们跳,比如:

  1. 非线程安全java.util.Date 并不是线程安全的。开发者在使用这个类时必须自己处理多线程并发问题。

  2. 设计不佳:一方面日期和日期格式化分布在多个包中。另一方面,java.util.Date 的默认日期,年竟然是从 1900 开始,月从1 开始,日从 0 开始,没有统一性。而且 Date 类也缺少直接操作日期的相关方法。

  3. 时区处理困难:因为设计不佳,开发人员不得不编写大量代码来处理时区问题。

  4. 还有其它一些问题

面对种种问题,Java 8 终于重新设计了所有日期时间、日历及时区相关的 API。并把它们都统一放置在 java.time 包和子包下。并作出了以下改进:

  1. 新的日期时间 API 是线程安全的。不仅没有 setter 方法,而且任何对实例的变更都会返回一个新的实例而保证原来的实例不变。
  2. 新的日期时间 API 提供了大量的方法,用于修改日期时间的各个部分,并返回一个新的实例。
  3. 在时区方面,新的日期时间 API引入了 域 ( domain ) 这个概念。

本地日期时间 API(一)

Java 8 为处理本地的日期时间提供了三个类 LocalDate 、LocalTime 和 LocalDateTime。分别用于处理 本地日期、本地时间 和 本地日期时间。

比如,可以使用 LocalDateTime.now() 方法返回当前的日期时间。

//import java.time.LocalDateTime;
LocalDateTime currentTime = LocalDateTime.now();
System.out.println("当前时间日期:" + currentTime);

运行结果如下

当前时间日期:2020-07-08T09:53:56.153

比如,我们可以调用 LocalDateTime 对象的 toLocalDate() 方法和 toLocalTime()分别返回当前的日期和当前的时间,也就是 LocalDateLocalTime两个类的实例

LocalDateTime currentTime = LocalDateTime.now();
System.out.println("当前日期时间: " + currentTime);

LocalDate date1 = currentTime.toLocalDate();
System.out.println("当前日期: " + date1);

LocalTime time1 = currentTime.toLocalTime();
System.out.println("当前时间: " + time1);

运行结果如下

当前日期时间: 2020-07-08T10:01:37.870
当前日期: 2020-07-08
当前时间: 10:01:37.870

比如我们可以调用 LocalDateTime 对象的 getMonth() 方法返回当前的月份,调用 getDayOfMonth() 返回当前的日期,调用 getSecond() 返回当前时间的秒数


LocalDateTime currentTime = LocalDateTime.now();
System.out.println("当前日期时间: " + currentTime);

Month month = currentTime.getMonth();
System.out.println("当前月份: " + month);

int day = currentTime.getDayOfMonth();
System.out.println("当前月中的第几天: " + day);

int seconds = currentTime.getSecond();
System.out.println("当前秒数: " + seconds);

运行结果如下

当前日期时间: 2020-07-08T11:06:08.962
当前月份: JULY
当前月中的第几天: 8
当前秒数: 8

比如我们可以调用 LocalDateTime 对象的 withDayOfMonth() 修改日并返回一个新的实例,调用 withYear() 修改年,调用其它 with* 方法修改其它属性。
这些 with方法都是返回新的实例,而原来的实例并不会改变。

LocalDateTime currentTime = LocalDateTime.now();
System.out.println("当前日期时间: " + currentTime);

LocalDateTime date2 = currentTime.withDayOfMonth(10).withYear(2012);
System.out.println("新的日期时间: " + date2);
System.out.println("原来的日期时间: " + currentTime);

运行结果如下

当前日期时间: 2020-07-08T11:09:57.747
新的日期时间: 2012-07-10T11:09:57.747
原来的日期时间: 2020-07-08T11:09:57.747

可以发现原先的实例并没有被修改。


同时,新的日期时间 API 还大量引入了 of() 方法,比如我们可以调用 LocalDate.of() 方法创建一个日期实例,调用 LocalTime.of() 方法创建一个时间实例。

LocalDate date = LocalDate.of(2020, Month.JULY, 8);
System.out.println("日期是: " + date);
// 22:15
LocalTime time = LocalTime.of(22, 15);
System.out.println("时间是: " + time);

运行结果如下

日期是: 2020-07-08
时间是: 22:15

我们还可以调用 LocalDateTime.parse()LocalDate.parse()LocalTime.parse()方法解析字符串格式的日期时间、日期和时间。

LocalDateTime datetime = LocalDateTime.parse("2012-10-10T21:58:00");
System.out.println("日期时间是:" + datetime);

LocalDate date = LocalDate.parse("2012-10-10");
System.out.println("日期是: " + date);

LocalTime time = LocalTime.parse("21:58:01");
System.out.println("时间是: " + time);

运行结果如下

日期时间是:2012-10-10T21:58
日期是: 2012-10-10
时间是: 21:58:01

本地日期时间 API(二)

以上对 Java 8 重新设计的日期时间 API 做了一些基础的介绍,同时详细介绍了和本地时间有关的几个类 LocalDateTime
LocalDateLocalTime
我同时也发现,这三个类没有任何时区相关的信息,但也不能说它们没处理时区,而只能说它们有选择的隐藏了时区的处理。它们内部会使用操作系统当前的时区。
以此同时,Java 在 java.time 包中也提供了几个类用于处理需要关注时区的日期时间 API。它们是 java.time.ZonedDateTimejava.time.ZoneId。前者用于处理需要时区的日期时间,后者用于处理时区。

ZonedDateTimeLocalDateTime 类似,几乎有着相同的 API。从某些方面说,ZonedLocalTime如果不传递时区信息,那么它会默认使用操作系统的时区,这样,结果其实和 LocalDateTime 是类似的。

比如,我们可以使用 ZonedDateTimenow()方法返回当前时区 ( 操作系统时区 ) 的日期时间,调用parse() 方法可以将一个包含了时区信息的字符串格式的日期时间转化为一个 ZonedDateTime 实例。

ZonedDateTime now = ZonedDateTime.now();
System.out.println("当前日期时间是:" + now);

ZonedDateTime datetime = ZonedDateTime.parse("2020-07-08T15:48:37.404+08:00");
System.out.println("日期时间是:" + datetime);

运行结果如下

当前日期时间是:2020-07-08T15:49:18.571+08:00[Asia/Shanghai]
日期时间是:2020-07-08T15:48:37.404+08:00


我们还可以调用ZonedDateTime 对象的 toLocalDate()toLocalTime()
方法将获取该实例的转换为本地的日期和时间

ZonedDateTime now = ZonedDateTime.now();
System.out.println("当前日期时间是:" + now);

LocalDate date = now.toLocalDate();
System.out.println("本地日期是:" + date);

LocalTime time = now.toLocalTime();
System.out.println("本地时间是:" + time);

运行结果如下

当前日期时间是:2020-07-08T15:51:10.643+08:00[Asia/Shanghai]
本地日期是:2020-07-08
本地时间是:15:51:10.643

P.S 这个返回值好诡异,为啥 toLocalDate() 还返回了时间?

处理时区


时区相关的信息,我们可以使用 ZoneId 类来处理。

比如可以调用 ZoneId类的静态方法systemDefault() 返回当前的时区。

ZoneId currentZone = ZoneId.systemDefault();
System.out.println("当前时区是: " + currentZone);

运行结果为

当前时区是: Asia/Shanghai

我们还可以调用 ZonedDateTime 实例的 getZone() 方法获取实例所在的时区

ZonedDateTime now = ZonedDateTime.now();
System.out.println("当前时区是: " + now.getZone());

运行结果如下

当前时区是: Asia/Shanghai

本地日期时间 API(三)

Java 8 似乎也对java.text.SimpleDateFormat 也不太满意,竟然重新创建了一个java.time.format 包,该包下包含了几个类和枚举用于格式化日期时间。

java.time.format 包

java.time.format 包提供了以下几个类用于格式化日期时间

项目说明
DateTimeFormatter用于打印和解析日期时间对象的格式化程序
DateTimeFormatterBuilder创建日期时间格式化样式的构建器
DecimalStyle日期和时间格式中使用的本地化十进制样式

java.time.format包还提供了以下几个枚举,包含了常见的几种日期时间格式。

枚举说明
FormatStyle包含了本地化日期,时间或日期时间格式器的样式的枚举
ResolverStyle包含了解决日期和时间的不同方法的枚举
SignStyle包含了如何处理正/负号的方法的枚举
TextStyle包含了文本格式和解析的样式的枚举
DateTimeFormatter 类

DateTimeFormatter类格式化日期时间的最重要的类,该类是一个最终类,只能实例化,不能被扩展和继承。

DateTimeFormatter类的定义如下

public final class DateTimeFormatter extends Object

DateTimeFormatter类用于打印和解析日期时间对象的格式化器。此类提供打印和解析的主要应用程序入口点,并提供DateTimeFormatter的常见模式

  • 使用预定义的常量,比如 ISO_LOCAL_DATE
  • 使用模式字母,例如uuuu-MMM-dd
  • 使用本地化样式,例如 longmedium
  • 所有的日期时间类,包括本地日期时间和包含时区的日期时间类,都提供了两个重要的方法

1、 一个用于格式化,format(DateTimeFormatter formatter)
2、 另一个用于解析,parse(CharSequence text DateTimeFormatter formatter)


下面,我们写几个示例来演示下这两个方法,并演示下如和使用 DateTimeFormatter 类
ZonedDateTime now = ZonedDateTime.now();
System.out.println("当前时间是: " + now);

System.out.println("另一种表示形式:" + now.format(DateTimeFormatter.RFC_1123_DATE_TIME));

运行结果是

当前时间是: 2020-07-08T16:23:58.164+08:00[Asia/Shanghai]
另一种表示形式:Wed, 8 Jul 2020 16:23:58 +0800

我们还可以调用 DateTimeFormatter.ofPattern() 方法创建自己的日期时间格式,例如

ZonedDateTime now = ZonedDateTime.now();
System.out.println("当前时间是: " + now);

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd H:m:s"); 
System.out.println("另一种表示形式:" + now.format(formatter));

运行结果如下

当前时间是: 2020-07-08T16:29:21.546+08:00[Asia/Shanghai]
另一种表示形式:2020/07/08 16:29:21

当然了,我们可以调用 LocalDateTime 类的静态方法 parse() 将我们刚刚自定义的日期时间格式给解析回来

ZonedDateTime now = ZonedDateTime.now();
System.out.println("当前时间是: " + now);

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String text = now.format(formatter);
System.out.println("另一种表示形式:" + text );

LocalDateTime parsed = LocalDateTime.parse(text, formatter);
System.out.println("解析后:" + parsed );

运行结果如下

当前时间是: 2020-07-08T16:35:49.110+08:00[Asia/Shanghai]
另一种表示形式:2020-07-08 16:35:49
解析后:2020-07-08T16:35:49

  1. 获取当前时间代码查看 ↩︎

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值