如何将 UTC 格式的字符串转换为特定时区的日历?

Posted

技术标签:

【中文标题】如何将 UTC 格式的字符串转换为特定时区的日历?【英文标题】:How to convert UTC formatted string to calendar in specific timezone? 【发布时间】:2012-12-05 01:47:19 【问题描述】:

我正在尝试将一些 UTC 时间的字符串转换为应设置为 GMT-5 的 java Calendar 对象。

我当前的 UTC 字符串输入是这样的:

UTC 日期:20050329174411

我使用这段代码(我检测到如下所示的“模式”):

DateFormat dateFormat = new SimpleDateFormat(pattern);
Date date = dateFormat.parse(utcDate);
calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT-5"));
calendar.setTime(date);

然后我这样打印时间:

日历.getTime()

我得到了这个结果:

格林威治标准时间:2005 年 3 月 29 日星期二 17:44:11 EST

我需要支持这些日期/时间字符串模式:

FORMAT_UTC4 = "yyyy";           
FORMAT_UTC6 = "yyyyMM";         
FORMAT_UTC8 = "yyyyMMdd";       
FORMAT_UTC10 = "yyyyMMddHH";    
FORMAT_UTC12 = "yyyyMMddHHmm";  
FORMAT_UTC14 = "yyyyMMddHHmmss";

我希望将时间设置为“12:44:11”。我已经阅读了几个示例,发现日期时间处理非常混乱。对我来说,它总是一样的,我得到某种格式的 UTC 字符串,然后将其转换为 GMT-5。我真的觉得应该很容易!

参考 1:How can I get the current date and time in UTC or GMT in Java?

参考 2:How to handle calendar TimeZones using Java?

【问题讨论】:

【参考方案1】:

在解析日期之前,您必须将 SimpleDateFormat 的时区设置为 UTC。否则,它使用您的默认时区。

并且要在“GMT-5”时区显示日期,您应该使用另一个 DateFormat,将时区设置为 GMT-5,并使用此 DateFormat 格式化日期。 Date 的toString() 方法使用您的默认时区将日期转换为可读的内容。

【讨论】:

我试过这个 dateFormat.setTimeZone(TimeZone.getTimeZone("GMT-5"));,需要改为 UTC 吗? 输入日期为UTC。因此必须使用 UTC 中的日期格式对其进行解析。输出日期为 GMT-5。因此必须使用 GMT-5 中的日期格式对其进行格式化。您不会使用法语翻译来阅读德语文本,对吗?而且您也不会使用德语翻译器来编写法语文本。 我认为从日历 (getTime) 中获取日期对象会给我 GMT-5 中的日期。 日期没有时区。这是一个普遍的瞬间。您可以选择使用时区对其进行格式化,其 toString() 方法使用您的默认时区对其进行格式化,但它没有任何时区。【参考方案2】:

java.time

请注意GMT-5-05:00 小时的时区偏移量是固定偏移量,即独立于DST 和类型来表示具有时区偏移量的日期时间为OffsetDateTime

演示:

import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;

public class Main 
    public static void main(String[] args) 
        Instant instant = Instant.ofEpochMilli(20050329174411L);
        OffsetDateTime odt = instant.atOffset(ZoneOffset.of("-05:00"));
        // Alternatively
        // OffsetDateTime.ofInstant(instant, ZoneOffset.of("-05:00"));
        System.out.println(odt);
    

输出:

2605-05-15T18:52:54.411-05:00

如果您希望根据 DST 自动调整时区偏移,请使用 ZonedDateTime

演示:

import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;

public class Main 
    public static void main(String[] args) 
        Instant instant = Instant.ofEpochMilli(20050329174411L);
        ZonedDateTime zdt = instant.atZone(ZoneId.of("America/Chicago"));
        // Alternatively
        // ZonedDateTime.ofInstant(instant, ZoneId.of("America/Chicago"));
        System.out.println(zdt);
    

输出:

2605-05-15T18:52:54.411-05:00[America/Chicago]

Trail: Date Time了解更多关于java.time的modern date-time API*

如果您需要从ZonedDateTime 的对象中获得java.util.Calendar 的对象,您可以按如下方式进行:

Calendar calendar = Calendar.getInstance();
calendar.setTime(Date.from(zdt.toInstant()));

* 出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,您可以使用 ThreeTen-Backport,它将大部分 java.time 功能向后移植到 Java 6 和 7 . 如果您正在为一个 android 项目工作并且您的 Android API 级别仍然不符合 Java-8,请检查 Java 8+ APIs available through desugaring 和 How to use ThreeTenABP in Android Project。

【讨论】:

以上是关于如何将 UTC 格式的字符串转换为特定时区的日历?的主要内容,如果未能解决你的问题,请参考以下文章

将 UTC 中的 SQL Server 日期时间转换为特定时区

如何在特定时区转换 DateTime?

如何在特定时区转换 DateTime?

JavaScript:将 UTC 日期时间转换为传递时区的日期时间

如何将 UTC 时间转换为本地时间

将 UTC 日期格式转换为本地 nsdate