`

转 java中System.currentTimeMillis与夏令时

 
阅读更多

这段正好有个故障,涉及到JAVA程序在向过去调整时间之后,系统出现的一些异常现象。手工通过系统程序时间日期管理器调整系统的时间、日期,发现Java用Timer、TimerTask框架实现的定时器机制,发现在时间被调整,特别往后面调整不断时间(几分钟粒度),就会发现定时器任务被延迟了。

当时,对这种大规模向过去调整时间的行为,本来不想修改,因为大规模向后调整时间,毕竟是一个非常非常异常的行为。但是,在讨论故障时有同事提到如果遇到夏令时的时间调整怎么办?看来他还是很有大局观的,我们系统确实需要应对夏令时。时间在夏令时进入的时候,时间会向将来调整,特别地在夏令时退出的时间,时间会向后面调整,照样会存在一个小时的大规模时间调整!!

而我们程序原来是被设计支持夏令时的,至少是程序业务设定某些数据记录时间字段的时间,是支持夏令时。但是,我确实很怀疑定时器,在遇到夏令时机制的时间,是否会出现延迟呢?
对于这个问题,同一个团队的同事,以前开发夏令时功能的,坚持说夏令时机制不会影响定时器。因为夏令时只是一个显示而已,而内部时间不会变,但,我一直很怀疑,一直在做研究。

今天,通过通读JDK1.6.17的源码和JavaDoc发现,我们同事这个说法在一定程度上是对的,也在阅读过程中给自己以理论指导的方向,但还有不足的地方。虽然,这刻,我没还没有验证,但是,直觉准确地告诉我,觉得,自己找到了答案。所以,自己很兴奋地写了这篇博客,也是为了答疑自己不断地在网上搜索,确实没有太大的真实性获得,几乎没有人回答System.currentTimeMillis的意义,也怪自己没有详细看JavaDoc中的说明。不过,就以当时的理解水平,看到也未必能够深入地理解,只有这一刻我觉得理解了。。。。

关于时间,在JavaDoc中谈论比较多文字的是UTC、UT、GMT等

UTC:科学纪年,时间采自原子时钟。在每过一两年会有一个跳秒,在某个跳点,一分钟有61秒
UT: GMT格林威治时间的科学学名,取自天文学观测

从这两种时间的定义,我们发现,从PC和一些机器系统获得所谓的UTC时间实际上是虚假的,因为其根本上就没有那样的设备或这样的tcp访问机制,让其知晓,其依靠的不过是主板上的晶振而已,跟上两种时间的定义有很大的区别。

在UT时间中,有一个特殊的时间,即起点 epoch:, namely January 1, 1970, 00:00:00 GMT. 如果在电脑上手工调整了系统时间,则距离此起点的时间值也会被调整。


夏令时是一种时间调整机制,与时区,特别某些国家所在的时区有很大关系。我们所用Java的Date类的接口中的计算是跟默认的时区有关系,计算的根本算法为现在距离起点时间的milliseconds,然后在根据特殊的时区的设定,包括偏移值,夏令时等,进行相应的计算。所以,说夏令时的进入和退出,仅于跟时区相绑定的计算有关系,例如Date、Calendar等,但是,跟系统距离起点时间的距离没有太大关系。这个时间距离在夏令时进入和退出时确实不会变化,一直是线性地增长的。不过,手工调整未必!特别是针对PC来说,呵呵,还是要强调这一点。

所以,我的结论是,夏令时不会影响定时器的执行,即使时间向后大范围调整。Java中Timer、TimerTask框架是依据 System.currentTimeMillis()进行计算下一次运行时间,这个时间在夏令时生效失效前后,一直是线性增长的,所以不会受到影响。但是,手工调整系统时间,则会遭遇到定时器的缓期执行。

摘一段Java JavaDoc中的文字感谢一些SUN。
Java中currentTimeMillis()方法返还的

* @return the difference, measured in milliseconds, between
* the current time and midnight, January 1, 1970 UTC.
* @see java.util.Date
*/
public static native long currentTimeMillis();


记录一下前一段自己的辛勤劳动,验证结果:

对于时间向过去调整后,由于迷惑,也研究了其他系统一些与时间有关的行为,发现一些有些很有意思的东西,行为不尽相同,特别是不同的系统:

JavaScript:setInerval貌似不受时间调整影响,很准确地以固定间隔运行
VC: WM_Timer事件,不受时间调整影响,但是准确性降低
Java: Timer、TimerTask定时器任务会受到影响,
但是Thread.sleep不会受到影响,很怪异,可能使用的另外一套时间计算方法,例如操作系统的ticks。

分享到:
评论

相关推荐

    高并发场景下 System.currentTimeMillis() 的性能问题

    在Java编程中,System.currentTimeMillis() 是一个常用的方法,用于获取当前时间戳,即自1970年1月1日(UTC/GMT的午夜)以来的毫秒数。然而,在处理大量并发请求时,这个方法可能不再是最佳选择,因为它的性能表现...

    System.currentTimeMillis()计算方式与时间的单位转换详解

    在Java编程中,`System.currentTimeMillis()` 是一个非常重要的方法,用于获取系统当前的日期和时间。这个方法返回的是从1970年1月1日(UTC/GMT的午夜)开始到现在的毫秒数。这是一个长期通用的标准,用于表示时间的...

    Unix时11间戳和Java 的 System.currentTimeMillis()的区别.pdf

    ,Unix时11间戳和Java 的 System.currentTimeMillis()的区别.pdf

    Unix时11间戳和Java 的 System.currentTimeMillis()的区别.docx

    ,Unix时11间戳和Java 的 System.currentTimeMillis()的区别.docx

    Java获取当前系统事件System.currentTimeMillis()方法

    在Java编程语言中,`System.currentTimeMillis()` 是一个非常基础且重要的方法,用于获取当前系统时间。这个方法返回从1970年1月1日0时0分0秒(协调世界时间,UTC)到现在的总毫秒数。这是一个非常常用的函数,尤其...

    System.currentTimeMillis()显示大写字母

    long haomiao = System.currentTimeMillis(); int b = (int)((haomiao/1000)%26+65); char daxiezimu = (char)b; System.out.println(haomiao); System.out.println(daxiezimu); } }

    java.util.Date与java.sql.Date互转及字符串转换为日期时间格式[文].pdf

    Java.util.Date与java.sql.Date的互转及字符串转换为日期时间格式 java.util.Date和java.sql.Date是Java中两个常用的日期时间类,分别属于不同的包。java.util.Date是Java标准库中的日期时间类,而java.sql.Date是...

    android时间戳总结:System.nanoTime(),System.currentTimeMillis(),SystemClock

    System.currentTimeMillis() SystemClock.uptimeMillis() SystemClock.elapsedRealtime() SystemClock.currentThreadTimeMillis 0、时间的单位: 秒:second 毫秒:Millisecond 微妙:Microsecond 纳秒:nanosecond ...

    java.sql.date与java.util.date.pdf

    - 可以通过`System.currentTimeMillis()`获取当前时间的`java.util.Date`实例。 - 使用`SimpleDateFormat`进行日期格式化和解析。 2. **`java.sql.Date`**: - `java.sql.Date` 是专门为处理SQL DATE类型而设计...

    Java中System类.pdf

    Java中System类还提供了许多其他的方法和变量,例如,System.currentTimeMillis()方法可以获取当前时间的毫秒数,System.getProperty()方法可以获取系统的属性信息,等等。 在编程中,System类非常重要,很多应用...

    System.currentTimeMillis() 和 System.nanoTime() 哪个更快?大

    互联网资讯,技术简介,IT、AI技术,人工智能互联网资讯,技术简介,IT、AI技术,人工智能互联网资讯,技术简介,IT、AI技术,人工智能互联网资讯,技术简介,IT、AI技术,人工智能互联网资讯,技术简介,IT、AI技术...

    解决时间戳long转换int溢出(即转换值为负数) long转int

    在Java编程中,时间戳通常用来表示某个时间点距离1970年1月1日00:00:00 UTC的毫秒数。`System.currentTimeMillis()` 方法返回的就是这样的一个long类型的数值。然而,当你需要将这个long类型的时间戳转换为int类型时...

    java 获取系统时间错误,少了8小时

    这通常与Java中的时区设置和夏令时(Daylight Saving Time, DST)处理有关。 Java的`Date`类在默认情况下会按照本地时区(Local Time Zone)展示日期和时间。如果开发者期望获取的是协调世界时间(UTC),但程序却...

    不敢相信?System.currentTimeMillis() 居然存在性能问题.docx

    图文并茂吃透面试题,看完这个,吊打面试官,拿高薪offer!

    java连接数据库.doc

    这篇文档主要针对Java初学者,讲解如何在Java中处理日期时间数据以及与数据库进行交互。 首先,JDK 1.1之后,`java.util.Date`类的多数方法被弃用,推荐使用`java.util.Calendar`类来处理日期和时间。`Calendar`类...

    Java中获取比毫秒更精确的时间.docx

    在Java中,`System.currentTimeMillis()` 是一个常用的获取当前时间(以毫秒为单位)的方法。然而,在实际应用中,可能会遇到使用该方法获取的时间间隔出现异常大的情况,例如在毫秒级别的时间测量中出现16毫秒的大...

    android中几种for循环的效率

    long timenow = System.currentTimeMillis(); for (String str : strs) { count++; } return System.currentTimeMillis() - timenow; } 2.比较慢 private long getTime2() { long time = 0; int...

    【图文】第六章、Java之API.doc

    第六章主要讨论的是Java中的System类,这个类包含了与系统密切相关的各种静态方法,便于开发者进行系统级别的操作。 System类是Java.lang包下的一个核心类,它的主要成员都是静态的,因此可以直接通过类名System来...

    java中 new date() 打印出的时间与系统时间错了八小时的解决方法

    Java使用`java.util.Date`类来表示日期和时间,而`System.currentTimeMillis()`方法返回的是自1970年1月1日00:00:00 GMT以来的毫秒数。`new Date()` 实际上是基于这个毫秒值创建一个日期对象,但它默认使用的是UTC...

    单元测试中PowerMock常用方法.

    例如,你可以模拟`System.currentTimeMillis()`来返回预设的时间值,以便控制测试环境中的时间变化。 2. **构造函数模拟** 对于那些内部依赖于私有或受保护构造函数的类,PowerMock可以创建新的实例,而无需实际...

Global site tag (gtag.js) - Google Analytics