我的日期时间值为2016-12-21T07:48:36,偏移量为UTC + 14。 如何将日期时间转换为等效的标准GMT时间。

我尝试使用sampleDateFormat.parse()方法。但是,我无法获得类似UTC偏移量的TimeZone对象。

sampleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC+14:00"))

请帮助我将Java 7中的UTC日期时间转换为标准GMT时间。

您知道您的问题仅在于您使用了不受支持的" UTC + 14"。 getTimeZone仅知道" GMT + xx"形式

您从哪里获得+14偏移量的?

tl; dr

LocalDateTime.parse("2016-12-21T07:48:36" )        // Parse as a `LocalDateTime` given the lack of an offset or zone. *Not* an actual moment, only a rough approximation of potential moments along a range of about 26-27 hours.
.atOffset( ZoneOffset.ofHours( 14 ) )  // Assign an offset-from-UTC as context, giving meaning to determine an actual point on the timeline.
.toInstant()                           // Renders `Instant` object in UTC.
java.time

现代方法是使用Java 8及更高版本中内置的java.time类。在ThreeTen-Backport项目中,许多功能都向后移植到Java 6和7。

ZoneOffset offset = ZoneOffset.ofHours( 14 ); // fourteen hours ahead of UTC.

将字符串解析为LocalDateTime,因为它缺少有关偏移量或区域的任何信息。您输入的是标准ISO 8601格式,因此无需指定格式格式。

LocalDateTime ldt = LocalDateTime.parse("2016-12-21T07:48:36" );

将偏移量应用于本地日期时间以获取OffsetDateTime对象。

OffsetDateTime odt = ldt.atOffset( offset );

从中,提取一个始终为UTC的Instant。

Instant instant = odt.toInstant();

instant.toString(): 2016-12-20T17:48:36Z

在UTC中,该值为另一个日期,而不是21日。

请参阅IdeOne.com上的实时代码。

关于java.time

java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧版旧式日期时间类,例如java.util.Date,Calendar和SimpleDateFormat。

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

要了解更多信息,请参见Oracle教程。并在Stack Overflow中搜索许多示例和说明。规格为JSR 310。

使用兼容JDBC 4.2或更高版本的JDBC驱动程序,您可以直接与数据库交换java.time对象。不需要字符串或java.sql。*类。

在哪里获取java.time类?

Java SE 8,Java SE 9和更高版本

内置的

标准Java API的一部分,具有捆绑的实现。

Java 9添加了一些次要功能和修复。

Java SE 6和Java SE 7

java.time的许多功能在ThreeTen-Backport中都被反向移植到Java 6和7。

安卓系统

更高版本的Android捆绑了java.time类的实现。

对于较早的Android,ThreeTenABP项目改编了ThreeTen-Backport(如上所述)。请参阅如何使用ThreeTenABP…。

ThreeTen-Extra项目使用其他类扩展了java.time。该项目为将来可能在java.time中添加内容提供了一个试验场。您可能会在这里找到一些有用的类,例如Interval,YearWeek,YearQuarter等。

从技术上讲,Instant不在任何时区中。它代表从纪元的偏移。

@OrangeDog错误。 Instant最肯定是UTC。引用类doc:"纪元是从1970-01-01T00:00:00Z的标准Java纪元开始计算的"。 Z是Zulu的缩写,表示UTC。如果没有定义为UTC,则Instant将没有任何意义。

仅仅因为文档中的纪元表示形式是Z,并不意味着Instant是。引用类doc:"此Java API定义了自己的时间标度,即Java时间标度"。

我们也可以说:Instant在UTC偏移量0上算术锚定(对于任何内部日期时间计算绝对必要),但是出于格式化目的,切勿在没有时区或偏移量的情况下使用瞬间来表示本地信息,而java.time -API可以防止这种情况,即在格式化/解析即时信息时(大多数情况下)强制用户指定时区或偏移量。

使用" GMT + 14:00"而不是" UTC + 14:00"

SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss");
f.setTimeZone(TimeZone.getTimeZone("GMT+14:00"));
final Date d = f.parse("2016-12-21T07:48:36");
f.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println(f.format(d)); // -> 2016-12-20T05:48:36

我假设您将原始日期作为字符串。请执行下列操作:

创建一个SimpleDateFormat并将时区设置为" GMT + 14"

解析字符串值。您得到一个Date对象

将SimpleDateFormat的时区设置为" UTC"(或使用其他SimpleDateFormat实例)

格式化日期(如果您也希望将结果作为字符串)

例:

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
public class ConvertToUTC {
public static void main(String[] args) throws Exception {
String dateval ="2016-12-21T07:48:36";
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
df.setTimeZone(TimeZone.getTimeZone("GMT+14"));
Date date = df.parse(dateval);
System.out.println(df.format(date)); // GMT+14
df.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println(df.format(date)); // UTC
}
}

如果我们使用GMT + offset而不是UTC + offset,是否会考虑日光节约组件?

@GOPI答案是正确的。您的问题仅提及固定偏移量(如果前缀为GMT或UTC,则相等。)因此,在您的问题中,节省日光与您无关。否则,请勿使用固定的偏移量,而应使用"亚洲/东京"等时区标识符。

感谢Meno和Grodriguez!