zoneId、ZoneOffset、Date、LocalDateTime、ZonedDateTime、OffsetDateTime的区别

本文探讨了Java中ZoneId、ZoneOffset和TimeZone在处理时区信息方面的差异,重点介绍了ZoneId和ZoneOffset的新旧对比,以及如何在LocalDateTime、ZonedDateTime和OffsetDateTime/OffsetTime类中灵活运用它们处理日期和时间,包括时区转换和偏移量的应用。
摘要由CSDN通过智能技术生成

1、zoneId
2、ZoneOffset继承了zoneId

3、ZoneOffset 和 TimeZone区别

ZoneOffset 和 TimeZone 是 Java 编程语言中处理时区信息的两个不同的类。

ZoneOffset 类:

ZoneOffset 是 Java 8 中引入的日期时间 API 的一部分,位于 java.time 包中。
它代表了与协调世界时(UTC)之间的固定时间偏移,以固定的小时和分钟表示。
例如,+02:00 表示时间比协调世界时快 2 小时。
TimeZone 类:

TimeZone 是旧的日期时间 API 中的类,位于 java.util 包中。
它用于表示时区信息,包括时区偏移、夏令时规则等。
TimeZone 类在 Java 1.0 中引入,但在 Java 8 之后,新的日期时间 API 提供了更先进和更安全的替代方案。
关系:

ZoneOffset 和 TimeZone 都与时区有关,但它们表示时区信息的方式不同。

ZoneOffset 表示一个固定的时区偏移,而 TimeZone 表示一个完整的时区,包括可能的夏令时规则。
在新的日期时间 API 中,更推荐使用 ZoneOffset 或 ZoneId(ZoneId 是 ZoneOffset 的父接口,也可以表示命名的时区,比如 “Europe/Paris”)。
如果你必须与旧的代码或库一起工作,可能需要进行一些转换,可以使用 ZoneId.of(“ZoneOffset”) 将 ZoneOffset 转换为 ZoneId。反之亦然。

ZoneOffset是JAVA8的API,他也包含了当地时间和UTC的偏移量。

TimeZone 这个是旧的,它包含了时区信息,偏移量等。


Date 和 LocalDateTime 是 Java 编程语言中处理日期和时间的两个不同的类。

Date 类:

Date 类是 Java 中用于表示日期和时间的类,它在 Java 1.0 中引入,但在 Java 8 之后已被大部分新的日期时间 API 所取代。
Date 类封装了自1970年1月1日UTC(协调世界时)开始的毫秒数。
这个类有一些问题,比如它是可变的,而且存在时区问题,因此在新的应用中更常用其他日期时间类。
LocalDateTime 类:

LocalDateTime 是 Java 8 中引入的日期时间 API 的一部分,位于 java.time 包中。
LocalDateTime 表示不带时区的日期和时间,即它不考虑时差或夏令时等问题。
该类提供了更丰富的日期和时间操作方法,同时是不可变的,因此更适合在多线程环境中使用。
关系:

Date 类和 LocalDateTime 类都用于表示日期和时间,但它们分别属于不同的日期时间 API。
在使用新的日期时间 API 时,推荐使用 LocalDateTime,因为它提供更强大和更安全的操作,并且考虑了一些 Date 类的问题。
如果你必须与旧的代码或库一起工作,可能需要在它们之间进行转换。可以使用 Date 类的 toInstant() 方法将其转换为 Instant,然后再通过 Instant 转换为 LocalDateTime。反之亦然。

小结:Date的老的日期API,LocalDateTime是JDK8的AIP, Date包含了时间戳,并且是UTC+时区的时间。

LocalDateTime 表示不带时区的日期和时间,所以他不用考虑时区带来的问题。

一、ZoneId and Offset

  1. ZoneId 表示时区,比如上海,北京、京东等等,当然既然知道时区,自然也就知道偏移量。
  2. ZoneOffset 表示偏移量,就是格林威治/ UTC时间的时区偏移量。这里不包含时区,因为同一个偏移量,可能会有多个时区,比如北京和上海的市区偏移量是一样的,但是他们属于不同的时区

ZoneId.getAvailableZoneIds(); 这个可以获取所有时区

ZoneId and Offset要配合时间类来使用,常用的时间类有下面3种

  • ZonedDateTime 使用格林威治/ UTC 的时区偏移量处理具有相应时区的日期和时间。
  • OffsetDateTime 使用格林威治/ UTC 的相应时区偏移量处理日期和时间,但不包含时区 ID。
  • OffsetTime 使用格林威治/ UTC 的相应时区偏移量处理时间,但不包含时区 ID。

二、ZonedDateTime

ZonedDateTime是结合了LocalDateTime类与zoneId类

前面介绍了LocalDateTime是不包含偏移量,也不好时区,就是一个时间,所以LocalDateTime可以很好的和zoneId或者ZoneOffset类一起使用

下面代码通过LocalDateTime+ZoneId得到ZonedDateTime

LocalDateTime leaving = LocalDateTime.of(2013, Month.JULY, 20, 19, 30);
ZoneId leavingZone = ZoneId.of("America/Los_Angeles");
ZonedDateTime departure = ZonedDateTime.of(leaving, leavingZone);
System.out.println(departure);
//ZonedDateTime结合DateTimeFormatter,可以转成我们想要的时间字符串格式,


//通过给ZonedDateTime设置新的时区,会刷新ZonedDateTime时间,返回该时区对应的时间。
ZoneId arrivingZone = ZoneId.of("Asia/Tokyo");
ZonedDateTime zonedDateTime = departure.withZoneSameInstant(arrivingZone);
System.out.println(zonedDateTime);

总结下:

1、首先固定一个不带任何时区的时间,也就是LocalDateTime
2、把这个时间加上需要的时区,就标识这个时间就是该时区的
3、把带时区的时间转换成目标时区,就可以得到一个目标时区的时间。

案例:组装一个地区+时间,比如洛杉矶时间,并且把他转成东京时间。这个是通过设置新的时区,来刷新时间。

DateTimeFormatter format = DateTimeFormatter.ofPattern("YYYY-MM-dd  HH:mm:ss");

//例如:2013-07-20 19:30:00
LocalDateTime leaving = LocalDateTime.of(2013, Month.JULY, 20, 19, 30);
ZoneId leavingZone = ZoneId.of("America/Los_Angeles");
ZonedDateTime departure = ZonedDateTime.of(leaving, leavingZone);
String out1 = departure.format(format);
System.out.printf("LEAVING:  %s (%s)%n", out1, leavingZone);


//补充知识:东京比洛杉矶多17个小时左右,比如洛杉矶上午4:50 在东京就是21:50
ZoneId arrivingZone = ZoneId.of("Asia/Tokyo");
//使用美国洛杉矶出发的时间,然后换算成东京的时区,返回该时区对应的时间
ZonedDateTime arrival = departure.withZoneSameInstant(arrivingZone);

//时间转成字符串
String out2 = arrival.format(format);
System.out.printf("ARRIVING: %s (%s)%n", out2, arrivingZone);

案例2:改变时区和刷新时间

LocalDateTime date = LocalDateTime.of(2018, 05, 01, 0, 0, 0);
ZonedDateTime d1 = ZonedDateTime.of(date, ZoneId.systemDefault());

// 把该时间转换成指定时区了,也就是会刷新这个地区的时间。
d1.withZoneSameInstant(ZoneId.of("Asia/Yerevan"));

// 只是改变了时区,不刷新时间
d1.withZoneSameLocal(ZoneId.of("Asia/Yerevan"));

二、OffsetDateTime

OffsetDateTime结合了 LocalDateTime 与类 ZoneOffset 类。它用于表示格林威治/ UTC 时间的偏移量,注意这个是不带时区的,相同的偏移量,可能会存在多个时区。

使用场景:比如有一个国外的时间,并且知道偏移量,那么我们要把这个时间转成标准的UTC+0的时间,或者转成北京时间。就可以使用下面的方式。

//1、通过其他地区的时间+偏移量 来得到对应的国际标准时间。

// 2017.07.20 19:30:00
LocalDateTime localDate = LocalDateTime.of(2013, Month.JULY, 20, 19, 30);
ZoneOffset offset = ZoneOffset.of("-08:00");
//通过LocalDateTime+ZoneOffset来得到OffsetDateTime
OffsetDateTime offsetDate = OffsetDateTime.of(localDate, offset);

//通过OffsetDateTime,我们可以重试给他设置偏移量,类得到这个偏移量所对应的时间。
OffsetDateTime offsetDateTime = offsetDate.withOffsetSameInstant(ZoneOffset.UTC);
System.out.println(offsetDateTime);

//2、OffsetDateTime也是可以转成Date的,不过需要理解下面的内容
//通过offsetDateTime转成LocalDateTime,在通过LocalDateTime转成Date,这里需要注意,首先是OffsetDateTime得到的LocalDateTime就是这个偏移所对应的时间,
// 时间上是没有任何变化,只是转成LocalDateTime对象
//LocalDateTime,是日期+偏移量,但是没有时区,atZone就是给他设置时区,这个时区,代码是取了默认的ZoneId.systemDefault(),所以最终结果date是没有任何变化,
// 只是加了时区进去,但是不会因为时区不同,导致时间变化。只有重行设置偏移量才会变化。
//OffsetDateTime offsetDateTime = offsetDate.withOffsetSameInstant(ZoneOffset.UTC);
//Date.from(offsetDateTime.toLocalDateTime().atZone(ZoneId.systemDefault()).toInstant());


//3、设置新的偏移量,但是不刷新时间

//设置新的偏移量,但是不会刷新时间,那么偏移量怎么得到呢?直接使用ZoneOffset.of方法
ZoneOffset newZoneOffset= ZoneOffset.of("-08:00");
OffsetDateTime offsetDateTime1=offsetDateTime.withOffsetSameLocal(newZoneOffset);
System.out.println(offsetDateTime1);

//4、设置新的偏移量,刷新时间。

ZoneOffset newZoneOffset1= ZoneOffset.of("-08:00");
OffsetDateTime offsetDateTime2 = offsetDate.withOffsetSameInstant(newZoneOffset1);
System.out.println(offsetDateTime2);
//注意withOffsetSameInstant和withOffsetSameLocal的作用是不一样的,withOffsetSameLocal是设置单纯的设置偏移量,不刷新时间。

三、OffsetTime

OffsetTime实际上,结合 LocalDateTime 与类 ZoneOffset 类。和OffsetDateTime比较像。所以我们大部分都是使用OffsetDateTime。

原文跳转1

原文跳转2

  • 20
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

信仰_273993243

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值