我需要将带有时区的日期字符串解析为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
。
答案 0 :(得分:5)
那是因为timezone's abbreviations such as IST are ambiguous。 IST 在India, 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 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());
答案 1 :(得分:0)
生成的Date对象不会包含任何时区信息。请参阅此stackoverflow thread
中的类似查询您可能会在JVM的当前时区获得正确的日期。
如果您使用的是Java 8,那么可以使用带有时区的Date对象。查看ZonedDateTime,但为此,您需要在解析时使用不同类型的格式化程序(DateTimeFormatter)