彻底搞懂时区

杀死时区

    • 摘要
    • 纪元时间
    • 时间分区
    • 关于时区可能存在的开发问题

摘要

工作五年了,对时区问题一直没有好好研究,一致云里雾里,大概也就知道北京时间是东八区,转成GMT时间要减去八个小时。这个理解。。。额。。。坑很大。

纪元时间

也称为机器时间,又称为绝对时间。此值是一个long类型的时间戳,指的是1970 到现在的毫秒数。 这是个绝对的时间戳。

时间分区

就对时间就是个时间戳,你在世界上任何一台电脑用java : System.currentTimeMillis()获得的时间戳都是一样的。这就是绝对时间。 那么到底和时区什么关系呢?
首先绝对时间只是一个毫秒数,再全世界都是一致的,但是这个long不符合我们人类的阅读习惯,我们希望把它转成字符串的样子,yyyy-mm-dd hh:mm:ss .
这样就有问题了:因为同一个绝对时间点再地球的不同地方对应的白天黑夜是不同的, 为了符合人类的习惯出现了时区。 比如有个十三位的时间戳:xxxxxxxxxxxxx, 走到此时间戳的时候北京刚好生起太阳, 而伦敦则是刚刚到凌晨。 于是人们为了显示方便把xxxxxxxxxxxxx绝对时间再北京显示成:2011-01-01 08:00:00, 再伦敦显示成为:2011-01-01 00:00:00, 这样同一个xxxxxxxxxxxxx时间戳再不同的区域就显示成了不同的样子,更符合人类的阅读习惯。

这就是时间分区,对伦敦时间也就是GMT时间来说,比北京GMT+8:00晚了八个小时,这里有个重大误区,不要把字面晚八个小时认为真的晚了八个小时, 实际上不管是哪个时区绝对时间戳是一模一样的。 所谓的晚了八个小时纯粹指的是人类转化的时间字符串看着晚了八个小时。

所以说可以总结为:全世界绝对时间,时间戳都是一致的, 同样的时间戳再不同的时区显示的字符串不一致。 忠告:在开发时不要把字符串看成时间,应该看成某个时区的显示时间。

关于时区可能存在的开发问题

比如我有个字符串:2022-10-1 00:00:00, 我想把这个字符串转成时间戳(也就是绝对时间),那么可能很常见的用java百分之九十的人都会写下面的代码:

   public static long stringTOTimestamp(String time, String format) {if(format==null||format.equals("")){format="yyyy-MM-dd HH:mm:ss";}SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);long timeStemp = 0;try {Date date = simpleDateFormat.parse(time);timeStemp = date.getTime();} catch (Exception e) {e.printStackTrace();}return timeStemp;}

让我们回到上面的忠告:在开发时不要把字符串看成时间,应该看成某个时区的显示时间。
其实上面的写法是有问题的比如:2022-10-1 00:00:00这是GMT 0时区的显示的时间, 那么你在国内调用上面的方法就会有问题,默认从str-to-timestamp 是使用的本地的时区, 也就意味着转换的时候系统认为2022-10-1 00:00:00 是GMT+8:00 时区显示的时间。这样转换过去就会出问题,你仔细想。。。。
正确的代码是:指出当前字符串所属时区,那就可以正常转换了。理论上来说:GMT 时区的:
2022-10-1 00:00:00 和GMT+8:00即东八区的2022-10-1 08:00:00 转成时间戳绝对时间应该是一致的,经过验证也确实如此,前提要指出时区。

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;public class TimeUntil {public static long stringTOTimestamp(String time, String format,String zone) {if(format==null||format.equals("")){format="yyyy-MM-dd HH:mm:ss";}SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);simpleDateFormat.setTimeZone(TimeZone.getTimeZone(zone));long timeStemp = 0;try {Date date = simpleDateFormat.parse(time);timeStemp = date.getTime();} catch (Exception e) {e.printStackTrace();}return timeStemp;}public static void main(String[] args) {System.out.println(TimeUntil.stringTOTimestamp("2022-10-1 00:00:00",null,"GMT"));//1664582400000System.out.println(TimeUntil.stringTOTimestamp("2022-10-1 08:00:00",null,"GMT+8:00"));//1664611680000}
}


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部