Java时间处理小结

时间:2022-09-03 22:08:13

UTC时间和GMT时间

GMT

格林威治时间,十七世纪,格林威治皇家天文台为了海上霸权的扩张计画而进行天体观测。1675年旧皇家观测所(Old Royal Observatory) 正式成立,到了1884年决定以通过格林威治的子午线作为划分地球东西两半球的经度零度。观测所门口墙上有一个标志24小时的时钟,显示当下的时间,对全球而言,这里所设定的时间是世界时间参考点,全球都以格林威治的时间作为标准来设定时间,这就是我们耳熟能详的「格林威治标准时间」(Greenwich Mean Time,简称G.M.T.)的由来.

UTC

全球通用协调时间(Universal Time Coordinated),是经过平均太阳时(以格林威治时间GMT为准)、地轴运动修正后的新时标以及以「秒」为单位的国际原子时所综合精算而成的时间,计算过程相当严谨精密,因此若以「世界标准时间」的角度来说,UTC比GMT来得更加精准。其误差值必须保持在0.9秒以内,若大于0.9秒则由位于巴黎的国际地球自转事务*局发布闰秒,使UTC与地球自转周期一致。所以基本上UTC的本质强调的是比GMT更为精确的世界时间标准,不过对于现行表款来说,GMT与UTC的功能与精确度是没有差别的。

由于目前的原子钟极其精确,大约50亿年才会相差一秒,所以UTC时间是极其精确的。GMT是根据地球的自转和公转来计算时间,也就是太阳每天经过位于英国伦敦郊区的皇家格林威治天文台的时间就是中午12点,地球公转速度变化都会对其造成影响。

如果不是对时间要求极其严格的场景,UTC和GMT可以看做是一样的。

UTC时间跳秒

前面提到UTC时间极其精确,那么为什么还会跳秒?比如在2015年6月30日的时候,就发生了一次跳秒,即闰秒。还有2012年也发生了一次。为什么会发生的如此频繁?
其实是我们理解错误,不是UTC时间变了,而是GMT时间变化了。GMT为了抵消地球自转发生变化而导致长时间累积出现的时间错误,所以会每隔一段时间执行一次闰秒。
说白了。闰秒的唯一意义就是避免在几万年后GMT时间的正午12:00不是太阳直射0度经度线的时间。

关于夏令时

所谓「夏日节约时间」Daylight Saving Time(简称D.S.T.),是指在夏天太阳升起的比较早时,将时钟拨快一小时,以提早日光的使用,在英国则称为夏令时间(Summer Time)。这个构想于1784年由美国班杰明•富兰克林提出来,1915年德国成为第一个正式实施夏令日光节约时间的国家,以削减灯光照明和耗电开支。自此以后,全球以欧洲和北美为主的约70个国家都引用这个做法。
夏令时和时区相关。

为什么中国夏令时实行了一段时间又取消了

“夏时制”的核心理念,就是充分利用日光照明,减少用电,从而节约能源。夏天日照时间长,在不更改作息时间的前提下,把“时间”提前,可以早早地利用阳光。
我国*几年在部分地区也曾实行过夏令时。1986年4月,*有关部门发出“在全国范围内实行夏时制的通知”,具体作法是:每年从四月中旬第一个星期日的凌晨2时整(北京时间),将时钟拨快一小时,即将表针由2时拨至3时,夏令时开始;到九月中旬第一个星期日的凌晨2时整(北京夏令时),再将时钟拨回一小时,即将表针由2时拨至1时,夏令时结束。从1986年到1991年的六个年度,除1986年因是实行夏时制的第一年,从5月4日开始到9月14日结束外,其它年份均按规定的时段施行。在夏令时开始和结束前几天,新闻媒体均刊登有关部门的通告。1992年起,夏令时暂停实行。
夏令时只在高纬度的地区有用。中国横跨五个时区,全国使用统一的时间,假设上海是早晨6点见到太阳升起,那*西南部要9点才见到太阳升起。在这个客观前提下,中国东西部必然实施不同的作息时间。这时再实行夏时制,中国东西部的作息时间还是各不相同,客观上并不能促成大规模减少用电、节约能源。而且还会导致混乱。
美国夏令时也是根据各州的不同情况自己决定是否使用夏令时的,而且夏令时开始和技术都根据地区不同而有所不同。

Java中的时间类型

Java的System.currentTimeMillis()和date.getTime()返回的都是1970-1-01 00:00:00.000 到现在的UTC时间差。单位精确到毫秒。
看下面例子:

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
sdf.setTimeZone(TimeZone.getTimeZone("GMT+08:00"));
System.out.println(sdf.parse("1970-1-01 00:00:00.000").getTime());//-28800000
System.out.println(sdf.format(new Date()));//2015-09-24 12:20:39.581
System.out.println(sdf.parse(sdf.format(new Date())).getTime());//1443068439582
System.out.println(new Date().getTime());//1443068439582
System.out.println(System.currentTimeMillis());//1443068439582
System.out.println("------------------------");
System.out.println("Change time zone to UTC");
System.out.println("------------------------");
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println(sdf.parse("1970-1-01 00:00:00.000").getTime());//0
System.out.println(new Date(0).getTime());//0

夏令时在Java中只是一个原始时间值的附加计算问题 ,可以获取到具体TimeInMillis到不同的时区去换算,例如GMT+0,就会发现仅是夏令时区域自己显象上的变化,而其他地方没有采用夏令时的地区同一个TimeInMillis换算出来就显出原形,并不是真的隐藏于内部的时间走快了,所以,当时也肯定地指出在夏令时的进入和退出的时间点上,对于使用TimeInMillis作为判断的定时器将不会受到任何影响
一般意义上来说夏令时需要获得系统级的支持,例如2007年美国变更夏令时法则后,linux操作系统都要打相应的补丁才可以运行正常;根据Java Doc和文档库的说明,Java通过最新的JDK和JRE更新达到类似的想过,因为对于Java程序而言,Java JVM就是自己虚拟的操作系统环境;对于已存在的Java环境,可以使用SUN提供的时区数据更新工具进行更新。
正常情况下,JAVA如果辨认的时区和夏令时规则与当前地区一致的话,就可以非常完美地解决夏令时问题,不用其他辅助手段。通过TimeZone.getDefault()发现或 System.getProperty(“user.timezone”)发现当前时区是什么。
例如,美国东部时间纽约实行了夏令时,其格式串为[id=”America/New_York”,offset=-18000000,dstSavings=3600000,useDaylight=true,transitions=235,lastRule=java.util.SimpleTimeZone[id=America/New_York,offset=-18000000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=3,startMonth=2,startDay=8,startDayOfWeek=1,startTime=7200000,startTimeMode=0,endMode=3,endMonth=10,endDay=1,endDayOfWeek=1,endTime=7200000,endTimeMode=0]]。其中startMode和endMode,以及其他相应属性指定了夏令时的规则。一般简单的设定夏令时的某个规则,例如3月份的第二个星期天凌晨2:00等,虽然每年的日期不同,但是,背后的规则和规律是一样的。
在Linux中可以通过TZ环境变量机制和/etc/sysconfig/clock文件配置系统的时区,进而影响Java JVM的初始化。在所研究的系统中,发现在TZ中设置过于复杂的时区数据格式,例如指定了夏令时的进入和退出时间点,则会导致Java JVM初始化时区变得异常。
夏令时和时区的变化不会导致Java定时器发生变化。
但是系统时间跳变会导致定时器失效。原因很简单,一个内部时间没有变化,只是显示发生了变化,另外一个内部时间已经发生了变化。

如何可靠的处理时间类型

存储和显示分离。存储的时候存储UTC时间。显示的时候根据时区不同,做不同的显示。

参考

http://www.zhihu.com/question/27052407
http://www.zhihu.com/question/19573569
http://www.zhihu.com/question/31549640
http://blog.csdn.net/jkler_doyourself/article/details/5202669
http://www.liaoxuefeng.com/article/0014132675721847f569c3514034f099477472c73b5dee2000
http://www.cnblogs.com/mailingfeng/archive/2012/06/20/2556326.html
http://lavasoft.blog.51cto.com/62575/52975
https://getpocket.com/a/read/1050342082