我正在使用Joda Time 2.3将String转换为java.lang.Date。
<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年以下的所有年份都会导致错误。
这绝对是joda的错误。有人可以告诉我如何避免这个错误,或者我必须使用SimpleDateFormatter。
谢谢!
答案 0 :(得分:5)
您是否看过关于上海时间的Jon Skeets answer?我想说,这不是一个错误,而是时区历史数据中的一个奇怪的条目。
请注意,tz历史数据应小心处理(不是可靠的来源,这里只是关于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相比更改为tzdb的版本2013a -see也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版本08:05:52 java.util.Date.toString()中无法读取的内容 - 输出(只有CST作为时区名称)。 因此,与JodaTime相比,偏移没有差异,只要JDK和JodaTime使用相同的tzdb版本。