【问题标题】:Java: Wrong hour from Calendar instance?Java:日历实例的时间错误?
【发布时间】:2018-12-02 09:25:10
【问题描述】:

跑步:

public class test {
    @Test
    public void displayDate() {
        SimpleDateFormat MONTH_FORMAT = new SimpleDateFormat("MMM", Locale.getDefault());
        String testDateStr = "2017-07-01T07:58:23.000Z";
        Calendar calendar = getFormatedDate(testDateStr);
        int yearInt  = calendar.get(Calendar.YEAR);
        String monthStr = MONTH_FORMAT.format(calendar.getTime()).toUpperCase();
        int monthInt = calendar.get(Calendar.MONTH);
        int dayInt  = calendar.get(Calendar.DAY_OF_MONTH);
        int hour24 = calendar.get(Calendar.HOUR_OF_DAY);
        int min = calendar.get(Calendar.MINUTE);
        int sec = calendar.get(Calendar.SECOND);
        System.out.println(testDateStr);
        System.out.println(String.format("%s-%s-%s %s:%s:%s", yearInt, monthStr, dayInt, hour24, min, sec));
        System.out.println(String.format("%s-%s-%s %s:%s:%s", yearInt, monthInt, dayInt, hour24, min, sec));

    }

    private Calendar getFormatedDate(String dateStr) {
        Instant instant;
        try {
            instant = Instant.parse(dateStr);
        } catch (DateTimeParseException e) {
            e.printStackTrace();
            return null;
        }
        ZonedDateTime zdt = ZonedDateTime.ofInstant(instant, ZoneId.systemDefault());
        Calendar calendar = GregorianCalendar.from(zdt);
        return calendar;
    }
}

我明白了:

2017-07-01T07:58:23.000Z
2017-JUL-1 9:58:23
2017-6-1 9:58:23

请注意,我的小时数 = 9,而预期为 7

问题

  1. 为什么会出现这个结果
  2. 如何获得正确的结果?

谢谢!

【问题讨论】:

  • 为什么你认为这是错误的结果?大概您的默认时区比 UTC 早 10 小时,或者晚 2 小时,对吧?
  • ZoneOffset 是 000Z 所以预计没有偏移
  • 由于您可以使用现代日期时间类(Instant、ZonedDateTIme 和 ZoneId,均来自 java.time),我建议您仅使用 java.time 并驱逐差的SimpleDateFormat,, Calendar 和 GregorianCalendar 从您的代码中设计并且现在已经过时。它将使您的代码更简单、更清晰。 java.time 拥有您需要的所有功能以及更多功能。
  • 只是为了说明问题:.000 是秒的小数部分(如果你愿意,0 毫秒)。 Z 是区域偏移量(没有偏移量,正确)。
  • 是否需要为 7 月 打印 6 的 monthInt? 7 月是第 7 个月,所以我觉得很困惑。

标签: java calendar


【解决方案1】:

为什么会有这个结果

由于这一行: ZonedDateTime zdt = ZonedDateTime.ofInstant(instant, ZoneId.systemDefault());
您强制您的时区超过dateStr 中定义的时区,因此日历将使用您的时区而不是原始时区。

如何得到正确的结果?

将您的 getFormatedDate 方法更改为:

private Calendar getFormatedDate(final String dateStr) {
    final ZonedDateTime zdt = ZonedDateTime.parse(dateStr);
    return GregorianCalendar.from(zdt);
}

【讨论】:

  • 感谢您的解释。这行得通。标记为已回答并投票赞成!
  • 如果提问者真的(真的,真的)需要一个Calendar 对象(通常是他们无法升级的遗留API),这个答案是正确的。通常不会使用ZonedDateTime 来解析具有Z 偏移量的字符串,但由于我们需要一个来生成Calendar,因此在这种特殊情况下似乎是正确的方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-09-29
  • 2011-05-20
  • 2019-06-25
  • 1970-01-01
  • 1970-01-01
  • 2014-06-16
  • 1970-01-01
相关资源
最近更新 更多