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

M-S*_*M-S 1 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();
Run Code Online (Sandbox Code Playgroud)

Bas*_*que 6

期望

你的期望是错误的.

该"+01:00"指的是时间是一个小时领先UTC/GMT.因此,调整为UTC意味着减去一小时(17:20)而不是添加(19:20).

"+01:00"与说CET(中欧时间)具有相同的效果,这意味着比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
Run Code Online (Sandbox Code Playgroud)

juDate混乱

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

指定时区

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

更好的做法是始终指定您的时区.如果你愿意UTC/GMT,可以这样说.如果你愿意CET,可以这样说.(实际上,不要使用三字母代码,CET因为它们不是标准化的并且有重复 - 使用时区名称,例如Europe/PragueEurope/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);
Run Code Online (Sandbox Code Playgroud)

转储到控制台......

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() );
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)