写点什么

Java 时间处理 ---Java8 中时区相关类库介绍

  • 2023-10-17
    湖南
  • 本文字数:2428 字

    阅读完需:约 8 分钟

前言

在 Java8 以前,我们对于时区的处理通常是为时间转换类设置指定 TimeZone,然后进行时区时间转换。

而在 Java8 中不仅对时间日期进行了细粒度处理,有无时区,时区处理也进行了更加细粒度的优化。

在之前我们介绍的新类库中基本都是无时区概念的。本文将引入时区概念。

概念

介绍时区相关类库前,先来认识下 Java 中常见的几种时间格式

1.世界标准时间(UTC 时间),其中 T 表示时分秒的开始,结尾的 Z 表示这是一个世界标准时间

2020-07-06T11:24:37.081Z

2.本地时间(不含时区信息的时间),结尾无时区信息

2020-07-06T19:24:37.156

3.含有时区信息的时间,+08:00表示该时间是由 UTC 时间加上 8 小时得到的,[Asia/Shanghai]表示该时间的时区信息

2020-07-06T19:24:37.156+08:00[Asia/Shanghai]

ZoneId 和 ZoneOffSet

  • ZoneId 表示一个时区实例,他的内部定义了一个地区的时区规则集,例如Europe/Paris

  • ZoneOffSet 表示与 UTC 时间的偏移时间,格式为+08:00-04:00

创建 ZoneId


//获取系统默认时区System.out.println(ZoneId.systemDefault());//4种常用方式创建ZoneIdSystem.out.println(ZoneId.of("+01:00"));System.out.println(ZoneId.of("UTC+01:00"));System.out.println(ZoneId.of("America/Chicago"));System.out.println(ZoneId.ofOffset("UTC", ZoneOffset.of("+01:00")));
复制代码

输入结果:

Asia/Shanghai+01:00UTC+01:00America/ChicagoUTC+01:00
复制代码


创建 ZoneOffSet

System.out.println(ZoneOffset.ofHours(3));System.out.println(ZoneOffset.ofHoursMinutesSeconds(1, 2, 3));System.out.println(ZoneOffset.of("+01:00"));
复制代码


输出结果:

+03:00+01:02:03+01:00
复制代码


单独看 ZoneId 和 ZoneOffSet 可能还不能完全看出使用效果,下面看看带时区的日期时间

ZoneDateTime

表示 ISO-8601 日历系统中具有时区的日期时间,此类存储所有日期和时间字段,精度为纳秒,时区为区域偏移量,用于处理模糊的本地日期时间。

例如:2020-07-06T19:24:37.156+08:00[Asia/Shanghai]

ZonedDateTime 相当于拥有三个独立对象,一个本地日期时间LocalDateTime ,一个时区 IDZoneId和时间偏移量ZoneOffset

偏移量和本地日期时间用于在必要时定义一个瞬时时间。 时区 ID 用于获取偏移量的具体规则。(因为在部分区域夏时令时的偏移量与平常不同)

来看看 ZoneDateTime 的常用方法

初始化

//默认系统时区System.out.println(ZonedDateTime.now());//指定一个时区的时间System.out.println(ZonedDateTime.now(Clock.system(ZoneId.of("Europe/Paris"))));//指定一个偏移量的时间System.out.println(ZonedDateTime.now(Clock.system(ZoneOffset.of("+04:00"))));//根据本地日期时间和系统时区组合日期时间System.out.println(ZonedDateTime.of(LocalDateTime.now(), ZoneId.systemDefault()));//根据年月日时分秒毫秒纳秒时区id构建System.out.println(ZonedDateTime.of(2020, 1, 1, 1, 1, 1, 111, ZoneId.of("Europe/Paris")));
复制代码


输出结果:

2020-07-10T11:44:15.651+08:00[Asia/Shanghai]2020-07-10T05:44:15.653+02:00[Europe/Paris]2020-07-10T07:44:15.668+04:002020-07-10T11:44:15.668+08:00[Asia/Shanghai]2020-01-01T01:01:01.000000111+01:00[Europe/Paris]
复制代码


其他方法

ZonedDateTime z = ZonedDateTime.of(LocalDateTime.now(), ZoneId.systemDefault());
System.out.println(z.getZone());//获取时区信息System.out.println(z.getOffset());//获取时间偏移量System.out.println(z.getDayOfMonth());//获取当月第几天System.out.println(z.getDayOfWeek());//获取本周星期几System.out.println(z.getDayOfYear());//获取本年第几天//获取时间信息System.out.println(z.getYear()+"/"+z.getMonthValue()+"/"+z.getDayOfMonth()+" "+ z.getHour()+":"+z.getMinute()+":"+z.getSecond()+"."+z.getNano());//加减时间System.out.println(z.plusHours(3));System.out.println(z.minusHours(3));//修改时间System.out.println(z.withHour(20));
复制代码


输出结果

Asia/Shanghai+08:0010FRIDAY1922020/7/10 13:37:19.370000002020-07-10T16:37:19.037+08:00[Asia/Shanghai]2020-07-10T10:37:19.037+08:00[Asia/Shanghai]2020-07-10T20:37:19.037+08:00[Asia/Shanghai]
复制代码


时区与偏移量

本文开始的时候介绍了 ZoneId 和 ZoneOffSet,在 Java8 中这两个类都可以对日期时间进行时区的转换,但是我更推荐使用时区信息(ZoneId),而不是时间偏移量(ZoneOffset)

首先需要重温一下概念

  • ZoneId 表示一个时区实例,他的内部定义了一个地区的时区规则集,例如Europe/Paris

  • ZoneOffSet 表示与 UTC 时间的偏移时间,格式为+08:00-04:00

这里我们以亚洲上海时间(北京时间)—>法国巴黎时间为例,对三月份的时间和六月份两个时间进行转换

ZoneId zoneId = ZoneId.of("Europe/Paris");ZonedDateTime now = ZonedDateTime.now().withMonth(6);System.out.println("6月的此时北京时间:"+now);System.out.println("6月的此时巴黎时间:"+now.withZoneSameInstant(zoneId));ZonedDateTime newTime = now.withMonth(3);System.out.println("3月的此时北京时间:"+newTime);System.out.println("3月的此时巴黎时间:"+newTime.withZoneSameInstant(zoneId));
复制代码


输出结果:

6月的此时北京时间:2020-06-10T14:23:48.756+08:00[Asia/Shanghai]6月的此时巴黎时间:2020-06-10T08:23:48.756+02:00[Europe/Paris]3月的此时北京时间:2020-03-10T14:23:48.756+08:00[Asia/Shanghai]3月的此时巴黎时间:2020-03-10T07:23:48.756+01:00[Europe/Paris]
复制代码


有没有发现什么异样?

两个同一时刻不同月份的时间转换了时区后第一次偏移量为 2 小时,第二次为 1 小时

这是因为部分国家存在夏时令这种骚操作,一年中不同的月份有着不同的时间偏移量。



如果我们使用 ZoneOffset,假设你知道目标时区的多种偏移时间,那么可以进行代码判断处理,但是如果要转换的时区很多,或者完全没有考虑夏时令问题时,那么转换出来的时间将会超乎你的想象!!

用户头像

只要码不死,就往死里码 2021-11-19 加入

还未添加个人简介

评论

发布
暂无评论
Java时间处理---Java8中时区相关类库介绍_Java 面试_程序员万金游_InfoQ写作社区