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.getAvailableZoneIds(); 这个可以获取所有时区
ZoneId and Offset要配合时间类来使用,常用的时间类有下面3种
- ZonedDateTime 使用格林威治/ UTC 的时区偏移量处理具有相应时区的日期和时间。
- OffsetDateTime 使用格林威治/ UTC 的相应时区偏移量处理日期和时间,但不包含时区 ID。
- OffsetTime 使用格林威治/ UTC 的相应时区偏移量处理时间,但不包含时区 ID。
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结合了 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实际上,结合 LocalDateTime 与类 ZoneOffset 类。和OffsetDateTime比较像。所以我们大部分都是使用OffsetDateTime。
原文跳转1
原文跳转2