JAVA8-Date Time API

前言

该文章仅仅记录Java 8 新增日期相关的API文档。

时区概念

Java8中日期和时间类的设计中,把相关API分成了两个包:

  • java.time:该包中的日期和时间类是不具有时区的,比如LocalDate、LocalTime、LocalDateTime等。
  • java.time.zone:该包中的日期和时间类则是带时区的,比如ZonedDateTime、OffsetDateTime等。这样的设计有以下几个重要
    原因:
  1. 方便不同场景使用对于不需要时区信息的场景,使用java.time中的类足够,简单易用。
    对于需要时区功能的场景,使用java.time.zone中的类,可以很好地完成不同时区的转换和处理。
  2. 避免在不需要时区信息的情况下携带时区,影响程序性能如果所有日期时间类都内置时区信息,则在不需要时区的场景下,多余的时区数据也会被加载和携带,浪费资源。
  3. 实现互操作java.time中的无时区类可以很容易地和java.time.zone中的有时区类互操作,相互转换。 这样可以在两种场景间灵活切换。
  4. 实现隔离并减少依赖通过包的划分,java.time和java.time.zone具有了一定的隔离度,互不依赖。 如果没有这个划分,那么利用不到时区信息的类也不得不依赖所有的时区数据库数据,会增加Java SE的大小。
  5. 方便未来拓展如果未来需要扩展新的日期时间相关功能,也可以通过包的划分加以区隔,同时又能够与现有类方便地互操作。 这种设计更具有可扩展性。
    所以,总体来说,Java 8之所以采用有时区和无时区两套 API 的设计,主要还是基于性能、 interchangeability、可扩展性等方面的考量。
    这种设计解耦了不同的需求场景,使得日期时间类组更为灵活和高效。
    同时,两套 API 又可以很好地协作,这为我们在不同的场景下选择恰当的工具提供了可能。
    OK,接下来记录一下Java8中常用的几个日期类。

Clock

详解

可以取代System.currentTimeMillis(),时区敏感,带有时区信息。

用法

1
2
3
4
5
6
Clock clock = Clock.systemDefaultZone();
long millis = clock.millis();

Instant instant = clock.instant();
// 可用历史日期类进行解析,legacy java.util.Date
Date legacyDate = Date.from(instant);

ZoneId

详解

新的时区类 java.time.ZoneId 是原有的 java.util.TimeZone 类的替代品。 ZoneId对象可以通过 ZoneId.of() 方法创建,也可以通过 ZoneId.systemDefault() 获取系统默认时区。

用法

1
2
3
4
// 打印所有有效的时区标识 available timezone ids
System.out.println(ZoneId.getAvailableZoneIds());
// 指定上海时区,ZoneRules[currentStandardOffset=+08:00]
ZoneId shanghaiZoneId = ZoneId.of("Asia/Shanghai");

有了 ZoneId,我们就可以将一个 LocalDate、LocalTime 或 LocalDateTime 对象转化为 ZonedDateTime 对象。

1
2
3
4
// 当前时间
LocalDateTime localDateTime = LocalDateTime.now();
// 把不带有时区时间转变成带有时区的时间
ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, shanghaiZoneId);

ZonedDateTime 对象由两部分构成:LocalDateTime 和 ZoneId,其中 2018-03-03T15:26:56.147 部分为 LocalDateTime,+08:00[Asia/Shanghai] 部分为ZoneId。

LocalTime

详解

LocalTime类是Java 8中日期时间功能里表示一整天中某个时间点的类,它的时间是无时区属性的(早上10点等等)

用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 定义两个时区,东八区、东七区,东八区比东七区早(快)一个点  
ZoneId systemDefault = ZoneId.of("Asia/Shanghai");
ZoneId laosZone = ZoneId.of("Asia/Vientiane");

LocalTime systemLdt = LocalTime.now(systemDefault);
LocalTime laosLdt = LocalTime.now(laosZone);

System.out.println("systemLdt = " + systemLdt);
System.out.println("laosLdt = " + laosLdt);

// true
System.out.println("laosLdt.isBefore(systemLdt) = " + laosLdt.isBefore(systemLdt));
Duration duration = Duration.between(laosLdt, systemLdt);
// 1
System.out.println("duration.toHours() = " + duration.toHours());
// 60
System.out.println("duration.toMinutes() = " + duration.toMinutes());

LocalDate

详解

LocalDate类是Java 8中日期时间功能里表示一个本地日期的类,它的日期是无时区属性的。 可以用来表示生日、节假日期等等。这个类用于表示一个确切的日期,而不是这个日期所在的时间

用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
LocalDate localDate = LocalDate.now();  
// localDate = 2023-05-29
System.out.println("localDate = " + localDate);
// tomorrow = 2023-05-30
LocalDate tomorrow = localDate.plusDays(1);
System.out.println("tomorrow = " + tomorrow);
// yesterday = 2023-05-28
LocalDate yesterday = tomorrow.minus(2, ChronoUnit.DAYS);
System.out.println("yesterday = " + yesterday);

// birthDay = 2023-08-26,星期6
LocalDate birthDay = LocalDate.of(2023, Month.AUGUST, 26);
System.out.println("birthDay = " + birthDay);
DayOfWeek dayOfWeek = birthDay.getDayOfWeek();
System.out.println("dayOfWeek = " + dayOfWeek.getValue());

LocalDateTime

详解

LocalDateTime类是Java 8中日期时间功能里,用于表示当地的日期与时间的类,它的值是无时区属性的。你可以将其视为Java 8中LocalDate与LocalTime两个类的结合。

用法

1
2
3
4
5
6
7
LocalDateTime ldt = LocalDateTime.of(LocalDate.now(), LocalTime.now());  
// 1
System.out.println("ldt.getDayOfWeek().getValue() = " + ldt.getDayOfWeek().getValue());
// 29
System.out.println("ldt.getDayOfMonth() = " + ldt.getDayOfMonth());
// 1
System.out.println("ldt.getLong(ChronoField.DAY_OF_WEEK) = " + ldt.getLong(ChronoField.DAY_OF_WEEK));

ZonedDateTime

详解

ZonedDateTime类是Java 8中日期时间功能里,用于表示带时区的日期与时间信息的类。可以用于表示一个真实事件的开始时间,如某火箭升空时间等等。

用法

1
2
3
4
5
// ZonedDateTime.now() = 2023-05-29T14:38:14.527+08:00[Asia/Shanghai]  
System.out.println("ZonedDateTime.now() = " + ZonedDateTime.now());
ZoneId laosZone = ZoneId.of("Asia/Vientiane");
// ZonedDateTime.of(LocalDateTime.now(), laosZone) = 2023-05-29T14:38:14.528+07:00[Asia/Vientiane]
System.out.println("ZonedDateTime.of(LocalDateTime.now(), laosZone) = " + ZonedDateTime.of(LocalDateTime.now(), laosZone));

Duration

详解

一个Duration对象表示两个Instant间的一段时间

用法

1
2
3
4
Instant first = Instant.now();
// wait some time while something happens
Instant second = Instant.now();
Duration duration = Duration.between(first, second);

DateTimeFormatter

详解

DateTimeFormatter类是Java 8中日期时间功能里,线程安全。用于解析和格式化日期时间的类。

用法

1
2
3
//pattern.format(LocalDateTime.now()) = 2023/05/29 14:46:25  
DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
System.out.println("pattern.format(LocalDateTime.now()) = " + pattern.format(LocalDateTime.now()));

JAVA8-Date Time API
https://github.com/yangxiangnanwill/yangxiangnanwill.github.io/2024/01/03/好好码代码吖/JAVA/JAVA特性/JAVA8-Date Time API/
作者
will
发布于
2024年1月3日
许可协议