【问题标题】:Unix Time Conversion between Language语言之间的 Unix 时间转换
【发布时间】:2021-05-20 13:42:11
【问题描述】:

我有这个以毫秒为单位的 unix 时间戳: -62135769600000

我尝试使用 java 和 javascript 转换时间戳,但我得到了两个不同的响应。往下看:

Date d = new Date(-62135769600000L);
System.out.println(d); // output = Sat Jan 01 00:00:00 GMT 1
d = new Date(-62135769600000L)
console.log(d) // output = Fri Dec 29 0000 19:00:00 GMT-0500 (EST)

如您所见,我们有两个不同的结果。我想了解原因以及如果可能的话如何解决。

【问题讨论】:

  • 您是否尝试过具有更合理时间戳的代码,例如现在的时间戳,而不是一些奇怪的负值!?
  • Java Date 和 LocalDate 没有时区的概念。您应该考虑迁移到 java LocalDateTime
  • 我建议在 Java 中不要使用java.util.Date。该课程设计不良且早已过时。而是使用来自java.time, the modern Java date and time APIInstant
  • 这可能是Julianproleptic Gregorian 日历之间的区别。 java.util.Date 使用 Julian,我不懂 JavaScript。
  • @OleV.V.是的;每当你用它做愚蠢的事情时, juDate 都会“规范化”为日历(例如,将 epochmillis 转换为人类概念,toString 本身也是如此),并且如果时间戳在硬编码截止之前,规范化代码将使用 julian,这OP 的近 0 年时间戳肯定是。看我的回答。

标签: javascript java unix-timestamp


【解决方案1】:

首先,一个教训:java.util.Date 是愚蠢的、破碎的,永远不应该被使用。在 java 中处理时间的正确方法是使用 java.time 包。

然后,解释您观察到的差异:

  • javascript 通过转换使用公历表示的时刻来报告时间,就像您在美国东部标准时间时区一样。
  • java 的 Date 正在报告时间,就好像它是儒略历一样,并且是 GMT 时区。

时区差异解释了为什么 javascript 打印 19:00 而 java 打印 00:00,以及 1 个日期的差异。当你在 12 月 29 日纽约的 19:00 拍手时,那一刻,正是伦敦的午夜,12 月 30 日。剩下正好 48 小时(2 天)的差异是由于儒略历。

正确的方式,在java中:

Instant i = Instant.ofEpochMilli(-62135769600000L);
System.out.println(i.atZone(ZoneOffset.UTC));
> 0000-12-30T00:00Z

今天常用的日历系统称为公历。它是对罗马时代使用的儒略历的修改。

世界没有在同一天从儒略转换为格里高利。事实上,俄罗斯来得太晚了,直到 1918 年才改变:你在莫斯科买了一份报纸,上面写着“1918 年 1 月 31 日”(但用俄语)。如果你然后跳上一匹马,向西骑行,直到你到达布拉格、柏林或阿姆斯特丹,一夜之间,然后问:嘿,今天是几号?他们会告诉你:现在是 2 月 13 日。

那你第二天骑马回莫斯科买另一份报纸。上面写着“1918 年 2 月 14 日”。 2 月 1 日至 13 日发生了什么? 它们从未存在过。那是俄罗斯转变的时候。

花絮:“十月革命”,指的是沙皇被推翻时,发生在 11 月。俄罗斯,仍然在朱利安,当时发生在十月。世界其他地方使用罗马风格的日历都使用公历,当时他们称之为 11 月。

尽管这是一件愚蠢的事情,java.util.Date 会尝试推测您真正想要的内容并具有任意时间戳:当您创建一个早于它的 Date 对象时,它会在儒略历中呈现时间。

这很愚蠢(世界并没有一次性全部切换),所以 javascript 和 java.time 都不会这样做。

这解释了 2 天。

【讨论】:

    【解决方案2】:

    这是因为DateDate 都有两个非常不同的实现。

    这里实际上有两个区别:输出文本的格式和输出所代表的实际日期。

    不同的日期

    我仍在调查为什么 Java 的 Date 会在 0001 年 1 月 1 日返回好吧,rzwitserloot 已经发现并在他的回答中提到了这一点,而我正在吃饭。 Java 的Date 使用当时使用的日历,而Java 的JSR 310 日期和时间API 和JavaScript 的Date 都使用公历。这被称为proleptic calendar——一种在引入之前应用于日期的日历。

    确实知道 JavaScript 返回正确的日期值。 Java的Dateis broken,不要用。相反,您应该使用 java.time 包中提供的现代 Java 日期和时间 API。

    以下 Java 代码返回正确的日期:

    OffsetDateTime odt = Instant.ofEpochMilli(-62135769600000L)
        .atOffset(ZoneOffset.ofHours(-5));
    System.out.println(odt);
    

    不同的格式

    Java 和 JavaScript 的 Date 都以不同的方式实现 toString()。 toString(). toString()` 总是返回调用方法的对象的文本表示 - 但如何完全取决于作者的想法。

    您永远不应该依赖toString() 来采用某种格式。如果您确实想要格式化字符串,请在 Java 中使用 DateTimeFormatter

    【讨论】:

    • 我为你计算了 48 小时的间隔。看我的回答。
    • @rzwitserloot 我明白了。我已经这么想了,但我还是决定先吃晚饭。 ;-)
    猜你喜欢
    • 2015-05-20
    • 1970-01-01
    • 2016-08-06
    • 2013-07-24
    • 1970-01-01
    • 2018-11-02
    • 1970-01-01
    • 2023-03-18
    • 2018-02-09
    相关资源
    最近更新 更多