Joda-Time DateTime.toDate()恢复时区

时间:2014-06-04 18:22:59

标签: java jodatime

我正在尝试使用Joda-Time从一个时区转换为另一个时区。

final DateTimeZone fromTimeZone = DateTimeZone.forID("America/Los_Angeles");
final DateTimeZone toTimeZone = DateTimeZone.forID(toTimeZoneString);
DateTime convertedStart = new DateTime(start, fromTimeZone).withZone(toTimeZone);

Date finalS = convertedStart.toDate();

我看到finalS丢失了时区,并在.toDate()时恢复到原始时区。 convertedStart已正确转换。

以格式开头 - > Wed Jun 04 18:15:38 GMT 2014


示例:

start: Wed Jun 04 18:15:38 GMT 2014
toTimeZoneString is Asia/Kolkata
convertedStart : 2014-06-05T06:45:38.409+05:30
finalS: Wed Jun 04 18:15:38 GMT 2014

为什么会这样?

1 个答案:

答案 0 :(得分:7)

由于您拒绝发布完整的代码示例,我将使用一个小的演示作为答案。

使用Joda-Time 2.3的示例代码。

仅在强制使用时才使用java.util.Date,例如输出/输入到其他类。

java.util.Date dateIn = new java.util.Date(); // Avoid java.util.Date when possible. 

将日期转换为Joda-Time DateTime,并指定时区。我随意选择UTC。除非业务规则规定使用本地时区,否则大部分或全部业务逻辑应以UTC完成。

DateTime dateTimeUtc = new DateTime( dateIn, DateTimeZone.UTC ); // Convert Date to DateTime, assign UTC time zone.

调整从UTC到美国西海岸的时区。使用proper time zone names(主要是洲/ cityOrRegion)而不是3或4个字母代码,既不是标准化也不是唯一的。

DateTimeZone timeZoneLos_Angeles = DateTimeZone.forID( "America/Los_Angeles" ); // Adjust time zone to United States.
DateTime dateTimeLos_Angeles = dateTimeUtc.withZone( timeZoneLos_Angeles );

调整到印度时区,比UTC早五个半小时。请注意,对于thread-safety,Joda-Time使用immutable objects。我们不是进行更改,而是在复制原始值时创建一个新实例。

DateTimeZone timeZoneKolkata = DateTimeZone.forID( "Asia/Kolkata" ); // Adjust time zone to India.
DateTime dateTimeKolkata = dateTimeLos_Angeles.withZone( timeZoneKolkata );

如果需要,转换回j.u.Date。

java.util.Date dateOut = dateTimeKolkata.toDate();

转储到控制台。请注意,默认情况下,Joda-Time根据ISO 8601 standard创建字符串表示。

System.out.println( "dateIn: " + dateIn ); // j.u.Date's "toString" method applies JVM's default time zone. Very confusing, as a j.u.Date has no time zone.
System.out.println( "dateTimeUtc: " + dateTimeUtc );
System.out.println( "dateTimeLos_Angeles: " + dateTimeLos_Angeles );
System.out.println( "dateTimeKolkata: " + dateTimeKolkata );
System.out.println( "dateOut: " + dateOut ); // j.u.Date's "toString" method uses a terrible format. Use only in a pinch like debugging, never in production.
System.out.println( "Milliseconds since Unix epoch: " + dateIn.getTime() + " | " + dateTimeUtc.getMillis() + " | " + dateTimeLos_Angeles.getMillis() + " | " + dateTimeKolkata.getMillis() + " | " + dateOut.getTime()  );

跑步时......

dateIn: Wed Jun 04 13:51:01 PDT 2014
dateTimeUtc: 2014-06-04T20:51:01.593Z
dateTimeLos_Angeles: 2014-06-04T13:51:01.593-07:00
dateTimeKolkata: 2014-06-05T02:21:01.593+05:30
dateOut: Wed Jun 04 13:51:01 PDT 2014
Milliseconds since Unix epoch: 1401915061593 | 1401915061593 | 1401915061593 | 1401915061593 | 1401915061593

了解所有这些日期时间值代表相同的同时时刻,即宇宙时间轴上的相同点。请注意字符串在不同日期(6月4日和5日)的变化情况,但我们看到了相同的时刻。想象雷克雅未克,洛杉矶和加尔各答的三个人同时看着他们的怀表/手机(wall-clock time)。