【问题标题】:Java: Parse Date String with timezone abbreviations to Date objectJava:将带有时区缩写的日期字符串解析为日期对象
【发布时间】:2018-09-11 17:16:14
【问题描述】:

我需要将带有时区的日期字符串解析为Date 对象。输入日期字符串模式为:

"MM/dd/yyyy hh:mm a z"  (eg: 04/30/2018 06:00 PM IST).

我使用了下面给出的代码。但它返回不正确的日期作为输出。

new SimpleDateFormat("MM/dd/yyyy hh:mm a z").parse("04/30/2018 06:00 PM IST")

电流输出:"Mon Apr 30 09:00:00 PDT 2018"。 预期输出:"Mon Apr 30 05:30:00 PDT 2018

【问题讨论】:

  • 你当前的输出是什么,你期望什么?
  • "MM/dd/yyyy hh:mm a z" 应该被用来代替 "MM/dd/yyyy HH:mm a z"。 H - 一天中的小时 (0-23)。 h - 上午/下午 (1-12) 小时
  • @MikitaHerasiutsin:谢谢。我只用了hh。这是一个拼写错误。
  • @NisheethShah:当前输出:“2018 年 4 月 30 日星期一 09:00:00 PDT”预期输出:“2018 年 4 月 30 日星期一 05:30:00 PDT”
  • @Salman 将澄清发布为对您的问题的编辑,而不是评论。您的读者无需梳理评论即可理解您的问题。

标签: java date timezone simpledateformat datetime-parsing


【解决方案1】:

那是因为timezone's abbreviations such as IST are ambiguousISTIndia, Israel and Ireland 中使用,SimpleDateFormat 以模糊和未记录的方式 (AFAIK) 将其中一些假定为默认值。实际上,according to javadoc“支持缩写只是为了兼容 JDK 1.1.x,应该使用全名”

使其工作的一种方法是任意选择一个时区并将其设置在格式化程序中:

SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy hh:mm a z");
sdf.setTimeZone(TimeZone.getTimeZone("Asia/Kolkata"));
Date date = sdf.parse("04/30/2018 06:00 PM IST");

始终使用 大陆/地区 格式的名称,例如 Asia/Kolkata。这些名字是IANA's timezones names,而且它们并没有歧义,所以这样就可以了。

java.time API

如果您使用的是 Java 8 或更高版本,请切换到 java.time API,这样会更好。对于 Java 7 或更低版本,Threeten Backport 具有相同的类和功能。

在此 API 中,您必须设置所有首选时区的列表,以防出现 IST 等模糊名称:

// prefered zones
Set<ZoneId> preferredZones = new HashSet<>();
preferredZones.add(ZoneId.of("Asia/Kolkata"));

DateTimeFormatter fmt = new DateTimeFormatterBuilder()
    // date and time
    .appendPattern("MM/dd/yyyy hh:mm a ")
    // zone (use set of prefered zones)
    .appendZoneText(TextStyle.SHORT, preferredZones)
    // use English, because different locales can affect timezones names
    .toFormatter(Locale.ENGLISH);

ZonedDateTime zdt = ZonedDateTime.parse("04/30/2018 06:00 PM IST", fmt);

如果你还需要使用java.util.Date,很容易转换:

// Java 8
Date d = Date.from(zdt.toInstant());

// Java 7 (Threenten Backport)
Date d = DateTimeUtils.toDate(zdt.toInstant());

【讨论】:

  • 谢谢 :) 我已经实现了您的第一种方法,并且按预期工作。
【解决方案2】:

生成的 Date 对象不会保存任何时区信息。请参阅此stackoverflow thread 中的类似查询

您可能会得到正确的日期,但在您的 JVM 的当前时区中。

如果您使用的是 Java 8,则可以提供带有时区的 Date 对象。查看ZonedDateTime,但为此您在解析时需要一种不同类型的格式化程序(DateTimeFormatter

【讨论】:

    猜你喜欢
    • 2010-12-15
    • 1970-01-01
    • 2022-01-24
    • 1970-01-01
    • 2012-02-09
    • 1970-01-01
    • 2020-09-24
    • 2013-06-05
    • 1970-01-01
    相关资源
    最近更新 更多