【问题标题】:length of System.currentTimeMillisSystem.currentTimeMillis 的长度
【发布时间】:2012-02-27 06:50:15
【问题描述】:

System.currentTimeMillis 是否总是返回固定长度的值。在我的 Windows Core2 中,它返回一个 13 位长的值。

来自其 API:

以毫秒为单位返回当前时间。请注意,虽然返回值的时间单位是毫秒,但值的粒度取决于底层操作系统并且可能更大。例如,许多操作系统以几十毫秒为单位测量时间。

【问题讨论】:

  • 询问它将包含多少位数字让我觉得这是一个有严重缺陷的问题。该值以纪元以来的毫秒数为单位。您可以根据当前时间计算出位数,但是为什么?!
  • 将你的时间设置为 1970 年,它会更短。
  • System.currentTimeMillis() 返回一个 Java long。它总是正好是 64 位长,并且通常有许多前导零。

标签: java time timer epoch milliseconds


【解决方案1】:

它返回一个 63 位二进制数(它实际上是一个 64 位有符号数,始终为正数,因此最高位永远不会设置)。许多前导数字将为零。将其转换为十进制时,通常会丢弃任何前导零。所以,小数位数会有所不同。

【讨论】:

  • 已签名以便可以存储 1970 年之前的日期
  • 它已签名,因为 Java 中的 long 已签名。但是,如果设计师可以在签名和未签名之间进行选择,那么签名将是一个不错的选择,正是出于这个原因。
  • 是的,这是真的。我实际上是在评论帖子的 ...which is always positive 部分,并指出事实并非如此
  • System.currentTimeMillis() 返回的数字 始终为正数,因为在 1970 年(或者,实际上是 1996 年)之前不可能调用它。除非你有时间机器,或者用你的系统时钟做一些傻事。但是,是的,更一般地说,你说得对,时间可能是负数。
【解决方案2】:

System.currentTimeMillis() 返回自纪元以来的毫秒数,即自 1970 年 1 月 1 日 UTC 午夜以来的毫秒数。

您可以检查自纪元以来的毫秒数首次为 13 位十进制数字。这发生在

2001 年 9 月 9 日 01:46:40.000 UTC(自纪元以来 1'000'000'000'000 毫秒)

您还可以检查自纪元以来的毫秒数最后一次是 13 位十进制数字。这将发生在

2286 年 11 月 20 日 17:46:39.999 UTC(自纪元以来 9'999'999'999'999 毫秒)

因此在这两个日期之间,假设机器的当前时间设置正确,该函数将始终返回 13 位十进制数字值。

因此,假设在接下来的两个世纪中返回值是 13 位十进制数字,您是安全的。

【讨论】:

  • 我想知道有多少开发人员编写过代码来处理 14+ 位 epochs..
  • @ryanbwork 精确地以 毫秒 为单位存储纪元。
  • @ryanbwork 我通过我的运营商看到了很多使用System.currentTimeMillis() 的代码,我不记得有任何对结果的十进制表示中的位数有限制的代码(不是我不明白你的意思)。
【解决方案3】:

most voted answer(即从 2001-09-09T01:46:40 UTC 到 2286-11-20T17:46:39.999 UTC 的任何日期的纪元毫秒数将具有 13 位数字)是准确的。对于任何有兴趣了解如何得出这些数字的人来说,这是对该答案的补充。

通常,我首先使用现代日期时间 API 编写解决方案,但在这种情况下,我将反转模式,因为 java.time,现代日期时间 API 于 2014 年 3 月发布(最晚两年后)投票的答案已发布。

使用旧的日期时间 API:

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

public class Main {
    public static void main(String[] args) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX", Locale.ENGLISH);
        sdf.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
        System.out.println(sdf.format(new Date(1000000000000L))); // 2001-09-09T01:46:40.000Z
        System.out.println(sdf.format(new Date(9999999999999L))); // 2286-11-20T17:46:39.999Z
    }
}

使用现代日期时间 API java.time

import java.time.Instant;

public class Main {
    public static void main(String[] args) {
        System.out.println(Instant.ofEpochMilli(1000000000000L)); // 2001-09-09T01:46:40Z
        System.out.println(Instant.ofEpochMilli(9999999999999L)); // 2286-11-20T17:46:39.999Z
    }
}

输出中的Z 是零时区偏移的timezone designator。它代表 Zulu 并指定 Etc/UTC 时区(其时区偏移量为 +00:00 小时)。

Trail: Date Time了解更多关于java.timemodern date-time API*


* 出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,您可以使用 ThreeTen-Backport,它将大部分 java.time 功能向后移植到 Java 6 和 7 . 如果您正在为一个 Android 项目工作并且您的 Android API 级别仍然不符合 Java-8,请检查 Java 8+ APIs available through desugaringHow to use ThreeTenABP in Android Project

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-24
    • 1970-01-01
    相关资源
    最近更新 更多