前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >工作 --多时区下时间的加减怎么做?

工作 --多时区下时间的加减怎么做?

作者头像
屈定
发布2020-02-10 17:14:37
1.5K0
发布2020-02-10 17:14:37
举报
文章被收录于专栏:屈定‘s Blog屈定‘s Blog

国际业务往往比国内业务复杂很多,其中一点就是多时区,洛杉矶时间2019.11.3号,正值夏令时切换时踩了一把坑,该篇文章记录下问题,并给出多时区下时间操作比较合理的做法。

问题简介

背景

由于线上服务器采用的都是America/Los_Angeles时区,因此会涉及夏令时,夏令时的意思是在2019-11-3 02:00:00时会回拨1小时到2019-11-3 01:00:00,然后时钟继续,相当于当天会有25个小时,那么夏令时会带来哪些问题?

  1. 字符串时间无法反向转换为精确时间,比如 2019-11-3 01:30:00就无法转换为一个具体的unix timestamp,因为无法确定该时间点位于回拨前还是回拨后。
  2. 这一天不再是24小时,由于时间回拨了1小时,针对Los_Angeles这一天实际上有25个小时。 这两点是导致本次问题的原因。

问题

问题复现代码如下所示,执行时需要把本地时间调整为America/Los_Angeles

代码语言:javascript
复制
/**
 * 错误的示例
 * 本地时间为LA时区
 */
@Test
public void test() throws ParseException {
    // 字符串一般都隐含时区问题,这里假定这个字符串为GMT+8时区        
    String gmt8Date = "20191104";

    // 得到东八区下该时间戳,此时时间戳对应的为东八区 2019-11-04 00:00:00
    FastDateFormat ymd = FastDateFormat.getInstance("yyyyMMdd", TimeZone.getTimeZone("GMT+8"));
    Date gmtDateInstance = ymd.parse(gmt8Date);
    
    // 时间减一,此时会受到本地时间影响, LA时区下20191103这一天有25个小时
    Date date = DateUtils.addDays(gmtDateInstance, -1);
    
    // format出来结果为20191102
    String preDate = ymd.format(date);
}

问题的本质原因是我们大多数时候默认一天有24个小时,然而夏令时切换当天一天有25个小时,同样冬令时切换当天,一天会有23个小时,而出现问题的代码是DateUtils.addDays(gmtDateInstance, -1),减1天,需要判断当前一天到底多少个小时,而Apache的该工具类默认使用了本地时区来判断,导致这里实际上减了25个小时,因此再转到东八区时间为2019-11-02 23:00:00,也就是结果中的20191102

解决方案

找到原因了,自然很好解决,时间的加减需要感知到具体时区信息,解决方案是使用JDK8的ZoneDateTime。

代码语言:javascript
复制
public Date addDay(Date date, int day) {
    Instant instant = ZonedDateTime.ofInstant(date.toInstant(), this.pattern.getZone())
        .plusDays(day)
        .toInstant();
    return new Date(instant.toEpochMilli());
}

ZoneDateTime在构建时已经包含了时区信息,因此加减会根据当前时间来判断具体的变化值。更多的代码可以参开我Github:DateFormat.java

JDK8已经相当普及,其增加的java.time相当优秀,新代码建议应该抛弃掉Date类,转抱Java8 Time,顺便这里分享下个人的Java8 Time笔记,希望对你有帮助.

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-12-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 问题简介
    • 背景
      • 问题
        • 解决方案
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档