【问题标题】:How to Convert a Date time value with UTC offset into GMT in java 7如何在 java 7 中将具有 UTC 偏移量的日期时间值转换为 GMT
【发布时间】:2017-05-07 04:47:37
【问题描述】:

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

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

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

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

【问题讨论】:

  • 您知道您的问题只是您使用了不受支持的“UTC+14”。 getTimeZone 只知道“GMT+xx”形式
  • 你从哪里得到 +14 偏移量?

标签: java datetime utc gmt date-conversion


【解决方案1】:

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

  • 创建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,则它是相等的)。因此,在您的问题中,夏令时是无关紧要的。否则不要使用固定偏移量,而是使用“亚洲/东京”等时区标识符。
  • 感谢梅诺和格罗德里格斯!
【解决方案2】:

使用“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

【讨论】:

    【解决方案3】:

    tl;博士

    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 中,值是不同的日期,即 20 日而不是 21 日。

    live code at IdeOne.com


    关于java.time

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

    Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。

    要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310

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

    从哪里获得 java.time 类?

    ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

    【讨论】:

    • 从技术上讲,Instant 不在任何时区“内”。它表示与纪元的偏移量。
    • @OrangeDog 不正确。 Instant 肯定是 UTC 格式。引用类文档:“纪元秒是从 1970-01-01T00:00:00Z 的标准 Java 纪元测量的”。 Z 是 Zulu 的缩写,意思是 UTC。如果没有定义为 UTC,Instant 将没有任何意义。
    • 仅仅因为文档中时代的表示是在 Z 中,并不意味着 Instant 是。引用类文档:“这个 Java API 定义了它自己的时间尺度,Java 时间尺度”。
    • 我们也可以说:Instant 在算术上锚定在 UTC 偏移量为零(对于任何内部日期时间计算绝对必要),但出于格式化目的,不应该使用瞬间用于表示本地信息的时区或偏移量,java.time-API 可防止这种情况发生,即强制用户在格式化/解析瞬间(在大多数情况下)时指定时区或偏移量。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-01
    • 2019-03-17
    • 2022-09-30
    • 2017-07-31
    • 2012-08-02
    • 2012-09-18
    相关资源
    最近更新 更多