惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Hacker News: Ask HN
Hacker News: Ask HN
H
Help Net Security
Microsoft Azure Blog
Microsoft Azure Blog
B
Blog RSS Feed
Jina AI
Jina AI
Stack Overflow Blog
Stack Overflow Blog
量子位
博客园_首页
Vercel News
Vercel News
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Forbes - Security
Forbes - Security
IT之家
IT之家
N
News and Events Feed by Topic
S
Security Affairs
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Webroot Blog
Webroot Blog
Recorded Future
Recorded Future
L
LangChain Blog
Y
Y Combinator Blog
AI
AI
MyScale Blog
MyScale Blog
大猫的无限游戏
大猫的无限游戏
小众软件
小众软件
Know Your Adversary
Know Your Adversary
AWS News Blog
AWS News Blog
Help Net Security
Help Net Security
Cyberwarzone
Cyberwarzone
L
Lohrmann on Cybersecurity
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Google Online Security Blog
Google Online Security Blog
V2EX - 技术
V2EX - 技术
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
PCI Perspectives
PCI Perspectives
I
Intezer
T
Tenable Blog
G
Google Developers Blog
Application and Cybersecurity Blog
Application and Cybersecurity Blog
T
Troy Hunt's Blog
L
LINUX DO - 最新话题
云风的 BLOG
云风的 BLOG
C
CXSECURITY Database RSS Feed - CXSecurity.com
有赞技术团队
有赞技术团队
O
OpenAI News
P
Proofpoint News Feed
TaoSecurity Blog
TaoSecurity Blog
C
Check Point Blog
Last Week in AI
Last Week in AI
S
Schneier on Security
Simon Willison's Weblog
Simon Willison's Weblog
Blog — PlanetScale
Blog — PlanetScale

Java技术经验分享

生产故障处理SOP分享 | Java技术经验分享 系统稳定性建设实践总结【转载】 | Java技术经验分享 valine访问leancloud国际版异常,评论失效修复 | Java技术经验分享 匆匆忙忙的2021 | Java技术经验分享 聊一下换工作 | Java技术经验分享 IoT系列(2):WIFI设备常见配网方案介绍 | Java技术经验分享 IoT系列(1):什么是物联网 | Java技术经验分享 Java8特性2 - StreamApi | Java技术经验分享 Java8特性1 - lambda表达式&函数式接口 | Java技术经验分享 设计模式(5)-适配器模式 | Java技术经验分享 设计模式(4)-建造者模式 | Java技术经验分享 设计模式(3)-原型模式与浅拷贝和深拷贝 | Java技术经验分享 设计模式(2)-工厂模式图文介绍 | Java技术经验分享 设计模式(1)-带你了解3类8种单例模式 | Java技术经验分享 Java时间处理4---Java8中LocalDate、LocalTime、LocalDateTime介绍 | Java技术经验分享 Java时间处理3---Java8中Instant、Duration、Period、Clock介绍 | Java技术经验分享 一些有意思的问答 | Java技术经验分享 Nacos系列博客说明 | Java技术经验分享 菜鸡程序员的2019年度总结 | Java技术经验分享 Java中“附近的人”实现方案讨论及代码实现 | Java技术经验分享 Java时间处理2----时区TimeZone类方法探究(Java8以前) | Java技术经验分享 Java时间处理1----Date和Calendar方法探究(Java8以前) | Java技术经验分享 FastJson中JSONString、JavaBean、JSONObject、JSONArray的转换关系及API示例 | Java技术经验分享 2019.11软考软件设计师归来心得体会及复习备考指南 | Java技术经验分享 你还没用过“约定式提交”吗?那你赶紧来补补知识吧 | Java技术经验分享 教你如何看懂UML中的类图及类图中的关系 | Java技术经验分享 设计模式总览 | Java技术经验分享 萌新入门Github请看这里,学不会远程教 | Java技术经验分享 Hexo的工作原理探究 | Java技术经验分享 Hexo-theme-butterfly修改调整记录教程 | Java技术经验分享 排序8:基数排序 | Java技术经验分享 排序7:归并排序 | Java技术经验分享 排序6:快速排序 | Java技术经验分享 排序5:冒泡排序 | Java技术经验分享 排序4:堆排序 | Java技术经验分享 排序3:选择排序 | Java技术经验分享 排序2:希尔排序 | Java技术经验分享 排序1:直接插入排序 | Java技术经验分享 推荐一款博客一文多发的良心工具OpenWrite | Java技术经验分享 近期学习计划 | Java技术经验分享 Nacos(九):Nacos集群部署和遇到的问题 | Java技术经验分享 Nacos(八):Nacos持久化 | Java技术经验分享 Nacos(七):Nacos共享配置 | Java技术经验分享 Nacos(六):多环境下如何“管理”及“隔离”配置和服务 | Java技术经验分享 Nacos(五):多环境下如何“读取”Nacos中相应的配置 | Java技术经验分享 Nacos(四):SpringCloud项目中接入Nacos作为配置中心 | Java技术经验分享 Nacos(三):Nacos与OpenFeign的对接使用 | Java技术经验分享 Nacos(二):SpringCloud项目中接入Nacos作为注册中心 | Java技术经验分享 Nacos(一):Nacos介绍 | Java技术经验分享 20190719小组分享 | Java技术经验分享 Java中equals和HashCode方法的分析 | Java技术经验分享 Java中==和equals方法的分析 | Java技术经验分享 Java中的自动拆装箱、装箱缓存 | Java技术经验分享 About-blog | Java技术经验分享 Java中的编译、反编译和反编译工具全家桶分享 | Java技术经验分享 finalize()的生命周期(执行过程) | Java技术经验分享 Java关键字之final、finally与finalize方法 | Java技术经验分享 Java中重写、重载 | Java技术经验分享 Java中面向对象的三大特征:继承、封装、多态 | Java技术经验分享 DockerFile介绍 | Java技术经验分享 Docker环境下安装Gitlab | Java技术经验分享 Docker中私有仓库的搭建流程 | Java技术经验分享 Centos7下两种方式安装Docker-CE | Java技术经验分享 Vert.x创建一个Http服务 | Java技术经验分享 Vert.x创建TCP服务端及客户端 | Java技术经验分享 Vert.x Core(二)- Event Bus(事件总线) | Java技术经验分享 Vert.x-Core(一)- 基础篇 | Java技术经验分享 SpringBoot项目中实现国际化 | Java技术经验分享 Vert.x介绍 | Java技术经验分享 毕设选题项目本地运行环境搭建教程 | Java技术经验分享 Jupyter Notebooks的安装和使用介绍 | Java技术经验分享 算法笔试题:1元,5元,10元,20元,50元、100元面值人民币组合给定x元的问题 | Java技术经验分享 Quartz学习总结 | Java技术经验分享 SpringBoot2.x集成Redis | Java技术经验分享 SpringBoot2.x集成MongoDB | Java技术经验分享 [SpringCloud学习] - 浅谈微服务架构 | Java技术经验分享 基于hexo和coding免费搭建个人博客网站 | Java技术经验分享 Hello World | Java技术经验分享
Java时间处理5---Java8中时区相关类库介绍 | Java技术经验分享
文章作者: LarsCheng · 2020-07-10 · via Java技术经验分享

前言

在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

1
2
3
4
5
6
7
//获取系统默认时区
System.out.println(ZoneId.systemDefault());
//4种常用方式创建ZoneId
System.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")));

输入结果:

1
2
3
4
5
Asia/Shanghai
+01:00
UTC+01:00
America/Chicago
UTC+01:00

创建ZoneOffSet

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

输出结果:

1
2
3
+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的常用方法

初始化

1
2
3
4
5
6
7
8
9
10
//默认系统时区
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")));

输出结果:

1
2
3
4
5
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:00
2020-07-10T11:44:15.668+08:00[Asia/Shanghai]
2020-01-01T01:01:01.000000111+01:00[Europe/Paris]

其他方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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));

输出结果

1
2
3
4
5
6
7
8
9
Asia/Shanghai
+08:00
10
FRIDAY
192
2020/7/10 13:37:19.37000000
2020-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

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

1
2
3
4
5
6
7
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));

输出结果:

1
2
3
4
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,假设你知道目标时区的多种偏移时间,那么可以进行代码判断处理,但是如果要转换的时区很多,或者完全没有考虑夏时令问题时,那么转换出来的时间将会超乎你的想象!!