Java:将带有时区缩写的日期字符串解析为日期对象 [英] Java: Parse Date String with timezone abbreviations to Date object

查看:84
本文介绍了Java:将带有时区缩写的日期字符串解析为日期对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

MM/dd/yyyy hh:mm a z"(例如: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.

解决方案

那是因为 timezone 的缩写如 IST 是暧昧.IST 用于印度、以色列和爱尔兰,并且 SimpleDateFormat 以模糊和未记录的方式 (AFAIK) 假定其中一些为默认值.实际上,根据javadoc:支持缩写仅适用于 JDK 1.1.x 兼容性,应使用全名".

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

SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy hh:mm a z");sdf.setTimeZone(TimeZone.getTimeZone("亚洲/加尔各答"));日期 date = sdf.parse("04/30/2018 06:00 PM IST");

始终使用 Continent/Region 格式的名称,例如 Asia/Kolkata.这些名称是IANA 的时区名称,并且它们没有歧义,所以这可以使事情顺利进行.>

java.time API

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

在此 API 中,您必须设置一个包含所有首选时区的列表,以便在名称不明确时使用,例如 IST:

//首选区域设置preferredZones = new HashSet<>();preferredZones.add(ZoneId.of("亚洲/加尔各答"));DateTimeFormatter fmt = new DateTimeFormatterBuilder()//日期和时间.appendPattern("MM/dd/yyyy hh:mm a")//区域(使用一组首选区域).appendZoneText(TextStyle.SHORT, preferredZones)//使用英语,因为不同的语言环境会影响时区名称.toFormatter(Locale.ENGLISH);ZonedDateTime zdt = ZonedDateTime.parse("04/30/2018 06:00 PM IST", fmt);

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

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

I need to parse a date string with timezone to Date object. The input date string pattern is:

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

I have used below given code. But it returns incorrect date as output.

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

Current Output: "Mon Apr 30 09:00:00 PDT 2018". Expected Output: "Mon Apr 30 05:30:00 PDT 2018.

解决方案

That's because timezone's abbreviations such as IST are ambiguous. IST is used in India, Israel and Ireland, and SimpleDateFormat assumes some of them as default, in obscure and undocumented ways (AFAIK). Actually, according to javadoc: "support of abbreviations is for JDK 1.1.x compatibility only and full names should be used".

One way to make it work is to arbitrarily choose a timezone and set it in the formatter:

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");

Always use names in the format Continent/Region, such as Asia/Kolkata. Those names are IANA's timezones names, and they are not ambiguous, so this make things work.

java.time API

If you're using Java 8 or higher, switch to the java.time API, which is much better. For Java 7 or lower, there's the Threeten Backport with the same classes and functionality.

In this API, you must set a list of all preferred timezones to be used in case of ambiguous names like 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);

If you still need to use java.util.Date, it's easy to convert:

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

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

这篇关于Java:将带有时区缩写的日期字符串解析为日期对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆