关于时区常见的问题:如何在java8及更高版本中获取默认的ZoneOffset?

tl;dr

OffsetDateTime.now().getOffset()

但是,建议使用时区(ZoneId) 而不是UTC的偏移量 (ZoneOffset)。

偏移量 VS 时区

一个UTC偏移量 offset-from-UTC 仅仅只记录了时分秒而已,除此之外没有任何其他信息。举个例子 ,+08:00的意思时超前于UTC八个小时,而 -05:45 意思是落后于UTC五小时四十五分钟。

而时区对于特定地区的人来说是过去,现在,未来的偏移量的历史集合。像夏令时 这样的异常会导致特定时间段内的偏移量会随时间变化,无论是过去已经发生的还是 未来政客们宣布计划的改变。

所以,当你了解时最好还是使用时区。

很多地区的偏移量都会随时间变化。比如,美国的夏令时 会导致约半年左右的时间内都会再原来的基础上偏移一个小时,然后再下半年再调整回这一个小时的偏移量。时区的意义就是记录这些所有的会造成偏移的情况。

因此,没有结合日期计算的偏移量没有意义的。举个例子,法国时间 (Europe/Paris),在一年的一小部分时间内偏移量为+01:00,而由于夏令时的缘故,大部分时间(三月末到十月末)的偏移量都是+02:00。

// 指定区域,构造时间: 法国巴黎时间的当前时间,五月有DST,偏移量+2

LocalDateTime now = LocalDateTime.of(LocalDate.of(2020, 5, 31), LocalTime.now())

ZonedDateTime zonedDateTime = ZonedDateTime.of(now, ZoneId.of("Europe/Paris"));

zonedDateTime.getOffset(); // +02:00

// 手动调整的二月份,此时没有DST,偏移量是+1

ZonedDateTime thirdMonth = zonedDateTime.minusMonths(3);

thirdMonth.getOffset(); // +01:00

OffsetDateTime

OffsetDateTime odt = OffsetDateTime.now();

ZoneOffset zoneOffset = odt.getOffset();

odt.toString(); // 2020-05-31T23:59:24.753+08:00

zoneOffset.toString(); // +08:00

now方法其实隐含应用了jvm当前的默认时区。我的建议是 应该永远显式的指定你需要的时区,即便你就是要获取当前的默认时区。这么做的目的就是明确代码的意图,从而消除模棱两可的不确定性,比如代码到底是要获取默认时区还是写代码的人忘记考虑了时区的因素,这种情况在代码里是经常发生的。默认时区可以通过调用 ZoneId.systemDefault获取。

OffsetDateTime odt = OffsetDateTime.now(ZoneId.systemDefault());

ZoneOffset zoneOffset = odt.getOffset();

ZoneId.systemDefault().toString(); // Asia/Shanghai

odt.toString(); // 2020-05-31T23:59:24.753+08:00

zoneOffset.toString(); // +08:00

注意,如果代码依赖了jvm的默认时区则需要小心,因为jvm中的任何一个线程都可以随时更改时区。如果时区对于代码十分重要,建议保存用户的时区到Session或者持久化存储,以便代码行为的统一性。

同时,你也可以通过偏移量获取以秒为单位的偏移秒数。

int offsetSeconds = zoneOffset.getTotalSeconds();

offsetSeconds; // 28800

ZonedDateTime

另外一个例子:也许你想知道今年圣诞节的时候的Québec(魁北克)偏移量是多少。定义一个America/Montreal的时区,获取ZonedDateTime,然后通过ZonedDateTime获取对应的UTC偏移对象ZoneOffset.

ZoneId z = ZoneId.of( "America/Montreal" );

LocalDate ld = LocalDate.of(2020, 12, 25);

ZonedDateTime zdtXmas = ld.atStartOfDay(z);

ZoneOffset zoneOffsetXmas = zdtXmas.getOffset();

zdtXmas.toString(); // 2020-12-25T00:00-05:00[America/Montreal]

zoneOffsetXmas.toString(); // -05:00

zoneOffsetXmas.getTotalSeconds(); // -18000

ZoneId

正如yanys在评论中所提到的,你可以通过给ZoneId传递一个时刻Instant来获取对应的偏移量。 Instant 类代表UTC的时间轴上的一个时刻,可以精确到纳秒级别(nanoseconds,可以达到小数点后九位)。

这是获取偏移量的另外一种方式。就像在OffsetDateTime和ZonedDateTime中讨论的一样,我们可以定义一个时区,然后通过一个时刻来获取偏移量。

Instant instant = zdtXmas.toInstant();

ZoneOffset zo = z.getRules().getOffset( instant );

For ZoneId: America/Montreal at instant: 2020-12-25T05:00:00Z the ZoneOffset is: -05:00

ZoneOffset.systemDefault – Bug还是特性?

ZoneOffset 类, 是 ZoneId的一个子类, 通过继承,拥有父类的 systemDefault 方法。然而,实际上它并不能按照预期工作.

// 编译失败

ZoneOffset zoneOffset = ZoneOffset.systemDefault();

error: incompatible types: ZoneId cannot be converted to ZoneOffset

不确定这个编译失败是bug还是特性。如同上文所提到的,脱离日期时间获取默认的偏移量没有意义。所以也许 ZoneOffset.systemDefault 确实需要失败,但是也应该在文档中提到或者提供详细的解释。

我尝试提交一个关于这个问题的bug,最后还是放弃了,因为我不知道在哪里如何提交这样一个bug报告。

java zone_offset_java 的 ZoneOffset 与 ZoneId相关推荐

  1. java时区时间ZoneOffset, ZoneId,OffsetTime,OffsetDateTime,ZonedDateTime

    前言 ZoneOffset,LocalDateTime,LocalTime, YearMonth, Year, MonthDay,它们代表与上下文相结合的本地日期/时间.这些类主要用于不需要在上下文中 ...

  2. java zoneoffset_Java 8:如何从ZoneOffset派生ZoneId

    这里有两个问题需要回答 1)第一种正确的语法是什么? 就是这个: ZoneId z; z = ZoneId.of("Z"); //for UTC z = ZoneId.of(&qu ...

  3. java 日本时区_java时区时间ZoneOffset, ZoneId,OffsetTime,OffsetDateTi

    前言 ZoneOffset,LocalDateTime,LocalTime, YearMonth, Year, MonthDay,它们代表与上下文相结合的本地日期/时间.这些类主要用于不需要在上下文中 ...

  4. java zoneid 中国_关于时区:Java 8 Time API – ZonedDateTime – 在解析时指定默认的ZoneId...

    我正在尝试编写一个泛型方法来返回ZonedDateTime给定日期为String及其格式. 如果String未在日期String中指定,我们如何使ZonedDateTime使用默认ZoneId? 它可 ...

  5. 高级JAVA开发必备技能:java8 新日期时间API((一)JSR-310:ZoneId 时区和偏移量)(JAVA 小虚竹)

    技术活,该赏 点赞再看,养成习惯 大家好,我是小虚竹.之前有粉丝私聊我,问能不能把JAVA8 新的日期时间API(JSR-310)知识点梳理出来.答案是肯定的,谁让我宠粉呢.由于内容偏多(超十万字了) ...

  6. 死磕18个Java 8的日期处理,工作必用!

    作者 | Wayfreem 来源 | https://segmentfault.com/a/1190000012922933 简介 伴随 lambda表达式.streams 以及一系列小优化,Java ...

  7. java calendar类_2020 年,你还在使用 Java 中的 SimpleDateFormat 吗?

    今天我和大家一起聊一聊SimpleDateFormat ,这都2020年了,怎么还在用SimpleDateFormat ? 其实,作为一名Java 程序员,我们会经常在编程时候和时间打交道,比如要把某 ...

  8. 死磕 Java 8 的日期处理

    TIME Java 8 推出了全新的日期时间API并且已经很久了,因为业务中遇到的时间处理的还是不多,因此用的也少,而且大多是用封装好的时间共计包,就更少接触java8 的时间类型API了,因此对他不 ...

  9. 2020 年,你还在使用 Java 中的 SimpleDateFormat 吗?

    作者 | 阿文 责编 | 屠敏 出品 | CSDN(ID:CSDNnews) 今天我和大家一起聊一聊SimpleDateFormat ,这都2020年了,怎么还在用SimpleDateFormat ? ...

最新文章

  1. gimp 去掉一个颜色的背景_不用背景图,PPT也能做的高大上?网友:看完这页PPT,我信了...
  2. python需要php吗-做网站用php还是python
  3. 修改/etc/sudoers权限后的补救方法
  4. leetcode-有效的括号(三种语言不同思路)
  5. LVITEM结构-列表视图控件的一个数据结构
  6. 隐私安全的必答题,网易云信如何解?
  7. POJ 1062.昂贵的聘礼
  8. Insyde uefi 隐藏设置_安卓福利,手机桌面图标隐藏,找应用按字母轻松搞定!
  9. LeetCode 355. 设计推特(哈希map+set)
  10. codis codis-ha主从切换后服务器标记为offline
  11. 使用java9的uuid生成方式,让uuid生成速度提升一个档次
  12. java set 的使用_Java中Set集合的使用
  13. 【尚硅谷】JavaScript基础实战丨JS入门到精通_01-06
  14. rda分析怎么做_PCA、PCoA、NMDS 、RDA和CCA等排序分析方法
  15. Android 蓝牙强度Rssi
  16. 一到放假就稀里糊涂过
  17. java parser .java_Stanford Parser使用之 Eclipse+java调用
  18. 业余时间决定了你的人生
  19. 每天实现一个小特效:百度新闻导航栏特效
  20. 蜘蛛爬行html语言的顺序,搜索引擎蜘蛛爬行的规律是什么?

热门文章

  1. 天津计算机软件工程学院,天津市软件学院是几本
  2. 基于 钉钉认证 通过 华为、H3C 结合 OpenPortal认证计费系统 实现 网络准入 钉钉授权 实名认证
  3. PS示例教程:如何用Photoshop打磨质感水晶风格图标
  4. android获取手机的国家码
  5. 局域网是计算机硬件和什么结合的,2017年计算机硬件知识备考试题及答案
  6. linux ccid驱动下载,ccid驱动支持
  7. win10设备管理没有android,win10无法识别安卓手机usb设备怎么办_win10连接安卓设备无法识别的修复方法-爱纯净...
  8. 哪些地方需要使用到301转向
  9. 实现全站http到https的301转向(实测有用)
  10. 为原型产品推荐的四款设计工具