【问题标题】:Difference between Java and Javascript on 1st Jan 0001 UTCUTC 0001 年 1 月 1 日 Java 和 Javascript 之间的差异
【发布时间】:2014-07-22 16:10:46
【问题描述】:

我对 0001 年 1 月 1 日 UTC 日期在 Java 和 Javascript 中的表示方式有所不同

在 Java 中:

TimeZone utcTimeZone = TimeZone.getTimeZone("UTC");
Calendar cal = Calendar.getInstance(utcTimeZone);
cal.clear();
//1st Jan 0001
cal.set(1, 0, 1);
Date date = cal.getTime();
System.out.println(date);//Sat Jan 01 00:00:00 GMT 1
System.out.println(date.getTime());// -62135769600000

在 JavaScript 中:

var date = new Date();
date.setTime(-62135769600000);
date.toUTCString(); //"Sat, 30 Dec 0 00:00:00 GMT"

为什么在 Java 中以时间 -62135769600000L 表示的日期 0001 年 1 月 1 日在 Javascript 中显示为 1 月 1 日?

【问题讨论】:

  • 这对我来说似乎是 Java 中的一个错误......进一步寻找......
  • 深入研究,我认为这是一个 Gregorian/Julian 转换问题。

标签: java javascript date utc


【解决方案1】:

看起来这是因为Java中的GregorianCalendar实际上是公历和儒略历的混合体:

GregorianCalendar 是一种混合日历,它同时支持儒略历和公历系统,并支持单个不连续性,默认情况下对应于公历制定时的公历日期(在某些国家/地区为 1582 年 10 月 15 日,稍后在其他)。调用者可以通过调用 setGregorianChange() 更改切换日期。

如果以 1500-01-01 为例,Java 和 Javascript 的值将相隔 10 天。

要使其成为纯粹的GregorianCalendar,您可以使用这个:

GregorianCalendar cal = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
cal.setGregorianChange(new Date(Long.MIN_VALUE));

然后你会得到 -62135596800000 的 0001-01-01 值,这为 Javascript 提供了相同的日期。

切换日历令人头疼 - 它们使各种事情变得奇怪,而且几乎从来没有用过。 (我怀疑他们合适的用例也可能有不同的要求。我最终决定不为Noda Time实现它:)

【讨论】:

    【解决方案2】:

    java.time

    java.util 日期时间 API 及其格式化 API SimpleDateFormat 已过时且容易出错。建议完全停止使用,改用modern Date-Time API*

    使用现代日期时间 API java.time 的解决方案:

    import java.time.OffsetDateTime;
    import java.time.ZoneOffset;
    
    public class Main {
        public static void main(String[] args) {
            System.out.println(OffsetDateTime.of(1, 1, 1, 0, 0, 0, 0, ZoneOffset.UTC).toInstant().toEpochMilli());
        }
    }
    

    输出:

    -62135596800000
    

    在线演示

    Trail: Date Time 了解有关现代日期时间 API 的更多信息。

    JavaScript:

    const date = new Date();
    date.setTime(-62135596800000);
    console.log(date.toUTCString()); // Mon, 01 Jan 0001 00:00:00 GMT

    * 出于任何原因,如果您必须坚持使用 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
      • 2016-12-27
      • 1970-01-01
      • 1970-01-01
      • 2013-07-17
      • 2012-04-21
      相关资源
      最近更新 更多