SimpleDateFormat解析方法之谜

SimpleDateFormat parse method mystery

我知道 SimpleDateFormat.parse 依赖日历 API,它取决于本地 JVM 时区(计算机的)。假设 JVM 时区是 IST。

SimpleDateFormat srcDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
srcDateFormat.setTimeZone(TimeZone.getTimeZone("EST"));
Date objDt = srcDateFormat.parse("2018-10-16 11:28:25"); //Time : 21:58:25 

从输出来看,它似乎从 EST 转换为 IST(JVM 本地时区)。

SimpleDateFormat srcDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
srcDateFormat.setTimeZone(TimeZone.getTimeZone("IST"));
Date objDt = srcDateFormat.parse("2018-10-16 11:28:25"); //Time : 11:28:25 

在这种情况下它保持时间不变。在这种情况下,我将时区设置为与 JVM 本地时区相同。

请帮助我理解 parse 方法的行为。不过,我很想知道这种行为背后的原因。 我知道 java.util.Datejava.text.SimpleDateFormat 遗留 类 现在已经过时了。

参考文献:

首先,DateSimpleDateFormat 是遗留的 class 并且现在已过时,您是对的。所以我建议你不要使用它们,而是使用 java.time,现代的 Java 日期和时间 API。在许多优点中,它对时区之间的转换更加明确,我希望这能帮助您理解代码的作用。

其次,您做了许多不正确或至少不充分的事情:

  1. 不要将日期时间存储为字符串。始终将它们作为日期时间对象存储在 Java 中。当您这样做时,您永远不需要将日期时间字符串从一个区域转换为另一个区域。 Instant(来自 java.time 的 class)是一个时间点,据我所知,您应该在此处使用。
  2. 不要依赖三个字母的时区缩写。其中很多是模棱两可的,包括 IST 和 EST,后者不是真正的时区,所以你在每年的这个时候得到的(当 America/New_York 时区使用 EDT 而不是 EST),我不知道。
  3. 重复一遍,使用现代 classes,而不是过时的。

出于好奇发生了什么事?

一个老式的Date表示一个独立于时区的时间点(在内部它存储它的值作为自纪元以来的毫秒计数,但这是一个我们不需要知道的实现细节或关心自己)。

在您的第一个示例中,您的字符串被解析为对应于 16:28:25 UTC、印度 21:58:25、纽约 12:28:25 或 11:28:25 的时间点在牙买加。我提到牙买加是因为它是少数几个全年都使用东部标准时间 (EST) 的地方之一。大多数使用 EST 的地点仅在冬季使用,而不是每年的这个时候。当您在调试器中查看 Date 时,调试器会调用 Date 上的 toString 以获取要显示的字符串。 toString 依次使用 JVM 的时区来生成字符串。在你的情况下它是 Asia/Kolkata,这就是你得到 21:58:25.

的原因

在第二种情况下,相同的字符串被解析为对应于 05:58:25 UTC、印度 11:28:25、纽约 01:58:25 或 00:58:25 的时间点] 在牙买加。您的调试器再次调用 toString,它再次使用您的 JVM 时区并转换回 11:28:25 IST。当您在同一时区解析和打印时,您会得到同一天的时间。

链接