Java 8 日期时间API快速扫盲

  在Java8发布之前,Javaer平时使用java.util.Date类和java.util.Calendar类来表示和计算时间。两个类分别发布于在1.0和1.1版本。

  由于过去API的设计不足,Java 8发布了一套全新的时间API。


表示日期和时间

Instant

  Instant类表示时刻,不直接对应年月日信息,需要通过转换。

获得当前时刻:

Instant now = Instant.now();

同时也可以通过Epoch Time(Unix认为UTC1970.01.01 00:00:00是纪元时间)创建Instant。

Instant now = Instant.ofEpochMilli(System.currentTimeMillis());
Date 转换成 Instant
Instant instant = Instant.ofEpochMilli(date.getTime());
Instant 转换成 Date
Date date = new Date(instant.toEpochMilli());

LocalDateTime

  LocalDateTime表示与时区无关的日期和时间,不直接对应时刻,需要通过时区转换。

获取系统默认时区的当前日期和时间:

LocalDateTime localDateTime = LocalDateTime.now();

同时LocalDateTime还支持直接指定年月日信息创建:

LocalDateTime localDateTime2 = LocalDateTime.of(2022, 1, 17, 10, 0, 0);

  LocalDateTime提供了直接获得具体年月信息方法,不再是Calendar那样的偏移量。

int year = localDateTime.getYear();
int month = localDateTime.getMonthValue();
int dayOfMonth = localDateTime.getDayOfMonth();
int hour = localDateTime.getHour();
int minute = localDateTime.getMinute();
int second = localDateTime.getSecond();
DayOfWeek dayOfWeek = localDateTime.getDayOfWeek();

LocalDate、LocalTime

  观察LocalDateTime的源码,可以发现LocalDateTime由LocalDate和LocalTime组成。

  • LocalDate:表示与时区无关的日期,与LocalDateTime相比,只有日期,没有时间信息;
  • LocalTime:表示与时区无关的时间,与LocalDateTime相比,只有时间,没有日期信息;
LocalDate localDate = localDateTime.toLocalDate();
LocalTime localTime = localDateTime.toLocalTime();

ZoneId/ZoneOffset

默认时区:

ZoneId zoneId = ZoneId.systemDefault();

自定义时区:

ZoneId zoneId = ZoneId.of("GMT+08:00");

  ZoneOffset是ZoneId的子类,可以根据时区差构造。

ZonedDateTime

  ZonedDateTime表示特定时区的日期和时间,获取系统默认时区的当前日期和时间。

基于系统默认时区,获得当前时间。

ZonedDateTime zonedDateTime = ZonedDateTime.now();
Instant 转换成 ZonedDateTime
ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(instant, ZoneId.systemDefault());
ZonedDateTime 转换成 Instant
Instant instant = zonedDateTime.toInstant();

时间格式化

DateTimeFormatter

  Java 8 中,加入了线程安全的时间格式化类java.time.format.DateTimeFormatter。

解析日期
String dateStr = "2016年10月25日";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
LocalDate date = LocalDate.parse(dateStr, formatter);
格式化时间
LocalDateTime now = LocalDateTime.now();
DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy年MM月dd日 hh:mm a");
String nowStr = now.format(format);

计算时间差

  Java 8 新增了两个类来表示时间差:Period表示日期之间的差,用年月日表示,不能表示时间;Duration表示时间差,用时分秒表示,也可以用天表示,一天严格等于24小时,不能用年月表示。

LocalDate localDate = LocalDate.of(2020, 5, 24);
LocalDate localDate2 = LocalDate.of(2021, 11, 2);
Period period = Period.between(localDate, localDate2);

System.out.println(period.getYears()); // 1
System.out.println(period.getMonths()); // 5
System.out.println(period.getDays()); // 9
LocalTime localTime = LocalTime.of(10, 0);
LocalTime localTime2 = LocalTime.now();
Duration duration = Duration.between(localTime, localTime2);