Java:解析日期字符串,时区缩写为Date对象

SPS*_*SPS 1 java timezone date simpledateformat datetime-parsing

我需要将带有时区的日期字符串解析为Dateobject.输入日期字符串模式为:

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

我使用下面给出的代码.但它返回错误的日期作为输出.

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

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

uil*_*lon 5

那是因为时区的缩写如IST是模棱两可的.IST印度,以色列和爱尔兰使用,并SimpleDateFormat假设其中一些是默认的,采用模糊和无证的方式(AFAIK).实际上,根据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");
Run Code Online (Sandbox Code Playgroud)

始终使用Continent/Region格式的名称,例如Asia/Kolkata.这些名称是IANA的时区名称,并且它们并不含糊,因此这可以使事情发挥作用.

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);
Run Code Online (Sandbox Code Playgroud)

如果您仍然需要使用java.util.Date,它很容易转换:

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

// Java 7 (Threenten Backport)
Date d = DateTimeUtils.toDate(zdt.toInstant());
Run Code Online (Sandbox Code Playgroud)