范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

时区的坑,不想再踩了

  原创:打码日记(微信公众号ID:codelogs),欢迎分享,转载请保留出处。   简介
  最近在使用date命令时,发现表示东8区(中国时区)要使用 GMT-8 ,但在Java中却需要使用GMT+8 ,如下: $ TZ="GMT-8" date -d@1647658144 +"%F %T %:z" 2022-03-19 10:49:04 +08:00  # 如果用GMT+8,反而慢了16小时 $ TZ="GMT+8" date -d@1647658144 +"%F %T %:z" 2022-03-18 18:49:04 -08:00
  而在Java中,如下:  DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss XXX"); String dateStr = dtf.format(Instant.ofEpochSecond(1647658144).atZone(ZoneId.of("GMT+8"))); System.out.println(dateStr); //输出2022-03-19 10:49:04 +08:00
  这就让人有点迷糊了,经过一段时间搜索,发现在时区表达形式上还有不少知识点呢!  时区的偏移量表示法
  众所周知,为了方便各地区本地时间之间的转换,人们将全球划分为了24个时区,以格林尼治天文台(GMT)为零时区,往东西两个方向分别有12个时区,所以自然有了以GMT为前缀的时区表示法,如下:
  GMT+8 表示东8区,中国就是使用这个时区,而GMT-8 表示西8区,如果格林尼治天文台的本地时间是2022-03-19的0点,那么GMT+8 地区的本地时间就是2022-03-19的8点,而GMT-8 的本地时间就是往前8小时,即2022-03-18的16点。
  注意,上面的各地区本地时间的表述虽然不同,但它们实际是同一个时刻(绝对时间),要理解本地时间与绝对时间的区别。
  GMT+8 正是Java中支持的时区表示法,那为啥Linux中却是GMT-8 呢?实际上Linux中的GMT-8 也可以写成Etc/GMT-8 ,这才是它的标准名称,如下: $ TZ="Etc/GMT-8" date -d@1647658144 -Is 2022-03-19T10:49:04+08:00DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss XXX"); String dateStr = dtf.format(Instant.ofEpochSecond(1647658144).atZone(ZoneId.of("Etc/GMT-8"))); System.out.println(dateStr); //输出2022-03-19 10:49:04 +08:00
  可以发现用 Etc/GMT-8 的话,Linux与Java的输出都是一样的了,是的,Etc/GMT-8 也是一种类似GMT+8 的时区表示机制,只不过它的+- 号是反的。
  Ok,虽然上面的差异弄清楚了,但时区的表示形式还没有介绍完,接着往下看...
  除了 GMT+8 表示方式外,我们还经常会看到UTC+8 这样的表示方式,这是UTC时区表示法。
  即生GMT何生UTC?这是由于GMT是以格林尼治天文台为时间基准,但地球不是完美球体且自转速度在变慢,所以地球自转速度并不均匀,这导致以格林尼治天文台为时间基准是不准的。
  为了更准确度量时间,科学家们发明了UTC时间,以铯原子跃迁次数来度量时间,比GMT时间更准确,为了保证GMT的准确性,每隔几年GMT时间会做一次调整,以与UTC时间对齐。
  因此,既然有了更准确的UTC,那么就有了以UTC为前缀的时区表示法,如中国时区可使用 UTC+8 。
  各时区偏移量表示法一览表,如下:
  偏移量表示法
  描述
  GMT+8
  相对GMT多8个小时
  Etc/GMT-8
  同GMT+8,+-号相反
  UTC+8
  同GMT+8
  GMT+08:00
  精确到分钟级别
  GMT+08:00:00
  精确到秒级别
  GMT+0800
  精确到分钟级别,省略冒号
  GMT+080000
  精确到秒级别,省略冒号
  +08:00
  精确到分钟级别,省略前缀
  +08:00:00
  精确到秒级别,省略前缀
  +0800
  精确到分钟级别,省略前缀与冒号
  +080000
  精确到秒级别,省略前缀与冒号
  Z
  表示零时区,等同于GMT、UTC、GMT+0、UTC+0   时区的区域表示法
  除了用偏移量来表示时区,为了方便,人们还按区域/城市的方式来定义时区,如 Asia/Shanghai ,Asia/Hong_Kong 都表示东8区,具体有哪些城市命名的时区,可以在时区数据库中查看。
  另外,为了简化区域时区表示法,又定义了一套时区缩写,如CST是中国时区 China Standard Time 的缩写,可以在时区缩写中查看各种缩写定义。
  注意,一般都不建议使用时区缩写,因为时区缩写的命名经常会重复,比如CST是 Central Standard Time (北美中部标准时间UTC -6)、China Standard Time (中国标准时间UTC +8)、Cuba Standard Time (古巴标准时间UTC -5)。
  由于不同软件对CST的解释可能不同,导致会出现时间相差13或14个小时的情况,这在Java搭配MySQL时经常出现,我还专门写了一篇文章mysql的timestamp会存在时区问题?,对于一定要使用时区缩写的场景,可以使用香港时区缩写 HKT ,它不重复且和上海处于同一个时区。
  区域表示法
  描述
  Asia/Shanghai
  上海时区,即东8区
  CST
  时区缩写,慎用   Java中表示时区
  在Java中和时区相关的类有TimeZone、ZoneId,其中TimeZone是老的时区类,而ZoneId是新的时区类,它有ZoneOffset和ZoneRegion两个子类,分别代表偏移量表示法和区域表示法。
  那它们都支持上述的哪些时区写法呢?写个Demo验证一下,如下:  public static void main(String[] args) {        printZoneId("+08:00");        printZoneId("+0800");        printZoneId("GMT+8");        printZoneId("Etc/GMT-8");        printZoneId("UTC+8");        printZoneId("Asia/Shanghai");        printZoneId("CST");        printZoneId("Z"); }  public static void printZoneId(String zone){    ZoneId zoneId;    if(!ZoneId.SHORT_IDS.containsKey(zone)){     	zoneId = ZoneId.of(zone);    }else{     	zoneId = ZoneId.of(ZoneId.SHORT_IDS.get(zone));    }    TimeZone timeZone = TimeZone.getTimeZone(zone);    ZoneOffset zoneOffset = zoneId.getRules().getOffset(Instant.now());    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("xxx ZZZ O OOOO");    System.out.printf("%-14s -> %-28s -> class:%s -> TimeZone.offset:%d  ", zone, dtf.format(zoneOffset),      zoneId.getClass().getSimpleName(), timeZone.getRawOffset()); }
  输出如下:  +08:00              -> +08:00 +0800 GMT+8 GMT+08:00 -> class:ZoneOffset -> TimeZone.offset:0  +0800               -> +08:00 +0800 GMT+8 GMT+08:00 -> class:ZoneOffset -> TimeZone.offset:0  GMT+8             -> +08:00 +0800 GMT+8 GMT+08:00 -> class:ZoneRegion -> TimeZone.offset:28800000  Etc/GMT-8        -> +08:00 +0800 GMT+8 GMT+08:00 -> class:ZoneRegion -> TimeZone.offset:28800000  UTC+8              -> +08:00 +0800 GMT+8 GMT+08:00 -> class:ZoneRegion -> TimeZone.offset:0  Asia/Shanghai  -> +08:00 +0800 GMT+8 GMT+08:00 -> class:ZoneRegion -> TimeZone.offset:28800000  CST                   -> -05:00 -0500 GMT-5 GMT-05:00 -> class:ZoneRegion -> TimeZone.offset:-21600000  Z                       -> +00:00 +0000 GMT GMT         -> class:ZoneOffset -> TimeZone.offset:0
  时区写法
  ZoneId
  TimeZone
  +08:00
  支持
  不支持
  +0800
  支持
  不支持
  GMT+8
  支持
  支持
  Etc/GMT-8
  支持
  支持
  UTC+8
  支持
  不支持
  Asia/Shanghai
  支持
  支持
  CST
  支持,代表北美西部时间,非中国标准时间
  支持,代表北美西部时间,非中国标准时间
  Z
  支持
  支持   偏移量表示法与区域表示法区别
  虽然偏移量表示法与区域表示法都可以表示时区,但由于夏令时的存在,它们并不完全等同。
  夏令时(Daylight Saving Time: DST),也叫 夏时制,是指为了节约能源,在天亮的早的夏季,人为将时间调快一小时,以充分利用光照资源,节约照明用电。
  而中国在 1986 年至 1991 年也实行过夏令时,在1986~1991的每年从四月中旬第一个星期日的凌晨2时整(北京时间),将时钟拨快一小时,即将表针由2时拨至3时,夏令时开始;到九月中旬第一个星期日的凌晨2时整(北京夏令时),再将时钟拨回一小时,即将表针由2时拨至1时,夏令时结束。从1986年到1991年的六个年度,除1986年因是实行夏时制的第一年,从5月4日开始到9月14日结束外,其它年份均按规定的时段施行。
  故会有下面看起来有点奇怪的现象:  DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss VV"); Instant instant = Instant.ofEpochSecond(515527200); System.out.println(dtf.format(instant.atZone(ZoneId.of("Asia/Shanghai")))); //输出1986-05-04 03:00:00 Asia/Shanghai System.out.println(dtf.format(instant.atZone(ZoneId.of("GMT+8")))); //输出1986-05-04 02:00:00 GMT+08:00
  为什么 Asia/Shanghai 输出为3点,而GMT+8 输出为2点呢?原因是1986-05-04 02:00:00 这个时间点中国正开始实行夏令时,时钟拨快了1小时。
  而 GMT+8 为什么输出为2点呢?因为中国、马来西亚、菲律宾、新加坡的时区都是GMT+8 ,只有中国在实行夏令时,而在GMT+8 中没法感知到区域信息,那java只能以没有实行夏令时的方法来计算本地时间了。 夏令时导致的奇怪现象
  正是由于夏令时的存在,导致程序可能出现诡异的现象甚至bug,如下:  由于夏令时会将2点改成3点,导致2点没了,所以date命令报错了  $ TZ="Asia/Shanghai" date -d 1986-05-04T02:00:00 +%s date: invalid date ‘1986-05-04T02:00:00’  $ TZ="Asia/Shanghai" date -d 1986-05-04T03:00:00 +%s 515527200时间解析后再格式化输出,发现不一样了  DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss VV"); ZonedDateTime time1 = ZonedDateTime.parse("1986-05-04 02:00:00 Asia/Shanghai", dtf); System.out.println(time1.format(dtf)); //输出1986-05-04 03:00:00 Asia/Shanghai时间加1小时,发现加了2小时或根本没变  public static void main(String[] args) {    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss VV");    //加1小时刚好夏令时开始    ZonedDateTime time1 = ZonedDateTime.parse("1986-05-04 01:00:00 Asia/Shanghai", dtf);    printZonedDateTime(time1);    printZonedDateTime(time1.plusHours(1));     //加1小时刚好夏令时结束    ZonedDateTime time2 = ZonedDateTime.parse("1986-09-14 01:00:00 Asia/Shanghai", dtf);    printZonedDateTime(time2);          printZonedDateTime(time2.plusHours(1));    }  private static void printZonedDateTime(ZonedDateTime time){    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss VV");    System.out.println(time.format(dtf)); }
  输出如下:  1986-05-04 01:00:00 Asia/Shanghai 1986-05-04 03:00:00 Asia/Shanghai  //加1小时,结果看起来加了2个小时 1986-09-14 01:00:00 Asia/Shanghai 1986-09-14 01:00:00 Asia/Shanghai  //加1小时,结果时间看起来没变
  为啥会这样呢?原因是本地时间虽然看起来没变,但 Asia/Shanghai 这个代表的时区却发生了变化。
  我们可以将上面 printZonedDateTime 中时间格式由yyyy-MM-dd HH:mm:ss VV 修改为yyyy-MM-dd HH:mm:ss VV xxx 再执行,发现输出如下: 1986-05-04 01:00:00 Asia/Shanghai +08:00 1986-05-04 03:00:00 Asia/Shanghai +09:00 1986-09-14 01:00:00 Asia/Shanghai +09:00 1986-09-14 01:00:00 Asia/Shanghai +08:00
  如上,夏令时导致 Asia/Shanghai 这个时区不一定是东8区了,也可能是东9区,故Java中,想将ZoneRegion转换为ZoneOffset,需要传递一个instant时刻参数,如下: //输出+08:00 Instant instant = Instant.now(); System.out.println(ZoneId.of("Asia/Shanghai").getRules().getOffset(instant)); //输出+09:00,在1986-05-04 02:00:00 +08:00处于夏令时,增加了1小时 Instant instant = Instant.ofEpochSecond(515527200); System.out.println(ZoneId.of("Asia/Shanghai").getRules().getOffset(instant));
  夏令时真是一种自欺欺人的做法,还好中国从1991年后就没再实行了!

iPhone13消息汇总,没有太大的期待,那到底香不香?随着时间的推移,很多骨灰级iPhone6s的用户不在少数,期待着iPhone13的到来!正好最近关于iPhone13爆料的信息挺多的,浩南给大家做个总结,并且分享一些自己的观点。外iPhone13最新消息!mini系列或成绝版,小屏手机为何没有市场?要说苹果今年上半年推出的重磅产品,那一定非iPhone12系列莫属了。iPhone12系列共有iPhone12miniiPhone12和iPhone12ProiPhone12Pro百元级蓝牙耳机评测低价未必低质四麦通话降噪不怕大风吹蓝牙耳机在我们的生活中已经越来越不可或缺,无论是通勤乘车健身运动还是驾车出行,都需要有一个蓝牙耳机。那么如何选择一个入门级别的蓝牙耳机呢?真的是只是越便宜越好吗?错!入门可不是廉价台积电将推进3nm工艺,首批面向苹果和Intel,iPad将是首发搭载7月7日,据外媒报道,台积电芯片代工厂将于明年如期推进3nm工艺技术的量产。也有消息称,台积电为此制程准备了4波产能,第一波产能。其中大部分将保留给苹果的长期大客户。相信大家也知道iPhone13或将支持反向无线充,网友续航问题解决了?点击右上方关注,第一时间获取科技资讯技能攻略产品体验,私信我回复01,送你一份玩机技能大礼包。3年前,华为在上海东方体育中心召开了新品发布会,正式推出了具有里程碑意义的Mate20vivoS10系列新机将于7月15日发布中证网讯(记者张兴旺)7月8日,vivo官方微博发布了S10系列新机代言人海报和预热视频,官宣发布会定档于7月15日。据悉,vivoS系列一直定位年轻潮流。此次S10同样采用了渐变vivoS10系列官宣7月15日发布7月8日消息,今天vivo官方宣布将于7月15日发布全新的S10系列手机,同时还公布蔡徐坤刘昊然LISA为S10系列新机的代言人。从vivo官方预热海报以及官网上已经放出的渲染图来从4599跌至2699,曲面屏12256G,骁龙865低调离场来到下半年之后手机市场即将迎来新一轮的竞争,各大厂商的年度旗舰蓄势待发,骁龙888Plus相信会是标配,而现在骁龙888和骁龙870都有着不同程度的降价,更不用说去年发布的骁龙86深夜手机党,都在玩什么?城市楼宇的灯被一盏盏熄灭,深夜的动物们悄悄出动,他们刚从文山会海中挣脱,又一头钻进了手机密织的网里,即使加班到晚上11点,第二天还有考试要战,不玩会儿手机就睡是不可能的!他们有一个来自老雷给年轻人的第二个教训,售价高达9999的小米proX15笔记本发了这么多篇文章都没见着粉丝数有增加,本喵快撑不下去了想要吃饭的嘛!(还没吃到)深圳是真的热啊,晒着晒着突然一场小雨然后继续大太阳,一股水煎包的气息。很痛苦深圳外面很晒,太阳很亮,手机长成什么样才能获得年轻人关注?vivoS9做出了示范了解智能手机市场的人都知道,现如今大多数年轻人在选购手机时往往对于颜值设计非常的注重,只有那些设计精致配色时尚的手机才能获得年轻人们的青睐。而在目前的手机市场上,轻薄自拍旗舰viv
家庭拖地机哪种好用,追觅智能洗地机拖吸一体拖地机值得购买吗追觅智能洗地机拖吸一体拖地机还是不错的,非常好用,可参考下面对追觅智能洗地机试用点评和感受。关注洗地机很久了,在很多品牌之间摇不定,经过对比最终选择了这款追觅H12。家里有只小奶猫万元以内75英寸电视如何选?看这一台就够了花一万元买一台电视对于普通家庭而言,是不可接受的,那么在万元以内有没有性价比更高的75英寸电视,笔者推荐一台,它的画质表现不在索尼75X90J之下,它就是TCL刚刚推出的miniL手机直播录视频绝配雷蛇魔音海妖BT无线麦克风大家好,我是波导终结者。现在手机拍视频或者直播越来越普遍,胜在小巧便携移动性好,然而想要好一点的收音效果,却又需要专业的麦克风。有线麦克风的话,会影响手机的便携性,容易勾到线,也有拯救过敏人群,让我畅快呼吸米家净化器4Pro实用测评转眼之间就到了五月份,天气也暖和了不少,本以为终于能够开始好好地享受一下生活,没想到生活先给了我一个下马威。作为一个资深鼻炎患者,每年的春季都是我鼻子要过的一道坎,各种各样的花粉和要专业,又要低调兼顾个性Lofree洛斐小翘水泥机械键盘开箱和很多人一样,我入手机械键盘就是从第一次到无数次的过程。现在手头的机械键盘多到可以说已经是到了家里领导开始要管制的程度了,但我对优秀的设计依旧毫无拒绝能力,比如这次顶着压力也要入手墨案电纸书MIX7上手,配备7英寸墨水屏,搭载安卓11开放系统记得读初中时,最大的兴趣就是去图书馆后面随着互联网的发展,我就改为用电脑手机来阅读,现在网络阅读已然成为了大多数人主流的读书方式。但无论是电脑阅读,还是手机阅读,其阅读体验与纸质书石头扫拖机器人T8Plus测评给父母家里配一台很有必要父母年纪大了,再加上腰腿不便,对于家务清洁也越来越力不从心。一直想给父母家里添置一台扫地机器人,既可以解放双手,又能钻到沙发底下这种不易清洁到的角落清扫,感觉非常有必要。但市面上很居家办公有把好的键盘工作效率翻倍杜伽K310机械键盘体验3月1日上海疫情!5月23日北京疫情!而我所在的山东也经历的从4月2日到4月22日,整20天的工厂全封闭生产隔离。而大多数办公行政人员则是进行居家办公,这就意味着该交的报表还得交,玩法丰富声音佳,HIDIZSMM2一动圈一静电耳机体验印象中Hidizs(海帝思)是以便携式播放器起家的,不过在近年来的发展中,除了当家花旦AP80这一枝儿外,也推出了耳机解码耳放(大小尾巴)等系列新品,形成了对音频各领域需求链的基本全球首款i9Evo的轻薄本,华为MateBook16s将办公体验拉满华为MateBook系列作为第三代移动办公的领导者,在行业中一直以出色的智慧化体验著称,深得消费者认可。华为全新一代笔记本MateBook16s作为高性能轻薄本市场的明星产品,再一操纵工业机器人关节具体如何操作?本文手把手教你,赶紧码住今天给大家带来工业机器人手动操纵之关节运动。在上一篇文章中(ABB机器人从入门到精通创建系统(内含软件下载链接)),相信你已经学会了如何从0开始创建机器人的系统,而在成功创建系统之