一位
new Date()
大法好的老顽固的真香之旅。
new Date()
大法和 new SimpleDateFormat()
等 API 是从我 2018 年学习 Java 开始就一直在使用的处理日期和格式化日期的神器,直到几个月前我还是喜欢用他们,但是突然遇到一个比较复杂并且涉及用户分布在全球的报表需求时,我开始退坑了。。。
我开始使用 java.time
包下的 API,真香 ~~~
在 Java 8 之前,java.util.Date
和 java.util.Calendar
是用于表示日期和时间的类。但是这两个工具类 存在很多问题,例如:
Date
和Calender
是可变的,这意味着它不是线程安全的。java.util.Date
的时间表示只能精确到毫秒,不能精确到更小的时间单位。- API 设计相对复杂且容易出错。
Calender
使用了许多常量和魔法值,不够直观。例如,月份从 0 开始计数,这与我们通常的习惯不同,容易导致错误。Date
存储的时间是从1970-01-01T00:00:00Z
(即格林威治时间)开始经过的时间,但是它的 API 设计存在很多问题,例如getYear()
方法返回的是从 1900 年开始经过的年数,导致其易于出现错误。
为了解决这些问题,Java 8 引入了新的日期时间 API(即 java.time 包
)也就是这篇文章要介绍和推广的,其中的日期时间类是不可变的、线程安全的,并且支持更精确的时间单位。这些类包括:
LocalDate
:表示日期(年月日)。LocalTime
:表示时间(小时分钟秒)。LocalDateTime
:表示日期和时间。ZonedDateTime
:表示带有时区信息的日期和时间。Instant
:表示从 1970-01-01T00:00:00Z(即格林威治时间)开始经过的时间,精确到纳秒。Duration
:表示时间段。Period
:表示日期段。
接下来我就一个一个的介绍这些 API 的使用,觉得有帮助的话可以点个赞哦!
Instant
这个类代表了一个精确的时间点。它的实例可以用于表示一个事件的发生时间,以便于在不同时区之间进行转换。示例代码如下:
Instant instant = Instant.now();
Date
也可以转换成 Instant
,如下:
var instant = new Date().toInstant();
LocalDate
这个类代表了一个日期,不含有具体时间信息。它提供了一系列的静态工厂方法,可以根据年月日的值创建实例。示例代码如下:
LocalDate date = LocalDate.of(2023, 3, 21);
LocalTime
这个类代表了一个时间,不含有具体日期信息。它同样提供了一系列的静态工厂方法,可以根据时分秒的值创建实例。示例代码如下:
LocalTime time = LocalTime.of(12, 30);
LocalDateTime
这个类同时包含了日期和时间信息。可以通过合并 LocalDate
和 LocalTime
的实例来创建 LocalDateTime
实例。示例代码如下:
LocalDateTime dateTime = LocalDateTime.of(2023, 3, 21, 12, 30);
也可以从 Date
转换成 LocalDateTime
var instant = new Date().toInstant();
var localDateTime = instant.atZone(ZoneId.systemDefault()).toLocalDateTime();
ZoneDateTime
ZoneDateTime
在 LocalDateTime
的基础上加上了时区信息。也就是说,它可以使用 LocalDateTime
类中所有的方法和属性。这让我们在处理一些全球性的业务是可以如鱼得水。
在 ZonedDateTime
类中,我们可以通过 ZoneId
类来设置时区。ZoneId
是一个表示时区的类,它包含所有的时区信息,并且提供了多种获取时区的方法。以下是一些常用的 ZoneId
的用法:
// 通过时区ID获取一个时区对象
ZoneId zoneId = ZoneId.of("Asia/Shanghai");
// 获取默认时区对象
ZoneId defaultZoneId = ZoneId.systemDefault();
可以看到,我们可以通过指定时区 ID 来获取对应的时区对象,也可以使用 systemDefault()
方法获取当前默认的时区对象。
然后,我们可以使用 ZonedDateTime
类来表示具有时区信息的日期和时间。下面是一个创建 ZonedDateTime
实例的示例代码:
// 获取当前时间
LocalDateTime localDateTime = LocalDateTime.now();
// 使用指定时区将当前时间转换为带时区的日期时间
ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, zoneId);
Duration 和 Period
这两个类分别代表了时间段和日期段。Duration 可以精确表示秒和纳秒之间的时间差,而 Period 可以精确表示年、月、日之间的时间差。示例代码如下:
Duration duration = Duration.between(LocalTime.now(), LocalTime.of(18, 0));
Period period = Period.between(LocalDate.now(), LocalDate.of(2023, 3, 30));
DateTimeFormatter
这个类提供了一系列的静态方法,可以将日期和时间对象格式化为字符串,也可以将字符串解析为日期和时间对象。再也不用 new SimpleDateFormat()
了。
示例代码如下:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String strDateTime = dateTime.format(formatter);
LocalDateTime parsedDateTime = LocalDateTime.parse(strDateTime, formatter);
方便的 API
java.time
提供的这些工具类,出了明确的职责和优良的设计之外,还提供了非常方便好用的 API,简化我们对于日期的计算。
包括但不限于
var today = LocalDate.now();//今天的信息
var yesterday = today.minusDays(1) //昨天的信息
var tomorrow = today.plusDays(1) //明天的信息
var firstDayOfMoth = today.withDayOfMonth(1); //返回这个月的第一天 1-31
var yesterdayStartTime = yesterday.atStartOfDay() //获取昨天零点的LocalDateTime对象
var dayOfYear = today.getDayOfWeek() //获取今天是这周中的第几天
var dayOfYear = today.getDayOfMonth() //获取今天是这个月中的第几天
var dayOfYear = today.getDayOfYear() //获取今天是一年中的第几天
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于