Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

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

android - Getting error java.text.ParseException: Unparseable date: (at offset 0) even if the Simple date format and string value are identical

I'm always getting the parse exception even if the format to check and the string value are same. Here is the code:

String format = "EEE MMM dd HH:mm:ss z yyyy";
String value = "Mon Sep 18 10:30:06 MST 2017";
public static boolean isValidFormat(String format, String value) {
    Date date = null;
    try {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        date = sdf.parse(value); // here it breaks
        if (!value.equals(sdf.format(date))) {
            date = null;
        }
    } catch (ParseException ex) {
        ex.printStackTrace(); //java.text.ParseException: Unparseable date: 
                                "Mon Sep 18 10:30:06 MST 2017" (at offset 0)
    }
    return date != null;
}
Question&Answers:os

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

1 Answer

0 votes
by (71.8m points)

It says that your date-time string is unparseable at index 0. Index 0 is where it says Mon, so the three letter time zone abbreviation is not the first suspect. The locale is. “Mon” works as abbreviation for Monday in English, but not in very many other languages. So if your device has a non-English language setting — maybe it has even been changed recently — this will fully explain your observation.

The shortsighted solution is

        SimpleDateFormat sdf = new SimpleDateFormat(format, Locale.ROOT);

I use Locale.ROOT to mean that no language specific processing should be done. If your string is in English because English is generally the language used in computing around the globe, I would consider this choice appropriate. If on the other hand it is in English because it comes from an English speaking locale, that locale will be the right one to use.

With this change, on my computer your code formats your date into Mon Sep 18 11:30:06 MDT 2017, which, as you can see is not the same as the value we started out from, so your method returns false. My JVM understood MST as Mountain Standard Time, and then assumed summer time (DST) in September and formatted the string accordingly.

ThreeTenABP

That said, Date and SimpleDateFormat are long outdated classes. You should give it a thought to get rid of them and use the modern Java date and time API instead. On Android you get it in the ThreeTenABP, see this question: How to use ThreeTenABP in Android Project. Now you may do:

    DateTimeFormatter dtf = DateTimeFormatter.ofPattern(format, Locale.ROOT);
    try {
        return ZonedDateTime.parse(value, dtf).format(dtf).equals(value); 
    } catch (DateTimeParseException dtpe) {
        dtpe.printStackTrace();
        return false;
    }

This behaves the same as above.

Three letter time zone abbreviations

You should avoid the three and four letter time zone abbreviations where you can. They are not standardized and generally ambiguous. MST, for example, may mean Malaysia Standard Time or Mountain Standard Time. The latter isn’t even a full time zone, since MDT is used for the greater part of the year, which caused the trouble I observed as I said above.

Instead, see if you can get a string in ISO 8601 format, like 2017-09-18T10:30:06+08:00. Second best, just get something unambiguous. One way is to include an offset from UTC rather than a time zone ID (or both).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...