Java Date(0)不是1970年1月1日

时间:2011-10-25 20:05:06

标签: java

我原本希望打印 1970-01-01-00:00:00 ,但会打印 1970-12-31-19:00:00 < / p>

我怎么误解了Date的计算方式?这是一年假。我在带有JDK 1.6的Windows 7上运行它

System.out.println(new SimpleDateFormat("YYYY-MM-dd-HH:mm:ss").format(new Date(0)));

6 个答案:

答案 0 :(得分:19)

  

我怎么误解了Date的计算方式?

new Date(0)是1970年1月1日 UTC您的时区不是UTC。

  

这是一年假。

不,不是。打印价值仅落后5个小时。让我猜一下 - 你在the eastern part of the US的某个地方?

答案 1 :(得分:19)

这不仅仅是时区 - 它使用时区混合使用YYYY表示周年而不是(自Java 7起)。将其更改为yyyy,您将看到1969年。

docs on week years州:

  

为WEEK_OF_YEAR字段计算的值范围为1到53.日历年的第一周是从getFirstDayOfWeek()开始的最早的七天时段,该时间段至少包含该年的getMinimalDaysInFirstWeek()天。因此,它取决于getMinimalDaysInFirstWeek(),getFirstDayOfWeek()和1月1日的星期几的值。一年的第1周和第二年的第1周之间的周(不包括)从2到52顺序编号或者53(参与Julian-Gregorian过渡的年份除外)。

     

在构造GregorianCalendar时,使用依赖于语言环境的资源初始化getFirstDayOfWeek()和getMinimalDaysInFirstWeek()值。当getFirstDayOfWeek()为MONDAY且getMinimalDaysInFirstWeek()为4时,周确定与ISO 8601标准兼容,这些值用于首选标准的语言环境中。可以通过调用setFirstDayOfWeek()和setMinimalDaysInFirstWeek()来显式设置这些值。

     

周年与WEEK_OF_YEAR周期同步。第一周和最后一周(包括)之间的所有周都具有相同的周年值。因此,一周中的第一天和最后一天可能具有不同的日历年值。

所以问题是1969年“正常年份”的最后一天实际上是1970年的“一周”。

你应该明确地使用yyyy来避免混淆 - 一周相对很少有用,很容易引起混淆,正如我们所见:)

编辑:正如评论中所述,你确定你没有使用Java 7吗? docs for SimpleDateFormat in 1.6没有提到它......也许你正在编译1.6但在7中运行

答案 2 :(得分:9)

要总结关于YYYYyyyy的正确答案以及时区处理,以下是产生预期输出的代码:

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HH:mm:ss");
    sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
    System.out.println(sdf.format(new Date(0))); //1970-01-01-00:00:00

答案 3 :(得分:0)

答案 4 :(得分:0)

做* 1000L

 System.out.println(new SimpleDateFormat("YYYY-MM-dd-HH:mm:ss").format(new Date(0) * 1000L));

答案 5 :(得分:0)

java.time

我建议您使用 java.time,现代 Java 日期和时间 API,用于您的日期和时间工作。在 Java 1.6 和 1.7 上,这是通过 java.time 向后移植到那些 Java 版本,称为 ThreeTen 后向移植(底部链接)发生的。

正如评论中所讨论的,您需要决定一个时区,以便将纪元之后的 0 毫秒解释为日期和时间。就像这样的评论一样,我选择 America/New_York 时区作为示例。插入你自己的。

我正在使用这些声明:

private static final ZoneId ZONE = ZoneId.of("America/New_York");
private static final DateTimeFormatter FORMATTER
        = DateTimeFormatter.ofPattern("uuuu-MM-dd-HH:mm:ss", Locale.ROOT);

剩下的很简单(当您知道如何操作时):

    String epochString = Instant.EPOCH.atZone(ZONE).format(FORMATTER);
    System.out.println(epochString);

输出为:

<块引用>

1969-12-31-19:00:00

如前所述,在 UTC 时间 1970 年 1 月 1 日,地球西半部(包括美洲和太平洋的大部分地区)仍然是 1969 年 12 月 31 日。

模式字母 uuuu?使用 java.time,您可以使用 yyyy 表示时代(总是正数)或 uuuu 表示签名年份。通常建议使用后者,这样您就可以确保在您(无论预期与否)遇到共同时代之前一年的情况下看到差异。 Java 中的 uuuu 格式化模式代码中的 yyyyDateTimeFormatter 问题? 链接到下面广泛涵盖了差异。

问题:java.time 不需要 Java 8 吗?

java.time 至少需要 Java 6

  • 在 Java 8 及更高版本以及更新的 Android 设备(从 API 级别 26 开始)中,内置了现代 API。
  • 在非 Android Java 6 和 7 中获得 ThreeTen Backport,现代类的向后移植(ThreeTen for JSR 310;请参阅底部的链接)。
  • 在较旧的 Android 上,使用脱糖或 ThreeTen Backport 的 Android 版本。它被称为 ThreeTenABP。在后一种情况下,请确保使用子包从 org.threeten.bp 导入日期和时间类。

链接