Java和Joda-Time:日期错误的值

时间:2013-12-19 17:24:37

标签: java jodatime

当我尝试解析这样的字符串日期时,我在Joda-Time收到了错误的日期:

2013-11-20 18:20:00 +01:00

我希望获得以下日期:     Wed Nov 20 19:20:00 CET 2013 但我得到了:     Wed Nov 20 18:20:00 CET 2013

我正在使用Joda-Time,这是我的代码:

String dateString = "2013-11-20 18:20:00 +01:00";
DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss Z");
DateTime temp = formatter.parseDateTime(dateString);
Date date = temp.toDate();

2 个答案:

答案 0 :(得分:6)

期望

你的期望是错误的。

“+01:00”表示UTC / GMT的时间提前一小时。因此,调整为UTC意味着减去一小时(17:20)而不是添加(19:20)。

“+01:00”与CET (Central European Time)具有相同的效果,这意味着比UTC / GMT提前一小时。所以......

2013-11-20 18:20:00 +01:00 = Wed Nov 20 18:20:00 CET 2013

......这是同一时间同一时间陈述的两种不同方式。

当我在美国西海岸时间运行你的代码时,我得到......(注意同一时间)

temp: 2013-11-20T09:20:00.000-08:00
date: Wed Nov 20 09:20:00 PST 2013

j.u.Date Confusion

正如the answer by Stroboskop所说,你可能会受到java.util.Date的愚弄。对象本身具有时区信息。然而,toString()方法的实现使用默认时区来呈现要显示的文本。混乱。避免使用java.util.Date/Calendar类的众多原因之一。相比之下,Joda-Time DateTime对象确实知道他们自己的时区。

指定时区

您真正的问题是一个非常常见的问题:忽略时区。如果未指定时区,则使用默认时区。如您所见,我的默认时区与您的不同,因此在运行相同代码时得到的结果不同。

更好的做法是始终指定您的时区。如果你想要UTC/GMT,请说明。如果你想要CET,请说明。 (实际上,不要使用像CET这样的三字母代码,因为它们没有标准化并且有重复 - 使用时区名称,例如 Europe / Prague Europe / Paris 。)解析该字符串时,请指定要合并到新DateTime对象中的时区。

示例代码

以下是一些示例代码,说明如何在解析时指定时区。请注意对withZone()的调用。

请注意,所有三个解析的结果都是Universe时间线中的相同时刻。为了说明这一点,我的代码将自Unix Epoch支持每个DateTime对象以来的毫秒转储到控制台。通常我会尝试不使用也不考虑毫秒以来的时间。但是这里使用毫秒 - 自 - 时代证明了一点。

// © 2013 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so.
// import org.joda.time.*;
// import org.joda.time.format.*;

String dateString = "2013-11-20 18:20:00 +01:00";
DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss Z");

// Time Zone list… http://joda-time.sourceforge.net/timezones.html  (not quite up-to-date, read page for details)
DateTime dateTimeInUtc = formatter.withZone( DateTimeZone.UTC ).parseDateTime( dateString );
DateTime dateTimeInPrague = formatter.withZone( DateTimeZone.forID( "Europe/Prague" ) ).parseDateTime(dateString);
DateTime dateTimeInVancouver = formatter.withZone( DateTimeZone.forID( "America/Vancouver" ) ).parseDateTime(dateString);

转储到控制台...

System.out.println( "dateTimeInUtc: " + dateTimeInUtc + "  … In Milliseconds since Unix Epoch: " + dateTimeInUtc.getMillis() );
System.out.println( "dateTimeInPrague: " + dateTimeInPrague + "  … In Milliseconds since Unix Epoch: " + dateTimeInPrague.getMillis() );
System.out.println( "dateTimeInVancouver: " + dateTimeInVancouver + "  … In Milliseconds since Unix Epoch: " + dateTimeInVancouver.getMillis() );

运行时...(请注意,无论此代码是在您的计算机上还是我的计算机上运行,​​我们都会得到相同的结果!)

dateTimeInUtc: 2013-11-20T17:20:00.000Z  … In Milliseconds since Unix Epoch: 1384968000000
dateTimeInPrague: 2013-11-20T18:20:00.000+01:00  … In Milliseconds since Unix Epoch: 1384968000000
dateTimeInVancouver: 2013-11-20T09:20:00.000-08:00  … In Milliseconds since Unix Epoch: 1384968000000

答案 1 :(得分:2)

标准问题:你在哪个时区? CET

我假设解析的DateTime是正确的?它有什么时区?

请记住,Date没有时区。我甚至不确定它是否真的考虑了Timezone.getDefault()。

所以,简而言之,看起来你的时区与+1不同,这就是为什么你的时间会被移动一小时。

- 编辑 - 坚持,稍等。为什么你甚至期待19:20?文字说18:20 +1,Joda解析这个就像那样,而Date则删除了时区。就是这样。