Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
536 views
in Technique[技术] by (71.8m points)

timezone - Joda DateTimeFormatter.parseDateTime is failing for General time zone('z')

Confused with the use of General time zone('z'). Joda is failing in below sample code. Can somebody help me to understand why the behavior is like this? How can I parse a date in differnt timezone using this format in Joda?

    public static void main(String[] args) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd G 'at' HH:mm:ss z");
        System.out.println(sdf.parse("2019.09.17 AD at 15:29:00 IST"));

        DateTimeFormatter pattern = DateTimeFormat.forPattern("yyyy.MM.dd G 'at' HH:mm:ss z");
        DateTime dateCtxParamDateTimeObj = pattern.parseDateTime("2019.09.17 AD at 15:29:00 IST");
        System.out.println(dateCtxParamDateTimeObj.toDate());
    }

Output

Tue Sep 17 15:29:00 IST 2019
Exception in thread "main" java.lang.IllegalArgumentException: Invalid format: "2019.09.17 AD at 15:29:00 IST" is malformed at "IST"
    at org.joda.time.format.DateTimeFormatter.parseDateTime(DateTimeFormatter.java:945)
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Edit: You need to tell Joda-Time what you mean by IST

Thanks go to HarryQ, who pointed me here to where this is documented.

    DateTimeUtils.setDefaultTimeZoneNames(Collections.singletonMap(
            "IST", DateTimeZone.forID("Europe/Dublin")));

    DateTimeFormatter pattern = DateTimeFormat.forPattern("yyyy.MM.dd G 'at' HH:mm:ss z");
    DateTime dateCtxParamDateTimeObj = pattern.parseDateTime("2019.09.17 AD at 15:29:00 IST");

    System.out.println(dateCtxParamDateTimeObj);

The output from this snippet is:

2019-09-17T15:29:00.000+01:00

Lowercase z in a format pattern string works differently when formatting and when parsing in Joda-Time. Joda-Time can format time zone names for all available time zones, but with default settings it can only parse a few back. Which it can parse is controlled by the default time zone names of the DateTimeUtils class. It comes with a map of 10 time zone abbreviations as documented in the DateTimeUtils.getDefaultTimeZoneNames method (link at the bottom): CST, MDT, GMT, PST, PDT, UTC, EDT, CDT, EST and MST. We can substitute with a different map. What I am doing above is substituting with a map of just one abbreviation for the illustration. This risks breaking other code, so a better approach for most purposes would be to build a map containing both the abbreviations that were there before and that or those that we want to be able to parse too.

The map I provided above assumes that IST is for Irish Summer Time (and on September 17, 2019, Ireland was using summer time (DST)). You hardly meant Israel Standard Time because Israel too used summer time, IDT. A third likely understanding is India Standard Time:

    DateTimeUtils.setDefaultTimeZoneNames(Collections.singletonMap(
            "IST", DateTimeZone.forID("Asia/Kolkata")));

2019-09-17T15:29:00.000+05:30

You notice that we now get offset +05:30 instead of +01:00, so a different point in time. The ambiguity may also be the reason why Joda-Time refuses to make its own assumption about what you intended and therefore needs us to tell it before it can parse the string.

Original answer

It’s a documented limitation in Joda-Time. From the documentation of DateTimeFormat:

Zone names: Time zone names ('z') cannot be parsed.

Also note that IST and many other time zone abbreviations are ambiguous, so if there is any way you can avoid parsing one, by all means do avoid it. IST may be for Irish Summer Time, Israel Standard Time or India Standard Time, and there’s no guarantee which of them you get, or if you may even get Iceland Standard Time.

If you insist, one possible solution is to follow the advice from the Joda-Time homepage:

Note that Joda-Time is considered to be a largely “finished” project. No major enhancements are planned. If using Java SE 8, please migrate to java.time (JSR-310).

The DateTimeFormatter class of java.time (the modern Java date and time API) will attempt to parse a time zone abbreviation. Good luck.

Links

Joda-Time

Others

  • My answer here shows how to control the interpretation of IST while parsing when using java.time.

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...