Duration的内部实现与Instant类似,也是包含两部分:seconds表示秒,nanos表示纳秒。两者的区别是Instant用于表示一个时间戳(或者说是一个时间点),而Duration表示一个时间段,所以Duration类中不包含now()静态方法。可以通过Duration.between()方法创建
LocalDateTime from = LocalDateTime.of(2019, Month.JANUARY, 5, 10, 7, 0); // 2019-01-05 10:07:00 LocalDateTime to = LocalDateTime.of(2019, Month.FEBRUARY, 5, 10, 7, 0); // 2019-02-05 10:07:00 Duration duration = Duration.between(from, to); // 表示从 2019-01-05 10:07:00 到 2019-02-05 10:07:00 这段时间 long days = duration.toDays(); // 这段时间的总天数 long hours = duration.toHours(); // 这段时间的小时数 long minutes = duration.toMinutes(); // 这段时间的分钟数 long seconds = duration.getSeconds(); // 这段时间的秒数 long milliSeconds = duration.toMillis(); // 这段时间的毫秒数 long nanoSeconds = duration.toNanos(); // 这段时间的纳秒数Duration对象还可以通过of()方法创建,该方法接受一个时间段长度,和一个时间单位作为参数:
Duration duration1 = Duration.of(5, ChronoUnit.DAYS); // 5天 Duration duration2 = Duration.of(1000, ChronoUnit.MILLIS); // 1000毫秒Period:处理两个日期之间的差值
Period在概念上和Duration类似,区别在于Period是以年月日来衡量一个时间段,比如2年3个月6天
Period period = Period.of(2, 3, 6);
Period对象也可以通过between()方法创建,值得注意的是,由于Period是以年月日衡量时间段,所以between()方法只能接收LocalDate类型的参数:
Period period = Period.between( LocalDate.of(2019, 1, 5), LocalDate.of(2019, 2, 5));示例
LocalDate date = LocalDate.of(2019,01,22); LocalDate date1 = LocalDate.now(); Period period = Period.between(date,date1); System.out.println(period.getYears() + "年" + period.getMonths() + "月" + period.getDays() + "天"); LocalTime time = LocalTime.of(20,30); LocalTime time1 = LocalTime.of(23,59); Duration duration = Duration.between(time,time1); System.out.println(duration.toMinutes() + "分钟"); ZonedDateTime无论是我们的 LocalDate,或是 LocalTime,甚至是 LocalDateTime,它们基本是时区无关的,内部并没有存储时区属性,而基本用的系统默认时区。往往有些场景之下,缺乏一定的灵活性。
ZonedDateTime 可以被理解为 LocalDateTime 的外层封装,它的内部存储了一个 LocalDateTime 的实例,专门用于普通的日期时间处理。此外,它还定义了 ZoneId 和 ZoneOffset 来描述时区的概念。
ZonedDateTime 和 LocalDateTime 的一个很大的不同点在于,后者内部并没有存储时区,所以对于系统的依赖性很强,往往换一个时区可能就会导致程序中的日期时间不一致。
而后者则可以通过传入时区的名称,使用 ZoneId 进行匹配存储,也可以通过传入与零时区的偏移量,使用 ZoneOffset 存储时区信息。
示例
ZonedDateTime zonedDateTime = ZonedDateTime.now(); System.out.println(zonedDateTime); //->2019-01-31T16:27:23.179+08:00[Asia/Shanghai] LocalDateTime localDateTime = LocalDateTime.now(); ZoneId zoneId = ZoneId.of("America/Los_Angeles"); ZonedDateTime zonedDateTime1 = ZonedDateTime.of(localDateTime,zoneId); System.out.println(zonedDateTime1); // ->2019-01-31T16:27:23.179-08:00[America/Los_Angeles] Instant instant = Instant.now(); ZoneId zoneId1 = ZoneId.of("GMT"); ZonedDateTime zonedDateTime2 = ZonedDateTime.ofInstant(instant,zoneId1); System.out.println(zonedDateTime2); // ->2019-01-31T08:27:23.183Z[GMT]第一个输出应使用了当前系统日期和时间以及默认的时区。
第二个小例子,LocalDateTime 实例保存了时区无关的当前日期时间信息,也就是这里的年月日时分秒,接着构建一个 ZonedDateTime 实例并传入一个美国时区(西七区)。你会发现输出的日期时间为西七区的 16 点 27 分。
像这种关联了时区的日期时间就很能够解决那种,换时区导致程序中时间错乱的问题。因为我关联了时区,无论你程序换到什么地方运行了,日期+时区 本就已经唯一确定了某个时刻,就相当于我在存储某个时刻的时候,说明了这是某某时区的某某时间,即便你换了一个地区,也不至于把这个时间按自己当前的时区进行解析并直接使用。
第三个小例子,构建 ZonedDateTime实例的时候,给定一个时刻和一个时区,而这个时刻值就是相对于给定时区的标准时间所经过的毫秒数。