用时区将Joda-Time`DateTime`转换为没有时区的DateTime?

给定DateTime例如2015-07-09T05:10:00+02:00使用Joda-Time ?

如何将其转换为本地时间,即将时区添加到时间本身。 期望的输出: 2015-07-09T07:10:00

我尝试了dateTime.toDateTime(DateTimeZone.UTC)但没有给出所需的结果。

@Nazgul说的是对的,但是如果你想要实现的只是UTC区域的“壁垒时间”,你可以做类似的事情:

 DateTime dateTimePlus2 = DateTime.parse("2015-07-09T05:10:00+02:00"); System.out.println(dateTimePlus2); DateTime dateTimeUTC = dateTimePlus2.withZone(DateTimeZone.UTC); System.out.println(dateTimeUTC); LocalDateTime localDateTimeUTC = dateTimeUTC.toLocalDateTime(); System.out.println(localDateTimeUTC); 

结果:

 2015-07-09T05:10:00.000+02:00 2015-07-09T03:10:00.000Z ("Z" == Zulu tz == UTC) 2015-07-09T03:10:00.000 

如您所见,时间不是您预期的“07:10”,因为UTC + 2区域 UTC 两个小时。 转换为UTC 减去 2小时。

在正确答案中添加更多信息和示例( 接受的答案和其他 答案 )。

更新在java.time类的末尾添加了一节。 这些取代了Joda-Time。

LocalDateTime目的

您可能会对LocalDateTime的用途感到困惑。

如果尝试使用“挂钟时间”来表示日期时间值,就像当地人看到他们自己的时钟和日历一样,那么调整DateTime对象的时区以适应所需的位置。

LocalDateTime不适用于特定地点,但适用于日期+时间的一般概念。 例如,“今年的圣诞节将于2014年12月25日午夜开始”。 从概念上讲,这是一个LocalDateTime,旨在表示巴黎的不同时刻,而不是蒙特利尔和奥克兰。

调整时区

使用Joda-Time中的DateTimeZone类调整到所需的时区。 Joda-Time使用不可变对象。 因此,我们不是更改时区(“mutate”),而是基于旧的Date实例化实例化,但具有所需的差异(某些其他时区)。

使用适当的时区名称 。 一般来说是一个continent/cityOrRegion

 DateTimeZone zoneParis = DateTimeZone.forID( "Europe/Paris" ); DateTimeZone zoneMontréal = DateTimeZone.forID( "America/Montreal" ); DateTimeZone zoneAuckland = DateTimeZone.forID( "Pacific/Auckland" ); 

解析字符串,指定时区,调整到其他时区。

 DateTime dateTimeParis = new DateTime( "2015-07-09T05:10:00+02:00" , zoneParis ); DateTime dateTimeMontréal = dateTimeParis.withZone( zoneMontréal ); DateTime dateTimeAuckland = dateTimeParis.withZone( zoneAuckland ); 

转储到控制台。

 System.out.println( "dateTimeParis: " + dateTimeParis ); System.out.println( "dateTimeMontréal: " + dateTimeMontréal ); System.out.println( "dateTimeAuckland: " + dateTimeAuckland ); 

跑步的时候。

 dateTimeParis: 2015-07-09T05:10:00.000+02:00 dateTimeMontréal: 2015-07-08T23:10:00.000-04:00 dateTimeAuckland: 2015-07-09T15:10:00.000+12:00 

使用格式化字符串进行本地化

在创建日期时间对象的字符串表示时,Joda-Time可以转换为特定语言环境的语言和习惯样式。

 DateTimeFormatter formatterMontréal = DateTimeFormat.forStyle( "FF" ).withZone( zoneMontréal ).withLocale( Locale.CANADA_FRENCH ); String outputMontréal = formatterMontréal.print( dateTimeParis ); System.out.println( "outputMontréal: " + outputMontréal ); 

运行时:

 outputMontréal: mercredi 8 juillet 2015 23 h 10 EDT 

java.time

现在处于维护模式的Joda-Time项目建议迁移到java.time类。 Joda-Time框架启发了java.time,因此概念非常相似。

ZoneIdZoneOffset分别代表时区和UTC的偏移量 。 偏移量仅为小时数,分钟数和秒数。 时区是偏移量加上一组用于处理夏令时(DST)等exception的规则。

 ZoneId zoneParis = ZoneId.of( "Europe/Paris" ); ZoneId zoneMontreal = ZoneId.of( "America/Montreal" ); ZoneId zoneAuckland = ZoneId.of( "Pacific/Auckland" ); 

java.time中的主要日期时间类是:

  • Instant – UTC时间轴上的一个时刻,分辨率为纳秒 (最多九(9)位小数)。
  • OffsetDateTime – 一个Instant加一个ZoneOffset
  • ZonedDateTime – 一个Instant加一个ZoneId

在解析/生成表示日期时间值的字符串时,java.time类默认使用ISO 8601标准格式。 因此,无需使用此类输入指定格式设置模式。

此输入指示与UTC的偏移但不是全时区。 所以我们解析为OffsetDateTime而不是ZonedDateTime

 OffsetDateTime odt = OffsetDateTime.parse( "2015-07-09T05:10:00+02:00" ); 

作为java.time的基本构建块,始终按UTC定义,您可能需要提取Instant

 Instant instant = odt.toInstant(); // `Instant` is always in UTC by definition. 

您可以调整为时区。

 ZonedDateTime zdtParis = odt.atZoneSameInstant( zoneParis ); ZonedDateTime zdtMontreal = odt.atZoneSameInstant( zoneMontreal ); ZonedDateTime zdtAuckland = zdtMontreal.withZoneSameInstant( zoneAuckland ); 

通过DateTimeFormatter类进行本地化。

 DateTimeFormatter f = DateTimeformatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( Locale.CANADA_FRENCH ); String output = zdtMontreal.format( f ); 

查看IdeOne.com中的实时代码 。

odt:2015-07-09T05:10 + 02:00

时刻:2015-07-09T03:10:00Z

zdtParis:2015-07-09T05:10 + 02:00 [欧洲/巴黎]

zdtMontreal:2015-07-08T23:10-04:00 [美国/蒙特利尔]

zdtAuckland:2015-07-09T15:10 + 12:00 [太平洋/奥克兰]

输出:mercredi 8 juillet 2015 23 h 10 EDT


关于java.time

java.time框架内置于Java 8及更高版本中。 这些类取代了麻烦的旧遗留日期时间类,如java.util.DateCalendarSimpleDateFormat

现在处于维护模式的Joda-Time项目建议迁移到java.time类。

要了解更多信息,请参阅Oracle教程 。 并搜索Stack Overflow以获取许多示例和解释。 规范是JSR 310 。

从哪里获取java.time类?

  • Java SE 8SE 9及更高版本
    • 内置。
    • 带有捆绑实现的标准Java API的一部分。
    • Java 9增加了一些小function和修复。
  • Java SE 6SE 7
    • 许多java.timefunction都被反向移植到ThreeTen-Backport中的 Java 6和7。
  • Android的
    • ThreeTenABP项目特别适用于Android的ThreeTen-Backport (如上所述)。
    • 请参阅如何使用….

ThreeTen-Extra项目使用其他类扩展了java.time。 该项目是未来可能添加到java.time的试验场。 您可以在这里找到一些有用的课程,如IntervalYearWeekYearQuarter等。

没有时区dosnt的DateTime是有道理的。 DateTime始终相对于使用它们的时区。 没有时区信息,日期时间组合对地理位置没有意义。 然而,原始时间戳毫秒可以作为自1970年1月1日以来的毫秒数而被访问,但任何具体的日期时间组合必须具有时区。