2014-03-27 71 views
4

我正在使用Joda Time 2.3将字符串转换为java.lang.Date。Joda时间:日期转换错误

<dependency> 
    <groupId>joda-time</groupId> 
    <artifactId>joda-time</artifactId> 
    <version>2.3</version> 
</dependency> 

下面是一些测试代码:

System.out.println(DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss").parseDateTime("1927-12-11 11:22:38")); 
System.out.println(DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss").parseDateTime("1927-12-11 11:22:38").toDate()); 

System.out.println(DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss").parseDateTime("1937-12-11 11:22:38")); 
System.out.println(DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss").parseDateTime("1937-12-11 11:22:38").toDate()); 

它运作良好,JDK 5和JDK 7下使用,但JDK 6时,其结果是:

1927-12-11T11:22:38.000+08:05:57 
Sun Dec 11 11:22:33 CST 1927 // lose 5 second 
1937-12-11T11:22:38.000+08:00 
Sat Dec 11 11:22:38 CST 1937 

你看到了第一次转换为java.lang.Date失去了5秒,但第二次是正确的。唯一的区别是年份数字,第一个是1927年,第二个是1937年.1927年以下的所有年份数字都会导致错误。

这对乔达来说肯定是错的。有人可以告诉我如何避免该错误,或​​者我必须使用SimpleDateFormatter。

谢谢!

+0

@BasilBourque不完全相同,因为海报关注的是5秒tz版本的差异。我已经更新了我的答案,并给出了tzdb historica数据更改的明确链接。 –

回答

5

你见过Jon Skeets answer关于上海时间?我会说,这不是一个错误,而是时区历史数据中的一个奇怪入口。

请注意,应该小心处理历史数据(不可靠的来源,这里只是关于LMT的一个假设 - 在中国的当地平均时间以上海经度为基础计算)。 IANA-TZDB产量可靠的数据后,才1970

编辑:

我已经测试你的代码的声明的时区“亚洲/上海”(适合时区名称CST在你的例子输出)和得到:

DateTimeZone tz = DateTimeZone.forID("Asia/Shanghai"); 

System.out.println(
    DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss") 
    .withZone(tz) 
    .parseDateTime("1927-12-11 11:22:38")); 
System.out.println(
    DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss") 
    .withZone(tz) 
    .parseDateTime("1927-12-11 11:22:38") 
    .toDate()); 

System.out.println(
    DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss") 
    .withZone(tz) 
    .parseDateTime("1937-12-11 11:22:38")); 
System.out.println(
    DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss") 
    .withZone(tz) 
    .parseDateTime("1937-12-11 11:22:38") 
    .toDate()); 

输出:

1927-12-11T11:22:38.000+08:05:52 
Sun Dec 11 04:16:46 CET 1927 // toString() prints in standard time zone 
1937-12-11T11:22:38.000+08:00 
Sat Dec 11 04:22:38 CET 1937 // toString() prints in standard time zone 

有5秒共一个小的差异因为我们使用不同版本的时区数据库(+08:05:52与+08:05:57比较,而2013年的tzdb版本更改 - 请参阅Paul Eggert实验库中的this commit)。和JDK版本从5更改为6或更高版本也可能涉及此更改 - 因此与SimpleDateFormat的结果相同。就这些。我不认为你会得到更好的结果SimpleDateFormat,在这里看到:

SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
df.setLenient(false); 
df.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai")); 
Date d = df.parse("1927-12-11 11:22:38"); 
System.out.println(d); 
long offset = TimeZone.getTimeZone("Asia/Shanghai").getOffset(d.getTime())/1000; 
System.out.println(offset); 
int offsetHours = (int) (offset/3600); 
long minutes = (offset % 3600); 
System.out.println(offsetHours + ":0" + minutes/60 + ":" + (minutes % 60)); 

你得到相同的偏移,即以我的TZ版本8时05分52秒究竟是不是可读的java.util.Date .toString() - 输出(只给CST作为时区名称)。 因此,与JodaTime相比,偏移量没有差别,前提是JDK和JodaTime使用相同的tzdb版本