【问题标题】:Convert GMT DateTime String转换 GMT 日期时间字符串
【发布时间】:2011-10-07 12:44:33
【问题描述】:

我对 Java 还是很陌生,我对使用 SimpleDateFormatCalendar 有点坚持。我有一个日期对象,想提取一个像 yyyy-MM-dd HH:mm:ss 这样的 GMT 日期字符串。我住在德国,目前我们是 GMT +0200。我的日期对象的时间例如是2011-07-18 13:00:00。我现在需要的是2011-07-18 11:00:00。应该自动计算我的时区的偏移量。

我尝试过这样的事情,但我想某处有问题:

private String toGmtString(Date date){
    SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    TimeZone timeZone = TimeZone.getDefault();
    Calendar cal = Calendar.getInstance(new SimpleTimeZone(timeZone.getOffset(date.getTime()), "GMT"));
    sd.setCalendar(cal);
    return sd.format(date);
}

在某些设备上,日期字符串会像我想要的那样返回。在其他设备上,偏移量计算不正确,我从输入日期对象接收日期和时间。你能给我一些提示或建议吗?我想我获得默认时区的方法不起作用?

【问题讨论】:

    标签: java android date simpledateformat gmt


    【解决方案1】:
    private String toGmtString(Date date){
        SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        sd.setTimeZone(TimeZone.getTimeZone("GMT"));
        return sd.format(date);
    }
    

    您不需要创建新的SimpleTimeZone,因为您没有发明新的时区 - 您的程序中有 2 个现有时区,GMT 和您的默认时区。

    您也不需要修改现有的日期对象,因为您不想表示不同的时间点 - 您只希望以不同的方式显示同一时间点。

    您需要做的就是告诉SimpleDateFormat 在格式化时使用哪个时区。

    【讨论】:

    • 我不敢相信它这么容易,但我当然也会尝试。请给我几分钟...
    • 好的.. 测试过.. 我使用了一个代表2011-07-18 13:34:27的日期对象。使用默认日期函数.toGMTString() 我收到18 Jul 2011 11:43:27 GMT,这是我需要的确切时间点。使用我自己的函数我仍然收到2011-07-18 13:43:27,这是我的问题。使用 Jigar Joshin 的功能,我收到 2011-07-18 12:43:27 缺少 1 小时(欧洲夏令时)。使用 Eli Acherkans 函数,我收到了2011-07-18 11:43:27,这正是我想要的(包括欧洲夏令时在内的偏移量)。
    • 你是一个活生生的救星@EliAcherkan!
    【解决方案2】:
    private String toGmtString(Date date){
        //date formatter
        SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //getting default timeZone
        TimeZone timeZone = TimeZone.getDefault();
        //getting current time
        Calendar cal = Calendar.getInstance()
        cal.setTime(date) ;
        //adding / substracting curren't timezone's offset
        cal.add(Calendar.MILLISECOND, -1 * timeZone.getRawOffset());    
        //formatting and returning string of date
        return sd.format(cal.getTime());
    }
    

    【讨论】:

    • 好的,这看起来不错。我会在几分钟内试一试。一个问题。您在哪里以及如何使用函数调用中的日期参数?!获取实例后是否应该使用cal.setTime(date);
    • 不错!作品!非常感谢!
    • @Jigar Joshi:您正在修改时间点,而不是修改它的显示方式。您的 cal 对象不代表 {13:00 in Germany, 11:00 in Greenwich} 的时间点 - 它代表 {11:00 in Germany, 09:00 in Greenwich}。我不认为这是意图。
    • 我认为这就是 OP 想要的
    • @JigarJoshi,您好,您知道如何将 UTC 时间转换为 GMT 时间吗?
    【解决方案3】:

    java.time

    使用现代日期时间 API java.time,有很多方法可以做到这一点:

    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 = "2011-07-18 13:00:00";
    
            DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss", Locale.ENGLISH);
    
            LocalDateTime ldt = LocalDateTime.parse(strDateTime, dtf);
    
            // Using ZoneId.of("Europe/Berlin") for the demo. Change it to
            // ZoneId.systemDefault()
            Instant instant = ldt.atZone(ZoneId.of("Europe/Berlin")).toInstant();
    
            ZonedDateTime zdtUtc = instant.atZone(ZoneId.of("Etc/UTC"));
    
            System.out.println(zdtUtc.format(dtf)); // 2011-07-18 11:00:00
        }
    }
    
    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 = "2011-07-18 13:00:00";
    
            DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss", Locale.ENGLISH);
    
            LocalDateTime ldt = LocalDateTime.parse(strDateTime, dtf);
    
            // Using ZoneId.of("Europe/Berlin") for the demo. Change it to
            // ZoneId.systemDefault()
            Instant instant = ldt.atZone(ZoneId.of("Europe/Berlin")).toInstant();
    
            ZonedDateTime zdtUtc = ZonedDateTime.ofInstant(instant, ZoneId.of("Etc/UTC"));
    
            System.out.println(zdtUtc.format(dtf)); // 2011-07-18 11:00:00
        }
    }
    
    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 = "2011-07-18 13:00:00";
    
            DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss", Locale.ENGLISH);
    
            LocalDateTime ldt = LocalDateTime.parse(strDateTime, dtf);
    
            // Using ZoneId.of("Europe/Berlin") for the demo. Change it to
            // ZoneId.systemDefault()
            ZonedDateTime zdtPak = ldt.atZone(ZoneId.of("Europe/Berlin"));
    
            ZonedDateTime zdtUtc = zdtPak.withZoneSameInstant(ZoneId.of("Etc/UTC"));
    
            System.out.println(zdtUtc.format(dtf)); // 2011-07-18 11:00:00
        }
    }
    
    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 = "2011-07-18 13:00:00";
    
            // Using ZoneId.of("Europe/Berlin") for the demo. Change it to
            // ZoneId.systemDefault()
            DateTimeFormatter dtfInput = DateTimeFormatter.ofPattern("u-M-d H:m:s", Locale.ENGLISH)
                                            .withZone(ZoneId.of("Europe/Berlin"));
    
            ZonedDateTime zdtPak = ZonedDateTime.parse(strDateTime, dtfInput);
    
            ZonedDateTime zdtUtc = zdtPak.withZoneSameInstant(ZoneId.of("Etc/UTC"));
    
            DateTimeFormatter dtfOutput = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss", Locale.ENGLISH);
            System.out.println(zdtUtc.format(dtfOutput)); // 2011-07-18 11:00:00
        }
    }
    

    通过 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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-11-06
      • 2014-02-23
      • 1970-01-01
      • 1970-01-01
      • 2016-10-25
      • 2018-12-05
      • 2023-03-30
      • 1970-01-01
      相关资源
      最近更新 更多