Trying to parse a datetime in PDT to a ZonedDateTime representation
我应该如何解析pdt时区中的日期时间值?
1 | 06/24/2017 07:00 AM (PDT) |
我想维护时区,这样我就可以根据网站访问者的偏好在其他时区表示时间。
我尝试使用
1 | java.time.ZonedDateTime.parse("06/24/2017 07:00 AM (PDT)") |
错误是:
1 2 3 4 5 | java.time.format.DateTimeParseException: Text '06/24/2017 07:00 AM (PDT)' could not be parsed at index 0 at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1949) at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1851) at java.time.ZonedDateTime.parse(ZonedDateTime.java:597) at java.time.ZonedDateTime.parse(ZonedDateTime.java:582) ... 29 elided |
另外,你同意我应该使用
由于您的格式是非标准格式,因此需要将其指定给解析器:
1 2 3 4 | ZonedDateTime.parse( "06/24/2017 07:00 AM (PDT)", DateTimeFormatter.ofPattern("MM/dd/yyyy HH:mm a (zzz)") ); |
其他答案已经很好地涵盖了你所得到的错误。
Also, do you agree that I should be using a
ZonedDateTime ?
是和否。您的字符串应该被解析成一个
为什么这样做?首先,通常的做法是存储
如果我正确理解您的情况,您需要存储时间点,以便显示到多个时区。您不需要存储最初输入时间的时区(如PDT,除了PDT不是真正的完整时区之外)。
这里有两个更好的答案:当数据依赖于日期时间时,在数据库中保存日期时间和时区信息的最佳实践。
需要注意的一个细节是,API使用IANA时区名称(始终采用
API对特定的ID进行了一些异常,并为它们提供了一些默认值。对于
另一个细节是在下面的例子中,我在模式中使用了小写的
如果使用大写的
所以代码如下:
1 2 3 | DateTimeFormatter fmt = DateTimeFormatter.ofPattern("MM/dd/yyyy hh:mm a (zzz)"); ZonedDateTime z = ZonedDateTime.parse("06/24/2017 07:00 AM (PDT)", fmt); System.out.println(z); |
输出是:
2017-06-24T07:00-07:00[America/Los_Angeles]
但并非所有3个字母的时区名称都能被API识别,并会引发异常。
不管怎样,还有其他的时区也在PDT中(如
1 2 3 4 5 6 7 8 9 10 11 12 13 | Set<ZoneId> preferredZones = new HashSet<>(); // set America/Vancouver as preferred zone preferredZones.add(ZoneId.of("America/Vancouver")); DateTimeFormatter fmt = new DateTimeFormatterBuilder() // pattern .appendPattern("MM/dd/yyyy hh:mm a (") // append timezone with set of prefered zones .appendZoneText(TextStyle.SHORT, preferredZones) // finish the pattern .appendPattern(")") // create formatter .toFormatter(); System.out.println(ZonedDateTime.parse("06/24/2017 07:00 AM (PDT)", fmt)); |
API将使用首选区域集(在本例中为
2017-06-24T07:00-07:00[America/Vancouver]
不清楚输入
1 2 3 4 | // parse the input string ZonedDateTime z = ZonedDateTime.parse("06/24/2017 07:00 AM (PDT)", fmt); // convert to another timezone ZonedDateTime other = z.withZoneSameInstant(ZoneId.of("America/Sao_Paulo")); // 2017-06-24T11:00-03:00[America/Sao_Paulo] |
但是,如果您可以控制输出,那么最好(IMO)在内部与UTC(
1 2 3 4 5 6 7 8 | // convert ZonedDateTime to instant ZonedDateTime z = // parse input // convert to UTC (Instant is always in UTC) Instant instant = z.toInstant(); // internally work with instant (as it's always in UTC) // convert instant to some timezone only when necessary (like displaying to users) ZonedDateTime converted = instant.atZone(ZoneId.of("Europe/London")); |