9

谜语:为什么这个简单的 JUnit 断言会失败?

public void testParseDate() throws ParseException {
    final SimpleDateFormat formatter = new SimpleDateFormat(
            "yyyy-MM-dd HH:mm:ss z");
    formatter.setTimeZone(UTC);
    final Calendar c = new GregorianCalendar();
    c.setTime(formatter.parse("2013-03-02 11:59:59 UTC"));

    assertEquals(11, c.get(HOUR_OF_DAY));
}

我原以为一天中的小时是 11,但根据 JUnit,一天中的小时是 12。

junit.framework.AssertionFailedError: expected:<11> but was:<12>
at junit.framework.Assert.fail(Assert.java:47)
    ... snip ...
4

2 回答 2

8

公历的默认构造函数使用机器的本地时区。如果这与 UTC 不同,则会出现这种行为。尝试使用 GregorianCalendar(TimeZone) 构造函数并将 UTC 传递给它。

这将起作用:

public void testParseDate() throws Exception {

    TimeZone UTC = TimeZone.getTimeZone("UTC");

    // Create a UTC formatter
    final SimpleDateFormat formatter = new SimpleDateFormat(
            "yyyy-MM-dd HH:mm:ss z");
    formatter.setTimeZone(UTC);

    // Create a UTC Gregorian Calendar (stores internally in UTC, so
    // get(Calendar.HOUR_OF_DAY) returns in UTC instead of in the
    // local machine's timezone.
    final Calendar c = new GregorianCalendar(UTC);

    // Ask the formatter for a date representation and pass that
    // into the GregorianCalendar (which will convert it into
    // it's internal timezone, which is also UTC.
    c.setTime(formatter.parse("2013-03-02 11:59:59 UTC"));

    // Output the UTC hour of day
    assertEquals(11, c.get(Calendar.HOUR_OF_DAY));
}
于 2013-04-13T18:46:42.547 回答
1

您还需要为日历设置时区/夏令时。看看这个摘自文档的片段:

 // create a Pacific Standard Time time zone
 SimpleTimeZone pdt = new SimpleTimeZone(-8 * 60 * 60 * 1000, ids[0]);

 // set up rules for daylight savings time
 pdt.setStartRule(Calendar.APRIL, 1, Calendar.SUNDAY, 2 * 60 * 60 * 1000);
 pdt.setEndRule(Calendar.OCTOBER, -1, Calendar.SUNDAY, 2 * 60 * 60 * 1000);

 // create a GregorianCalendar with the Pacific Daylight time zone
 // and the current date and time
 Calendar calendar = new GregorianCalendar(pdt);
于 2013-04-13T18:58:09.157 回答