【问题标题】:Timezone CEST to GMT时区 CEST 到 GMT
【发布时间】:2018-12-25 00:16:21
【问题描述】:

我必须以这种格式输入日期时间:

"2018-07-17T12:16:50.52Z"

因此我正在使用:

private static final SimpleDateFormat LIVETRACK_DATE_TIME_FORMATTER =
  new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");

DATE_TIME_FORMATTER.parse(timeFrameFrom);

但是当我运行测试用例时出现以下错误:

Tue Jul 17 1[2:20:50 CES]T 2018> but was:<Tue Jul 17 1[0:20:50 GM]T 2018>

这是否意味着我应该将日期转换为 GMT 格式? 如何转换?

【问题讨论】:

  • 我建议你避免使用SimpleDateFormat 类。它不仅过时了,而且出了名的麻烦。今天我们在java.time, the modern Java date and time API 中做得更好。也不要将Z 硬编码为格式模式字符串中的文字。这是一个 UTC 偏移量,需要这样解析,否则会得到不正确的结果。
  • 您的代码不会生成单元测试报告为观察结果的Tue Jul 17 10:20:50 GMT 2018 Uhr,至少不会产生“Uhr”。请问create a Minimal, Complete, and Verifiable example可以吗?然后我们可以更好地帮助您。
  • 你的例子中的方括号是什么?错字?
  • @BasilBourque 在比较预期字符串和实际字符串时,JUnit(可能还有其他测试框架?)在不同的部分周围插入方括号。所以显然测试比较了字符串,但DATE_TIME_FORMATTER.parse 没有产生字符串,所以我们还没有被告知。

标签: java date datetime timezone gmt


【解决方案1】:
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern(
            "EEE MMM dd HH:mm:ss zzz yyyy 'Uhr'", Locale.ROOT);

    String input = "2018-07-17T12:16:50.52Z";
    ZonedDateTime dateTime = Instant.parse(input)
            .atZone(ZoneId.of("Europe/Berlin"));
    String output = dateTime.format(formatter);
    System.out.println(output);

输出:

2018 年 7 月 17 日星期二 14:16:50 CEST Uhr

您的测试用例期望得到错误的结果。输入字符串中的 Z 表示 UTC(从 UTC 或所谓的祖鲁时区偏移零)。 UTC 时间 12:16:50.52 与中欧夏令时间 (CEST) 的 14:16:50.52 相同。所以要求Tue Jul 17 12:20:50 CEST 2018 Uhr 是错误的。

在您的代码中,您将Z 硬编码为文字,而不是将其解析为应有的偏移量。有趣的是,这产生了单元测试预期的错误时间点,只是不在预期的时区。这可能Date.toString 使用您的JVM 的时区设置和期望这是CEST 的测试有关,而实际上它是GMT。但是,您的 SimpleDateFormat 没有使用 GMT 来解析字符串(可能是 CEST),因此您没有向我们提供足够的信息来解释测试中发生的所有事情。 SimpleDateFormat 将使用相同的 JVM 设置,除非您已明确设置其时区,这在您发布的代码中不会发生。

链接:Oracle tutorial: Date Time解释如何使用java.time

【讨论】:

    【解决方案2】:

    如果您使用的是 Java8,您可以使用 java.time API,您可以使用默认日期时间格式 Instant 解析您的字符串:

    ZonedDateTime zdt = Instant.parse("2018-07-17T12:16:50.52Z")
            .atZone(ZoneId.of("Europe/Berlin"));
    

    输出

    2018-07-17T14:16:50.520+02:00[Europe/Berlin]
    

    【讨论】:

    • 但是 Z 表示 GMT 时区对吗?我想要 2018 年 7 月 17 日星期二 [0:20:50 GM]T 的时间
    • @pgman 你的意思是ZonedDateTime zdt = Instant.parse("2018-07-17T12:16:50.52Z").atZone(ZoneId.of("GMT")); 或者只是Instant ins = Instant.parse("2018-07-17T12:16:50.52Z"); 我不明白你在说什么!
    【解决方案3】:

    这是否意味着我应该将日期转换为 GMT 格式??

    不,这意味着不应将“Z”视为像“T”那样的常量分隔符,而应将其视为指示日期时区的完整字段。其中 Z 表示 GMT 时区。

    你的格式真的应该是

    "yyyy-MM-dd'T'HH:mm:ss.SSX"
    

    这将使 SimpleDateFormat 识别 Z 表示 GMT 时区,因此它生成的 Date 将与 GMT 时区对齐。将其转换为字符串并因此转换为德国时区时,它将添加差异并产生预期的结果。

    话虽如此,更好的解决方案是从过时的 java.util.Date 和 SimpleDateFormat 类继续前进,并改用 Java 8 的 java.time.* API。请参阅其他答案以获取灵感。

    【讨论】:

    • 使用这种格式只会将小时数增加 2 小时,不会转换为 GMT
    • 你的意思是使用 Z 表示 GMT?在这里,我的格式实际上并没有转换为格林威治标准时间?但是通过将这种格式与 SSX 一起使用,它只会将小时数增加 2 小时,而不会转换为 GMT
    • @pgman 与 java.util.Date 没有“转换为 GMT”之类的东西。此类不包含有关时区的信息。它代表了一个瞬间,不管这个瞬间在纽约、柏林或格林威治如何发音。那里没有时区。这意味着当将 java.util.Date 转换为 String 或从 String 转换时,需要指定一个时区来告诉世界上的哪个瞬间是这样写的(因为它在不同的时区会以不同的方式写成)。在这里,您的测试表明他们期望日期写为 CEST。所以,让他们拥有它。
    【解决方案4】:

    以下是将日历中的日期转换为不同时区的示例。

    TimeZone tzLA = TimeZone.getTimeZone("America/Los_Angeles");
        TimeZone tzIN = TimeZone.getTimeZone("Asia/Calcutta");
    
        Calendar calendar = new GregorianCalendar();
    
        calendar.setTimeZone(tzLA);
    
        long timeLA = calendar.getTimeInMillis();
    
        System.out.println("Time at America in milliseconds = " +timeLA);
        System.out.println("Hour at America = " +calendar.get(Calendar.HOUR_OF_DAY));
    
        calendar.setTimeZone(tzIN);
    
        long timeIN = calendar.getTimeInMillis();
        System.out.println("Time at Asia in millis = " + timeIN);
        System.out.println("Hour at Asia = " + calendar.get(Calendar.HOUR_OF_DAY));
    

    这是输出。

    Time at America in milliseconds = 1515136660357
    Hour at America = 23
    Time at Asia in millis = 1515136660357
    Hour at Asia = 12
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-02-17
      • 2012-12-01
      • 2013-04-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多