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());
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)
Locale.getDefault()
is useless in this caseBy 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.
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.
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]
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.