【问题标题】:How to convert any Date time to UTC using ZonedDateTime or Java 8如何使用 ZonedDateTime 或 Java 8 将任何日期时间转换为 UTC
【发布时间】:2016-03-11 00:09:53
【问题描述】:

我正在尝试使用 ZonedDateTime 将日期 06-12-2015 02:10:10 PM 从默认区域转换为 UTC。

LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
ZonedDateTime utc = ZonedDateTime.of(localDateTime, ZoneOffset.UTC);

utc 返回 2015-12-06T14:10:10Z 而不是 06-12-2015 09:10:10 AM

如何将日期从默认时区转换为 UTC?给出的答案here 将当前时间转换为 UTC。

【问题讨论】:

    标签: java date java-8 zoneddatetime


    【解决方案1】:

    您可以使用ZonedDateTime.ofInstant(Instant, ZoneId),其中第二个参数是UTC(即时知道本地偏移量)。类似的,

    String source = "06-12-2015 02:10:10 PM";
    String pattern = "MM-dd-yyyy hh:mm:ss a";
    DateFormat sdf = new SimpleDateFormat(pattern);
    try {
        Date date = sdf.parse(source);
        ZonedDateTime zdt = ZonedDateTime.ofInstant(date.toInstant(), ZoneId.of("UTC"));
        System.out.println(zdt.format(DateTimeFormatter.ofPattern(pattern)));
    } catch (ParseException e) {
        e.printStackTrace();
    }
    

    我得到(对应于我的本地区域偏移量)

    06-12-2015 06:10:10 PM
    

    【讨论】:

    • 如果我这样做Date date1 = Date.from(zdt.toInstant())它会返回原始时间06-12-2015 02:10:10 PM为什么?
    • 为什么要将 SimpleDateFormat 与 java.time 代码混合?为什么不让 java.time 做解析呢?
    • @BasilBourque OP 的代码包括 date.toInstant(),我认为这就是问题所在。
    【解决方案2】:

    06-12-2015 02:10:10 PM 在巴基斯坦 = 06-12-2015 09:10:10 AM 在 UTC

    有很多方法可以做到这一点。

    1. 解析为LocalDateTime ➡️ 将其与您的时区结合以获得ZonedDateTime ➡️ 转换为Instant ➡️ 使用Instant#atZone 和UTC 时区转换为ZonedDateTime
    import java.time.Instant;
    import java.time.LocalDateTime;
    import java.time.ZoneId;
    import java.time.ZonedDateTime;
    import java.time.format.DateTimeFormatter;
    import java.util.Locale;
    
    public class Main {
        public static void main(String[] args) {
            String strDateTime = "06-12-2015 02:10:10 PM";
    
            DateTimeFormatter dtf = DateTimeFormatter.ofPattern("MM-dd-uuuu hh:mm:ss a", Locale.ENGLISH);
    
            LocalDateTime ldt = LocalDateTime.parse(strDateTime, dtf);
    
            // Using ZoneId.of("Asia/Karachi") for the demo. Change it to
            // ZoneId.systemDefault()
            Instant instant = ldt.atZone(ZoneId.of("Asia/Karachi")).toInstant();
    
            ZonedDateTime zdtUtc = instant.atZone(ZoneId.of("Etc/UTC"));
    
            System.out.println(zdtUtc.format(dtf)); // 06-12-2015 09:10:10 AM
        }
    }
    
    1. 解析为LocalDateTime ➡️ 将其与您的时区结合以获得ZonedDateTime ➡️ 转换为Instant ➡️ 使用ZonedDateTime#ofInstant 和UTC 时区转换为ZonedDateTime
    import java.time.Instant;
    import java.time.LocalDateTime;
    import java.time.ZoneId;
    import java.time.ZonedDateTime;
    import java.time.format.DateTimeFormatter;
    import java.util.Locale;
    
    public class Main {
        public static void main(String[] args) {
            String strDateTime = "06-12-2015 02:10:10 PM";
    
            DateTimeFormatter dtf = DateTimeFormatter.ofPattern("MM-dd-uuuu hh:mm:ss a", Locale.ENGLISH);
    
            LocalDateTime ldt = LocalDateTime.parse(strDateTime, dtf);
    
            // Using ZoneId.of("Asia/Karachi") for the demo. Change it to
            // ZoneId.systemDefault()
            Instant instant = ldt.atZone(ZoneId.of("Asia/Karachi")).toInstant();
    
            ZonedDateTime zdtUtc = ZonedDateTime.ofInstant(instant, ZoneId.of("Etc/UTC"));
    
            System.out.println(zdtUtc.format(dtf)); // 06-12-2015 09:10:10 AM
        }
    }
    
    1. 使用ZonedDateTime#withZoneSameInstant
    import java.time.LocalDateTime;
    import java.time.ZoneId;
    import java.time.ZonedDateTime;
    import java.time.format.DateTimeFormatter;
    import java.util.Locale;
    
    public class Main {
        public static void main(String[] args) {
            String strDateTime = "06-12-2015 02:10:10 PM";
    
            DateTimeFormatter dtf = DateTimeFormatter.ofPattern("MM-dd-uuuu hh:mm:ss a", Locale.ENGLISH);
    
            LocalDateTime ldt = LocalDateTime.parse(strDateTime, dtf);
    
            // Using ZoneId.of("Asia/Karachi") for the demo. Change it to
            // ZoneId.systemDefault()
            ZonedDateTime zdtPak = ldt.atZone(ZoneId.of("Asia/Karachi"));
    
            ZonedDateTime zdtUtc = zdtPak.withZoneSameInstant(ZoneId.of("Etc/UTC"));
    
            System.out.println(zdtUtc.format(dtf)); // 06-12-2015 09:10:10 AM
        }
    }
    
    1. 使用DateTimeFormatter#withZoneZonedDateTime#withZoneSameInstant
    import java.time.ZoneId;
    import java.time.ZonedDateTime;
    import java.time.format.DateTimeFormatter;
    import java.util.Locale;
    
    public class Main {
        public static void main(String[] args) {
            String strDateTime = "06-12-2015 02:10:10 PM";
    
            // Using ZoneId.of("Asia/Karachi") for the demo. Change it to
            // ZoneId.systemDefault()
            DateTimeFormatter dtfInput = DateTimeFormatter.ofPattern("M-d-u h:m:s a", Locale.ENGLISH)
                                            .withZone(ZoneId.of("Asia/Karachi"));
    
            ZonedDateTime zdtPak = ZonedDateTime.parse(strDateTime, dtfInput);
    
            ZonedDateTime zdtUtc = zdtPak.withZoneSameInstant(ZoneId.of("Etc/UTC"));
    
            DateTimeFormatter dtfOutput = DateTimeFormatter.ofPattern("MM-dd-uuuu hh:mm:ss a", Locale.ENGLISH);
            System.out.println(zdtUtc.format(dtfOutput)); // 06-12-2015 09:10:10 AM
        }
    }
    

    通过 Trail: Date Time 了解有关 modern date-time API* 的更多信息。


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

    【讨论】:

    • 经过深入研究的优秀答案,包含大量示例代码
    猜你喜欢
    • 2020-01-11
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    • 2014-01-24
    • 2012-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多