javaandroiddatedatetime-parsingparseexception

java.text.ParseException: Unparseable date: Mon Apr 08 00:00:00 IST 2013


I am trying to parse date with Android build on 4.2.2 and running on emulator of 2.2, its throwing exception. Please help!! here is my code

String date = "Mon Apr 08 00:00:00 IST 2013";
DateFormat parserSDF = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy",Locale.getDefault());
parserSDF.setTimeZone(TimeZone.getTimeZone("IST"));
Calendar calendarEvent = Calendar.getInstance();
Date dateStr = null;
try {
    dateStr = parserSDF.parse(date);
    calendarEvent.setTime(dateStr);
} catch (Exception e) {
    e.printStackTrace();
}
System.out.println("d>>"+calendarEvent.getTime());

Stack trace

04-17 13:01:42.658: W/System.err(1088): java.text.ParseException: Unparseable date: Mon Apr 08 00:00:00 IST 2013
04-17 13:01:42.667: W/System.err(1088):     at java.text.DateFormat.parse(DateFormat.java:645)
04-17 13:01:42.667: W/System.err(1088):     at com.example.datetest.MainActivity.onCreate(MainActivity.java:26)
04-17 13:01:42.667: W/System.err(1088):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
04-17 13:01:42.667: W/System.err(1088):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)
04-17 13:01:42.667: W/System.err(1088):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
04-17 13:01:42.667: W/System.err(1088):     at android.app.ActivityThread.access$2300(ActivityThread.java:125)
04-17 13:01:42.667: W/System.err(1088):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)
04-17 13:01:42.667: W/System.err(1088):     at android.os.Handler.dispatchMessage(Handler.java:99)
04-17 13:01:42.667: W/System.err(1088):     at android.os.Looper.loop(Looper.java:123)
04-17 13:01:42.667: W/System.err(1088):     at android.app.ActivityThread.main(ActivityThread.java:4627)
04-17 13:01:42.667: W/System.err(1088):     at java.lang.reflect.Method.invokeNative(Native Method)
04-17 13:01:42.678: W/System.err(1088):     at java.lang.reflect.Method.invoke(Method.java:521)
04-17 13:01:42.678: W/System.err(1088):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
04-17 13:01:42.678: W/System.err(1088):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
04-17 13:01:42.678: W/System.err(1088):     at dalvik.system.NativeStart.main(Native Method)

Solution

  • Locale.getDefault() is useless in this case

    By default, the date-time parsing/formatting API uses the default Locale (i.e. the Locale set in your JVM) when you do not specify a Locale; so, Locale.getDefault() is useless in this case.

    Since your date-time string is in English, you should use an English-Locale; otherwise, your parsing/formatting code will work only when executed on a JVM with an English-Locale as the default.

    Check this answer to learn more about it.

    Avoid using abbreviations for time zone ID

    Given below is an excerpt from the legacy TimeZone documentation:

    Three-letter time zone IDs

    For compatibility with JDK 1.1.x, some other three-letter time zone IDs (such as "PST", "CTT", "AST") are also supported. However, their use is deprecated because the same abbreviation is often used for multiple time zones (for example, "CST" could be U.S. "Central Standard Time" and "China Standard Time"), and the Java platform can then only recognize one of them.

    So, educate the publisher of a date-time string with such an abbreviation about providing the full zone ID e.g. "Asia/Kolkata".

    java.time

    In March 2014, Java 8 introduced the modern, java.time date-time API which supplanted the error-prone legacy java.util date-time API. Any new code should use the java.time API.

    Solution using modern date-time API

    Given below is an expert from DateTimeFormatterBuilder#appendZoneText(TextStyle textStyle, Set<ZoneId> preferredZones) documentation:

    During parsing, either the textual zone name, the zone ID or the offset is accepted. Many textual zone names are not unique, such as CST can be for both "Central Standard Time" and "China Standard Time". In this situation, the zone id will be determined by the region information from formatter's locale and the standard zone id for that area, for example, America/New_York for the America Eastern zone. This method also allows a set of preferred ZoneId to be specified for parsing. The matched preferred zone id will be used if the textural zone name being parsed is not unique.

    So, if you get a date-time string with an ambiguous abbreviated time zone ID, you can use DateTimeFormatterBuilder#appendZoneText to define these abbreviations.

    Demo:

    class Main {
        public static void main(String[] args) {
            Set<ZoneId> preferredZones = Set.of(ZoneId.of("Asia/Kolkata"));
            DateTimeFormatter dtf = new DateTimeFormatterBuilder()
                    .appendPattern("EEE MMM dd HH:mm:ss")
                    .appendLiteral(' ')
                    .appendZoneText(TextStyle.SHORT, preferredZones)
                    .appendLiteral(' ')
                    .appendPattern("uuuu")
                    .toFormatter(Locale.ENGLISH);
    
            ZonedDateTime zdt = ZonedDateTime.parse("Mon Apr 08 00:00:00 IST 2013", dtf);
            System.out.println(zdt);
        }
    }
    

    Output:

    2013-04-08T00:00+05:30[Asia/Kolkata]
    

    Online Demo

    Note: If for some reason, you need an instance of java.util.Date, let java.time API do the heavy lifting of parsing your date-time string and convert zdt from the above code into a java.util.Date instance using Date date = Date.from(zdt.toInstant()).

    Learn more about the modern Date-Time API from Trail: Date Time.