System.currentTimeMillis() 是不是返回 UTC 时间?

Posted

技术标签:

【中文标题】System.currentTimeMillis() 是不是返回 UTC 时间?【英文标题】:does System.currentTimeMillis() return UTC time?System.currentTimeMillis() 是否返回 UTC 时间? 【发布时间】:2013-06-20 16:45:07 【问题描述】:

我想以毫秒为单位获取当前的 UTC 时间。我搜索了谷歌并得到了一些 System.currentTimeMillis() 确实返回 UTC 时间的答案。但事实并非如此。如果我执行以下操作:

long t1 = System.currentTimeMillis();
long t2 = new Date().getTime();
long t3 = Calendar.getInstance().getTimeInMillis();

所有三个时间几乎相同(由于调用,差异以毫秒为单位)。

t1 = 1372060916
t2 = 1372060917
t3 = 1372060918

这个时间不是 UTC 时间,而是我的时区时间。如何在android中获取当前的UTC时间?

【问题讨论】:

返回自 1970 年 1 月 1 日 00:00:00 UTC 以来的当前系统时间(以毫秒为单位) docs.oracle.com/javase/1.4.2/docs/api/java/lang/… long t3 = Calendar.getInstance(TimeZone.getTimeZone("UTC")).getTimeInMillis(); 以上链接显示“请参阅类 Date 的描述,以讨论“计算机时间”和协调世界时 (UTC) 之间可能出现的细微差异。”在 java.util.Date 文档中,您会发现:“虽然 Date 类旨在反映协调世界时 (UTC),但它可能并不完全如此,具体取决于 Java 虚拟机的主机环境”-> 所以它可能您的机器可能返回非 UTC 时间 @g.revolution:它是“自 1970 年 1 月 1 日 00:00:00 UTC 以来的毫秒数” - 您希望如何针对时区进行调整?您的本地时区不会影响自该纪元以来发生的毫秒数。 【参考方案1】:

您显示的所有三行都将给出自 unix 纪元以来的毫秒数,这是一个固定的时间点,不受您当地时区的影响。

你说“这个时间不是 UTC 时间”——我怀疑你实际上是错误地诊断出来的。我建议为此使用epochconverter.com。例如,在您的示例中:

1372060916 = Mon, 24 Jun 2013 08:01:56 GMT

我们不知道您何时生成该值,但除非它实际上是在世界标准时间上午 8:01,否则这是您的系统时钟问题。

System.currentTimeMillisDate 本身的值都不受时区影响。但是,您应该知道 Date.toString() 确实 使用本地时区,这会误导许多开发人员认为 Date 与时区固有地相关联 - 它不是,它只是一个瞬间及时,没有关联的时区甚至日历系统。

【讨论】:

所以基本上,也就是说,如果在不同的时区同时调用这个函数,不管主机的时钟如何,这个函数都会返回相同的值,对吗? 伙计,这让我希望世界能够(可以)采用单一时区。谁会在乎时钟上的数字是 00:00 还是 08:00 当天空中出现大亮的东西时?在这个历史遗迹上浪费了无数小时的生产时间,这让我热血沸腾...... 与此相关,请注意对 OS 时钟函数的底层调用具有几毫秒的记录“漂移”。如果目的是获得高度精确的操作持续时间(任务开始和完成的时间,增量是经过的时间量),Java 有一个“高性能计时器”。见:docs.oracle.com/javase/7/docs/api/java/lang/… @JonSkeet 如果 toString() 内部使用时区,我如何在没有时区的情况下从它构建字符串。实际上,我正在 REST 服务器中生成文件,该文件的文件名正好是午夜时间值前“1551139200.json”(2019 年 2 月 26 日上午 12:00:00),并且需要在设备的 System.currentTimeMillis() 后从 android 应用程序访问返回准确的时间。 @kiranking:使用Date.getTime() 查找自Unix 纪元以来的毫秒时间,除以1000(因为该文件名是自Unix纪元以来的)和只需将该整数格式化为字符串。【参考方案2】:

我可以确认所有三个调用可能取决于本地时间,考虑到时代,而不是 Date.toString() 或任何类似的方法。我已经看到它们依赖于运行 Android 2.3 的特定设备中的本地时间。我没有用其他设备和安卓版本测试过它们。在这种情况下,本地时间是手动设置的。

获得独立 UTC 时间的唯一可靠方法是使用 GPS_PROVIDER 请求位置更新。从NETWORK_PROVIDER 检索到的位置的getTime() 值也取决于本地时间。例如,另一个选项是 ping 一个返回 UTC 时间戳的服务器。

所以,我要做的是:

public static String getUTCstring(Location location) 
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
    String date = sdf.format(new Date(location.getTime()));
    // Append the string "UTC" to the date
    if(!date.contains("UTC")) 
        date += " UTC";
    
    return date;

【讨论】:

System.currentTimeMillis() 返回一个基于 UTC 的值。至于操作系统时钟的“精度”或准确性,虽然这肯定会影响结果,但与系统或Java环境时区值没有任何关系。 @DarrellTeague 我坚持认为,我在特定的华为设备中看到了不同的值。所以不,它并不总是返回正确的 UTC 时间(丢弃精度差异) OP 的问题是关于 Java 类时区的使用。这与硬件或返回时间值的准确性无关。简而言之,JVM 从(抽象的)操作系统“系统时钟”(其功能因操作系统而异)中获取时间。另请参阅:drdobbs.com/embedded-systems/… 和操作系统上的“C”实现chemie.fu-berlin.de/chemnet/use/info/libc/libc_17.html

以上是关于System.currentTimeMillis() 是不是返回 UTC 时间?的主要内容,如果未能解决你的问题,请参考以下文章

System.currentTimeMillis() 是不是返回 UTC 时间?

给定日期的 System.currentTimeMillis()? [复制]

System.nanoTime()和System.currentTimeMillis()性能问题

System.currentTimeMillis()

System.currentTimeMillis() uptimeMillis() elapsedRealtime() 区别

System.currentTimeMillis()和new Date().getTime()比较