为什么具有0 long值作为参数的Date构造函数将在1970年之前在Java中输出日期?

时间:2014-03-26 18:09:09

标签: java date epoch

我知道他们认为 epoch 是1970年1月1日午夜以来的毫秒数。

然而,当我设置:

System.out.println(new Date(0));

我明白了:

  

Wed Dec 31 18:00:00 CST 1969

因为它倒退了,为什么?

愚蠢的编辑:

是的,我是GMT -6

2 个答案:

答案 0 :(得分:8)

时代始于1970年1月1日,UTC时间午夜。您的系统默认时区可能是当时UTC的6小时。 (这就是使用系统默认值而不明确选择的函数的原因很糟糕。)

答案 1 :(得分:0)

java.util.Date 对象不是像 modern date-time types 那样的真实日期时间对象;相反,它表示自称为“纪元”的标准基准时间以来的毫秒数,即 January 1, 1970, 00:00:00 GMT(或 UTC)。当您打印 java.util.Date 的对象时,它的 toString 方法返回 JVM 时区中的日期时间,根据该毫秒值计算得出。

由于 JVM 的时区偏移为 -06:00 小时,January 1, 1970, 00:00:00 GMT 显示为 Wed Dec 31 18:00:00 CST 1969。如果您需要以 GMT(或 UTC)打印日期时间,则需要将相应的时区设置为 SimpleDateFormat 并从中获取格式化的字符串,例如

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) {
        Date date = new Date(0);
        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(date));
    }
}

输出:

1970-01-01T00:00:00.000Z

随着 Java SE 8(2014 年 3 月)的发布,过时且容易出错的遗留日期时间 API(java.util 日期时间类型及其格式类型,SimpleDateFormat 等)被由 java.time 取代,modern date-time API*

使用 java.time,现代 API:

import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;

public class Main {
    public static void main(String[] args) {
        Instant instant = Instant.EPOCH;
        System.out.println(instant);

        // Alternatively,
        instant = Instant.ofEpochMilli(0);
        System.out.println(instant);

        // The same instant in your JVM's timezone
        ZonedDateTime zdt = instant.atZone(ZoneId.of("America/Mexico_City"));
        System.out.println(zdt);
    }
}

输出:

1970-01-01T00:00:00Z
1970-01-01T00:00:00Z
1969-12-31T18:00-06:00[America/Mexico_City]

Instant 代表时间线上的一个瞬时点。输出中的 Z 是零时区偏移的 timezone designator。它代表祖鲁语并指定 Etc/UTC 时区(时区偏移为 +00:00 小时)。

modern date-time API 中详细了解 java.timeTrail: Date Time*


* 出于任何原因,如果您必须坚持使用 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