简体   繁体   English

Java:使用日期对象的时区缩写解析日期字符串

[英]Java: Parse Date String with timezone abbreviations to Date object

I need to parse a date string with timezone to Date object. 我需要将带时区的日期字符串解析为Date对象。 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" . 当前输出: "Mon Apr 30 09:00:00 PDT 2018" Expected Output: "Mon Apr 30 05:30:00 PDT 2018 . 预期输出: "Mon Apr 30 05:30:00 PDT 2018

That's because timezone's abbreviations such as IST are ambiguous . 这是因为IST等时区的缩写不明确 IST is used in India, Israel and Ireland , and SimpleDateFormat assumes some of them as default, in obscure and undocumented ways (AFAIK). IST印度,以色列和爱尔兰使用SimpleDateFormat以默默无闻的方式(AFAIK)将其中的一些假定为默认值。 Actually, according to javadoc : "support of abbreviations is for JDK 1.1.x compatibility only and full names should be used" . 实际上, 根据javadoc“缩写的支持仅出于JDK 1.1.x兼容性,应使用全名”

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 . 始终使用Continent / Region格式的名称,例如Asia/Kolkata Those names are IANA's timezones names , and they are not ambiguous, so this make things work. 这些名称是IANA的时区名称 ,并且它们不是模棱两可的,因此这使事情变得可行。

java.time API java.time API

If you're using Java 8 or higher, switch to the java.time API , which is much better. 如果您使用的是Java 8或更高版本,请切换到java.time API ,这会更好。 For Java 7 or lower, there's the Threeten Backport with the same classes and functionality. 对于Java 7或更低版​​本,存在Threeten Backport ,它们具有相同的类和功能。

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

If you still need to use java.util.Date , it's easy to convert: 如果仍然需要使用java.util.Date ,则很容易转换:

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

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

The resultant Date object will not hold any timezone information. 结果Date对象将不包含任何时区信息。 See the similar query in this stackoverflow thread 在此stackoverflow线程中查看类似的查询

You might be getting the correct date but in your JVM's current timezone. 您可能会获得正确的日期,但使用的是JVM的当前时区。

In case if you are using Java 8, then there's a provision of Date object with timezone. 如果您使用的是Java 8,则提供带有时区的Date对象。 Look at ZonedDateTime , but for this you need a different kind of formatter while parsing ( DateTimeFormatter ) 看一下ZonedDateTime ,但是为此您需要在解析时使用另一种格式化程序( DateTimeFormatter

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM