Java SimpleDateFormat时间诡计多端

时间:2016-03-03 17:03:44

标签: java date simpledateformat

我正在尝试使用java.util.Date将日期字符串解析为java.text.SimpleDateFormat;但是,生成的格式化日期是错误的。

以下是一个显示问题的测试用例:

@Test
public void testSimpleDateFormat() throws Exception {
    String dateString = "2016-03-03 11:50:39.5960000";
    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSSS");
    Date date = format.parse(dateString);

    assertEquals(dateString, format.format(date));
}

这导致以下失败:

org.junit.ComparisonFailure: 
Expected :2016-03-03 11:50:39.5960000
Actual   :2016-03-03 13:29:59.0000000

日期正确,但小时,分钟,秒和毫秒都是错误的。为什么java.text.SimpleDateFormat搞砸我约会的时间?

2 个答案:

答案 0 :(得分:7)

您的模式表明5960000是一个毫秒。这代表5960秒,大约1小时39分钟,这解释了您获得的日期与初始日期之间的差异。

答案 1 :(得分:0)

java.time

您正在使用经证明令人困惑,麻烦且设计不佳的旧类。避免他们。它们已被Java 8及更高版本中内置的java.time框架所取代。

java.time类使用nanoseconds的分辨率,最多九位小数秒。绰绰有余的六位数(microseconds)。

您的输入字符串接近标准ISO 8601格式。默认情况下,在java.time中使用该格式来解析/生成日期时间值的字符串表示。所以,需要指定解析模式。

将输入字符串变为标准格式。用T替换中间的空格。

String input = "2016-03-03 11:50:39.5960000";
String inputStandardized = input.replace( " " , "T" );

将该字符串解析为日期时间对象。

LocalDateTime ldt = LocalDateTime.parse( inputStandardized );

要在时间轴上获得实际时刻,请为此输入指定偏移或时区。

如果是UTC格式,请创建OffsetDateTime

OffsetDateTime odt = ldt.atOffset( ZoneOffset.UTC );

如果需要特定时间,请创建ZonedDateTime

ZonedDateTime zdt = ldt.atZone( ZoneId.of( "America/Montreal" ) ) ;

在Java 8之前

如果您还没有Java 8技术,请考虑添加backport of java.timeJoda-Time(java.time的灵感)。对于Android,有一个特定的backport包装器ThreeTenABP