前言 该文章仅仅记录Java 8 新增日期相关的API文档。
时区概念 Java8中日期和时间类的设计中,把相关API分成了两个包:
java.time:该包中的日期和时间类是不具有时区的,比如LocalDate、LocalTime、LocalDateTime等。 java.time.zone:该包中的日期和时间类则是带时区的,比如ZonedDateTime、OffsetDateTime等。这样的设计有以下几个重要 原因: 方便不同场景使用对于不需要时区信息的场景,使用java.time中的类足够,简单易用。 对于需要时区功能的场景,使用java.time.zone中的类,可以很好地完成不同时区的转换和处理。 避免在不需要时区信息的情况下携带时区,影响程序性能如果所有日期时间类都内置时区信息,则在不需要时区的场景下,多余的时区数据也会被加载和携带,浪费资源。 实现互操作java.time中的无时区类可以很容易地和java.time.zone中的有时区类互操作,相互转换。 这样可以在两种场景间灵活切换。 实现隔离并减少依赖通过包的划分,java.time和java.time.zone具有了一定的隔离度,互不依赖。 如果没有这个划分,那么利用不到时区信息的类也不得不依赖所有的时区数据库数据,会增加Java SE的大小。 方便未来拓展如果未来需要扩展新的日期时间相关功能,也可以通过包的划分加以区隔,同时又能够与现有类方便地互操作。 这种设计更具有可扩展性。 所以,总体来说,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();Date legacyDate = Date.from(instant);
ZoneId 详解 新的时区类 java.time.ZoneId
是原有的 java.util.TimeZone
类的替代品。 ZoneId对象可以通过 ZoneId.of()
方法创建,也可以通过 ZoneId.systemDefault()
获取系统默认时区。
用法 1 2 3 4 System.out.println(ZoneId.getAvailableZoneIds());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); System.out.println("laosLdt.isBefore(systemLdt) = " + laosLdt.isBefore(systemLdt)); Duration duration = Duration.between(laosLdt, systemLdt); System.out.println("duration.toHours() = " + duration.toHours()); 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(); System.out.println("localDate = " + localDate); LocalDate tomorrow = localDate.plusDays(1 ); System.out.println("tomorrow = " + tomorrow); LocalDate yesterday = tomorrow.minus(2 , ChronoUnit.DAYS); System.out.println("yesterday = " + yesterday); 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()); System.out.println("ldt.getDayOfWeek().getValue() = " + ldt.getDayOfWeek().getValue()); System.out.println("ldt.getDayOfMonth() = " + ldt.getDayOfMonth()); System.out.println("ldt.getLong(ChronoField.DAY_OF_WEEK) = " + ldt.getLong(ChronoField.DAY_OF_WEEK));
ZonedDateTime 详解 ZonedDateTime类是Java 8中日期时间功能里,用于表示带时区的日期与时间信息的类
。可以用于表示一个真实事件的开始时间,如某火箭升空时间等等。
用法 1 2 3 4 5 System.out.println("ZonedDateTime.now() = " + ZonedDateTime.now()); ZoneId laosZone = ZoneId.of("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();Instant second = Instant.now();Duration duration = Duration.between(first, second);
详解 DateTimeFormatter类是Java 8中日期时间功能里,线程安全。用于解析和格式化日期时间的类。
用法 1 2 3 DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss" ); System.out.println("pattern.format(LocalDateTime.now()) = " + pattern.format(LocalDateTime.now()));