关于时区:时区的坑别再踩了
原创:打码日记(微信公众号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 -Is2022-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+8GMT+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验证一下,如下: ...