0

我将日历实例设置为 00:00 的 UTC 日期,但是一旦我提前 1 小时返回结果

Calendar cal = Calendar.getInstance(TIMEZONE_UTC, Locale.ENGLISH);
cal.set(2017, 12 - 1, 15);
cal.set(Calendar.AM_PM, Calendar.AM);
cal.set(Calendar.HOUR, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
System.out.println(cal.getTime());
// Fri Dec 15 01:00:00 CET 2017 but should be 00:00:00

我想有冬季/夏季偏移,但我没有在公历或日历元素中找到任何描述来处理这个问题

4

2 回答 2

4

我的印象是,您真的只是在 2017 年 12 月 15 日之后,只是想确保一天中没有意外的时间?如果是这样,LocalDate那么java.time现代 Java 日期和时间 API 就是为您准备的:

LocalDate ld = LocalDate.of(2017, Month.DECEMBER, 15);
System.out.println(ld);

这打印

2017-12-15

无需担心小时、分钟或秒。

如果您确实需要 00:00 UTC 的日期时间(在Basil Bourque 发表评论之前,我曾经调用午夜的时间),有几种方法可以获得它。其中之一是:

    OffsetDateTime utcDateTime = LocalDateTime.of(2017, Month.DECEMBER, 15, 0, 0)
            .atOffset(ZoneOffset.UTC);
    System.out.println(utcDateTime);

这打印

2017-12-15T00:00Z

最后Z意味着UTC或偏移量为零。您会看到一天中的时间是您想要的 00:00。

您在问题中使用的Calendar课程早已过时,因此我建议您不要再使用它。java.time,现代 Java 日期和时间 API,也称为 JSR-310,使用起来非常好用。

你的代码出了什么问题?

虽然 aCalendar确实包含时区(您将其初始化为TIMEZONE_UTC),但 a Date(另一个过时的类)不包含。因此,当您转换为Date使用时cal.getTime(),您会丢失您希望时间为 UTC 的信息。接下来(这让很多人感到困惑),当您打印日期时,您会隐式调用Date.toString(),并且此方法会获取 JVM 的时区设置并生成一个包含该时区时间的字符串。显然,您(和我一样)处于 12 月 UTC+01:00 的时区。以下两个日期时间表示时间线上的同一点:

Fri Dec 15 01:00:00 CET 2017
Fri Dec 15 00:00:00 UTC 2017
于 2017-12-21T10:50:47.323 回答
1

您看到打印本地时间的原因是您通过Date.toString()使用本地时区(隐式使用系统时区)的日历实例显示它。

于 2017-12-21T09:45:01.163 回答