时区 CEST 到 GMT
Posted
技术标签:
【中文标题】时区 CEST 到 GMT【英文标题】:Timezone CEST to 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
没有产生字符串,所以我们还没有被告知。
【参考方案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
【讨论】:
以上是关于时区 CEST 到 GMT的主要内容,如果未能解决你的问题,请参考以下文章