10.4小节所介绍的LocalDateTime类对象可以代表一个时间点,但严格的说,这个对象所代表的时间点并不精确,这是因为对象中并不包含时区信息。例如北京时间的2022年6月1日早上8点和法国巴黎时间的2022年6月1日早上8点并不是同一个时间点。因此仅靠“2022年6月1日早上8点”,人们并不能准确的知道这是哪一个时间点。如果希望精确的描述一个时间点,日期时间对象中就必须包含时区信息。

Java8新日期时间系统中专门定义了表示时区的类,这个类的名称叫做ZoneId。ZoneId是一个抽象类,它有两个子类,分别是ZoneRegion,另一个子类叫做ZoneOffset。为什么要定义ZoneRegion和ZoneOffset两个类来表示时区呢?这是因为人们可以通过两种方式来定义时区。

第一种方式是通过城市或地区来定义时区。世界上有很多城市和地区,这些城市或地区都处在某个特定的时区当中,因此如果指定了一个城市或地区,就能确定它所在的时区。ZoneRegion就是代表城市或地区的类,当一个ZoneRegion类对象被创建后,ZoneRegion类对象所代表的那个城市或地区的时区也会被确定,所以说一个ZoneRegion类对象就代表一个时区。

第二种定义时区的方式是指定时差。我们知道:全球共分为24个时区,人们把英国格林尼治时间天文台所在的那个时区称为“零时区”或“中时区”,其他各个时区与零时区都有时差。因此只需要指出与零时区的时差,也能确定一个时区。ZoneOffset就是代表时差的类,但必须说明:ZoneOffset类对象所代表的时差并不是任意两个地区的时差,而是特指与零时区的时差。ZoneOffset类对象中包含了与零时区的时差数值,所以ZoneOffset类对象也能代表一个时区。

10.6.1 ZoneRegion类

因为ZoneId是一个抽象类,因此程序员可以通过ZoneId类的of()静态方法来创建它的子类对象,如果为of()方法传递的字符串参数代表一个城市或地区,那么of()方法将会创建出一个ZoneRegion类的对象。此外,还可以调用systemDefault()方法来创建一个表示系统默认地区的ZoneRegion类的对象。下面的【例10_25】展示了如何创建ZoneRegion类对象以及获取对象中所包含的信息。

【例10_25 创建ZoneRegion类对象】

Exam10_25.java

import java.time.ZoneId;
public class Exam10_25 {public static void main(String[] args){ZoneId zid1 = ZoneId.systemDefault();//①ZoneId zid2 = ZoneId.of("Europe/Paris");//②System.out.println("zid1的类型:"+zid1.getClass().getName());//③System.out.println("zid1的值:"+zid1);System.out.println("zid1的时区信息:"+zid1.getRules());System.out.println("zid2的类型:"+zid2.getClass().getName());//④System.out.println("zid2的值:"+zid2);System.out.println("zid2的时区信息:"+zid2.getRules());}
}

【例10_25】的语句①创建了一个操作系统默认的时区对象,而语句②则通过字符串参数创建了一个代表法国巴黎所在时区的对象。语句③和语句④调用了getClass()方法获得这两个对象的类型并打印类型的名称。【例10_25】的运行结果如图10-22所示。

图10-22【例10_25】运行结果

从图10-22可以看出:zid1和zid2都是ZoneRegion类对象。此处需要说明:ZoneRegion不是一个public类,所以在程序中无法直接访问这个类,也创建不出这个类型的引用。由于ZoneRegion和ZoneOffset都代表时区,所以程序中一般都统一使用ZoneId类的引用指向这两个类的对象。此外还可以看出:直接打印ZoneRegion类对象只能输出ZoneRegion类对象所代表的城市或地区,而操作系统默认的时区用ZoneRegion类对象表示出来是“Asia/Shanghai”,意为“亚洲/上海”,并不是人们常用的北京。如果希望打印ZoneRegion类对象的时区信息,需要调用getRules()方法。zid1的时区信息为“ZoneRules[currentStandardOffset=+08:00]”,其中“+08:00”表示这个时区比零时区的时间早8个小时。同理,zid2时区信息中的“+01:00”表示法国巴黎所在的时区比零时区早1个小时。

在创建zid2对象时为of()方法所传递的参数为“Europe/Paris”,它表示“欧洲/巴黎”。但是需要注意:并不是任意一个大洲的名称加上城市的名称所组成的字符串都可以成为of()方法的参数,例如“Asia/Beijing”就不可以当作of()方法的参数,如果以这个字符串作为参数,程序在执行of()方法时会抛出异常。所有能够作为of()方法参数的字符串都被存放到一个集合中,程序员可以通过ZoneId类定义的getAvailableZoneIds()静态方法来获得这个集合,遍历这个集合就可以得到所有可以作为of()方法参数的字符串。下面这段代码展示了如何获取集合并通过增强型for循环遍历集合中所有元素。

for (String str:ZoneId.getAvailableZoneIds())
{System.out.println(str);
}

10.6.2 ZoneOffset类

前文讲过:如果给ZoneId的of()方法传递的字符串参数代表一个城市或地区,那么of()方法将会创建出一个ZoneRegion类的对象。那么,如果给of()方法传递的字符串参数代表与零时区的时差,of()方法将会创建一个ZoneOffset类的对象。下面的【例20_26】展示了用多种形式的参数创建ZoneOffset类的对象的过程。

【例20_26 创建ZoneOffset类对象1】

Exam10_26.java

import java.time.ZoneId;
public class Exam10_26 {public static void main(String[] args){ZoneId zid1 = ZoneId.of("+08:00");//①ZoneId zid2 = ZoneId.of("+8");//②ZoneId zid3 = ZoneId.of("+080000");//③ZoneId zid4 = ZoneId.of("+08:30:00");//④ZoneId zid5 = ZoneId.of("UTC+08:00:00");//⑤ZoneId zid6 = ZoneId.of("GMT+08:00:00");//⑥System.out.println("zid5的时区信息:"+zid5.getRules());System.out.println("zid6的时区信息:"+zid6.getRules());}
}

【例10_26】通过向of()方法传递表示时差的字符串参数创建了6个ZoneOffset类对象。其中语句①为of()方法所传递的参数为“+08:00”,它表示比零时区的时间早8小时0分。参数中“+”表示比零时区的时间更早,如果换成“-”,则表示比零时区的时间更晚。语句②为of()方法所传递的参数为“+8”,这是一种简略的写法,也表示比零时区的时间早8小时。需要注意:只有在省略分钟的情况下才能省略数字8之前的0,也就是说不能把参数写为“+8:00”。语句③为of()方法传递的参数为“080000”,它表示比零时区的时间早8小时0分0秒,实际上,这个参数的标准写法是“08:00:00”,Java语言规定:如果参数中时、分、秒都用两位数来表示,那么它们之间的冒号(:)可以省略。语句④所创建的对象表示比零时区的时间早8小时30分。这说明ZoneOffset对象所代表的时区与零时区的时差并不一定是1小时的整数倍,它可以与零时区相差任意长度的时间,只要这个时差不超过18小时即可。语句⑤和⑥中,字符串参数中出现了“UTC”和“GMT”,它们代表了两种时间系统。“GMT”表示格林尼治时间,它是通过计算地球自转周期所确定的时间系统,而“UTC”表示协调世界时,它是通过计算原子吸收或释放能量时发出电磁波的频率所确定的时间系统。【例10_26】的运行结果如图10-23所示。

图10-23【例10_26】运行结果

从图10-23可以看出:zid5和zid6的时区信息是一样的,这说明在Java8新日期时间系统中GMT时间和UTC时间之间不存在时间差。

程序员除了可以用ZoneId类的of()方法创建出ZoneOffset类的对象,还可以直接通过ZoneOffset类中所定义的of()方法来创建ZoneOffset对象,需要注意:这个of()方法的参数中不能带有“UTC”或“GMT”。除此之外,ZoneOffset类还定义了一系列以of开头的方法用于创建ZoneOffset类的对象,并且还定义了getTotalSeconds()方法用于计算与零时区的时差是多少秒。下面的【例10_27】展示了如何使用ZoneOffset类所定义的方法创建对象,并如何计算这些对象所代表的时区与零时区之间的时差。

【例20_27 创建ZoneOffset类对象2】

Exam10_27.java

import java.time.ZoneOffset;
public class Exam10_27 {public static void main(String[] args){ZoneOffset zo1 = ZoneOffset.of("+08:00");ZoneOffset zo2 = ZoneOffset.of("+8");ZoneOffset zo3 = ZoneOffset.of("+080000");ZoneOffset zo4 = ZoneOffset.of("+08:30:00");//设置时差为3600秒(1小时)ZoneOffset zo5 = ZoneOffset.ofTotalSeconds(3600);//设置时差为3小时ZoneOffset zo6 = ZoneOffset.ofHours(3);//设置时差为3小时30分ZoneOffset zo7 = ZoneOffset.ofHoursMinutes(3,30);//设置时差为4小时20分45秒ZoneOffset zo8 = ZoneOffset.ofHoursMinutesSeconds(4,20,45);int r1 = zo1.getTotalSeconds();//计算zo1与零时区的时差int r2 = zo5.getTotalSeconds();//计算zo5与零时区的时差System.out.println("zo1与零时区之间相差"+r1+"秒");System.out.println("zo5与零时区之间相差"+r2+"秒");System.out.println("zo1与zo5之间相差"+(r1-r2)+"秒");}
}

【例10_27】的运行结果如图10-24所示。

图10-24【例10_27】运行结果

除阅读文章外,各位小伙伴还可以点击这里观看我在本站的视频课程学习Java!

第十章《日期与时间》第6节:ZoneId、ZoneRegion和ZoneOffset相关推荐

  1. 《Java8实战》笔记(12):新的日期和时间API

    新的日期和时间API 相信大多数有经验的程序员都会赞同Java 8之前的库对日期和时间的支持就非常不理想.值得高兴的是 Java 8中引入全新的日期和时间API就是要解决这一问题. Java 8之前的 ...

  2. 《Java 8 in Action》Chapter 12:新的日期和时间API

    在Java 1.0中,对日期和时间的支持只能依赖java.util.Date类.同时这个类还有两个很大的缺点:年份的起始选择是1900年,月份的起始从0开始. 在Java 1.1中,Date类中的很多 ...

  3. 【转】C/C++中的日期和时间

    头文件 time.h 函数用途 函数名 得到处理器时间 clock 得到时间差 difftime 设置时间 mktime 得到时间 time 得到以ASCII码表示的时间 asctime 得到字符串表 ...

  4. php入门时间,php入门教程(二十一) php日期与时间函数

    本节内容: php日期与时间函数 PHP提供了很多的处理日期和时间的函数,包括time().date().mktime().checkdate().microtime().strtotime()等,详 ...

  5. mysql提供了表示日期和时间的数据类型_MySQL数据类型 - 日期和时间类型(1)

    1.日期和时间数据类型语法 用于表示时间值的日期和时间数据类型是DATE, TIME, DATETIME, TIMESTAMP和 YEAR. 对于TIME, DATETIME和 TIMESTAMP值, ...

  6. php极客时间,PHP日期与时间

    日期与时间是一种比较复杂的组合型数据,各种环境下的处理方式并不完全一致:本节,我们就了解一些在PHP中处理日期与时间的函数,并对一些常用代码进行封装. time().mktime()与checkdat ...

  7. java8 日期比较_20 个案例教你在 Java 8 中如何处理日期和时间?

    点击左上角蓝字,关注"SpringForAll社区" 专注分享Spring周边技术内容 前言 前面一篇文章写了<SimpleDateFormat 如何安全的使用?>, ...

  8. C++中的日期和时间 time_t与struct tm转换

    C++中的日期和时间 time_t与struct tm转换 通过学习许多C/C++库,可以有很多操作.使用时间的方法.但在这之前需要了解一些 "时间"和"日期" ...

  9. python中datetime函数怎么获得当年年份_Python 日期和时间函数使用指南

    在本教程中,我们将介绍 python 的 datetime 模块以及如何使用它来处理日期.时间,以及日期时间的格式化处理. 它包含各种实用示例,可帮助您通过 python 函数更加快捷高效进行日期和时 ...

  10. C/C++中的日期和时间

    C/C++中的日期和时间 由 zhanjun 在 周五, 2006-03-24 08:11 提交 C/C++中的日期和时间 作者:日期和时间 出处:日期和时间 更新时间: 2005年09月15日 摘要 ...

最新文章

  1. Vue 里 几个重要的指令
  2. Javascript/Jquery——简单定时器
  3. Fluid 0.5 版本:开启数据集缓存在线弹性扩缩容之路
  4. SpringBoot_日志-指定日志文件和日志Profile功能
  5. linux系统结构与文件管理命令
  6. 面向对象技术——UML
  7. linux 如何重启apache
  8. 避免野指针的方法及结构体小细节
  9. 替代亿图的软件-mac,windows都可用
  10. visual_c++外挂教程(较详细)
  11. vblog 的 前景展望
  12. CentOs解压缩命令
  13. 该如何去认知Level 2 十档行情数据?
  14. 统计学习导论之R语言应用(二):R语言基础
  15. 修改火狐浏览器滚动条样式
  16. ubuntu14.04 64位安装H3C iNode客户端
  17. 人工智能到底有多强大?
  18. 判断质数和合数python代码_小学五年级数学《质数和合数》测试题
  19. 什么是cookie?什么是session?cookie与session有什么区别
  20. 2006世界杯夺冠热门分析

热门文章

  1. mac关闭当前窗口快捷键,mac关闭当前应用快捷键
  2. 大众-OBD-接口位置
  3. 阿里云安全防护是如何做到的?有怎样的安全生态圈
  4. ios如何解除dns被劫持_iPhone被DNS劫持,老跳广告咋办?
  5. oracle 19c jdbc之Reactive Streams Ingestion (RSI) Library
  6. 计算机的奇迹英语作文,高中英语作文范文:奇迹
  7. 洛谷 P2123 皇后游戏 解题报告
  8. [鸿篇巨制]蚂蚁金融级分布式架构SOFAStack编年史
  9. 桂林电子科技大学校园网登录数据包抓取教程实现路由器每天自动登录
  10. 把两个pdf合并成一个如何解决?