Java SimpleDateFormat将结果解析一小时(是的,我设置了时区)

谜我:为什么这个简单的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: but was: at junit.framework.Assert.fail(Assert.java:47) ... snip ... 

公历的默认构造函数使用机器的本地时区。 如果这与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)); } 

您还需要设置日历的时区/夏令时。 看看从文档中获取的这个片段:

  // 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);