This question already has answers here:
Java - Unparseable date
(3 answers)
Getting error java.text.ParseException: Unparseable date: (at offset 0) even if the Simple date format and string value are identical
(4 answers)
Closed 4 years ago.
I am trying to parse the following date/time:
Wed, 29 Aug 2018 12:56:00 +0200
Currently, I am using the following code which works on my Android emulator but on my actual phone I get a "java.text.ParseException: Unparseable date"
SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z");
this.pubDate = sdf.parse(s_pubDate);
You need to explicitly set the formatter locale, otherwise it would try to pars it based on phone locale and that may cause an error. I think that the cause in your case.
Your emulated device has one locale, while your phone has the one, that can't pars date in such format.
SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z",
**YOUR DESIRED LOCALE**);
java.time
String dateTimeString = "Wed, 29 Aug 2018 12:56:00 +0200";
OffsetDateTime dateTime = OffsetDateTime.parse(
dateTimeString, DateTimeFormatter.RFC_1123_DATE_TIME);
System.out.println(dateTime);
Output from this snippet is:
2018-08-29T12:56+02:00
The format of the string you want to parse is RFC 1123. This format is built into Java, so spares you the trouble of building your own formatter for parsing. Furthermore RFC 1123 is always in English, so there is no risk that your phone’s default locale (or any other locale) interferes.
I am using java.time, the modern Java date and time API. The SimpleDateFormat that you tried to use is not only long outdated, it is also notoriously troublesome.
Question: Can I use java.time on Android?
Yes, java.time works nicely on older and newer Android devices. It just requires at least Java 6.
In Java 8 and later and on newer Android devices (from API level 26, I’m told) the modern API comes built-in.
In Java 6 and 7 get the ThreeTen Backport, the backport of the new classes (ThreeTen for JSR 310; see the links at the bottom).
On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from org.threeten.bp with subpackages.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Java Specification Request (JSR) 310, where java.time was first described.
ThreeTen Backport project, the backport of java.time to Java 6 and 7 (ThreeTen for JSR-310).
ThreeTenABP, Android edition of ThreeTen Backport
Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.
Related
I have obtained a string from an API in form of 2017-04-23T19:47:39+00:00
How do i convert it into date of format "2017-04-23T19:47:39-0000"?
I tried the following but it gave ParseException
String created_at_string = "2017-04-23T19:47:39+00:00";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
Date created_at = sdf.parse(created_at_string);
Exception:
06-22 18:18:32.517 10396-10396/com.harit.abs W/System.err: java.text.ParseException: Unparseable date: ""2018-04-29T10:55:37+00:00""
at java.text.DateFormat.parse(DateFormat.java:358)
at com.harit.abs.Sync_Activity.bu(Sync_Activity.java:169)
at com.harit.abs.Sync_Activity$2.onCompleted(Sync_Activity.java:118)
at com.harit.abs.Sync_Activity$2.onCompleted(Sync_Activity.java:87)
at com.koushikdutta.async.future.SimpleFuture.handleCallbackUnlocked(SimpleFuture.java:107)
at com.koushikdutta.async.future.SimpleFuture.setComplete(SimpleFuture.java:141)
at com.koushikdutta.async.future.SimpleFuture.setComplete(SimpleFuture.java:128)
at com.koushikdutta.ion.IonRequestBuilder$1.run(IonRequestBuilder.java:246)
at com.koushikdutta.async.AsyncServer$RunnableWrapper.run(AsyncServer.java:60)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
Tried what is given in SimpleDateFormat with TimeZone
Still getting the same parse Exception
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.getDefault());
String created_at_string = "2017-04-23T19:47:39+00:00";
Date created_at = sdf.parse(created_at_string);
You don’t need to
The conversion you are asking about could easily be superfluous. You are asking for a string like 2017-04-23T19:47:39-0000. This string is in ISO 8601 format, the international standard format. So depending on your exact situation I would expect a string in ISO 8601 to be fine for you. The string you already got, 2017-04-23T19:47:39+00:00 is in ISO 8601 too! The standard allows for some variations, and one of them is that the colon in the offset is optional. So the first thing I think that you should do is to pass on the string you get and see if that works. In case it doesn’t, read on.
java.time
Your desired conversion goes so smoothly with java.time the modern Java date and time API:
DateTimeFormatter formatterWithoutColon
= DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ssxx");
String createdAtString = "2017-04-23T19:47:39+00:00";
OffsetDateTime dateTime = OffsetDateTime.parse(createdAtString);
String inDesiredFormat = dateTime.format(formatterWithoutColon);
System.out.println(inDesiredFormat);
This prints the desired:
2017-04-23T19:47:39+0000
Please note that we didn’t even need a formatter for parsing the string. OffsetDateTime and many other classes of java.time parse ISO 8601 as their default. Since our requirements for the result are a bit more precise, we use a formatter here. xx gives us the offset without colon, for example +0000.
The Date class that you used is long outdated. So is SimpleDateFormat, and it’s notoriously troublesome too. I suggest you avoid those classes.
Question: Can I use java.time on Android?
Yes, java.time works nicely on older and newer Android devices. It just requires at least Java 6.
In Java 8 and later and on newer Android devices (from API level 26, I’m told) the modern API comes built-in.
In Java 6 and 7 get the ThreeTen Backport, the backport of the new classes (ThreeTen for JSR 310; see the links at the bottom).
On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from org.threeten.bp with subpackages.
The hack
The change you require is very simple, you just want a colon removed. So another, not so nice, but basic and simple solution that doesn’t require ThreeTenABP is a regular expression:
String inDesiredFormat = createdAtString.replaceFirst("([+-]\\d{2}):(\\d{2})$", "$1$2");
This gives the same result as above.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Java Specification Request (JSR) 310, where java.time was first described.
ThreeTen Backport project, the backport of java.timeto Java 6 and 7 (ThreeTen for JSR-310).
ThreeTenABP, Android edition of ThreeTen Backport
Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.
Wikipedia article: ISO 8601
Possibly you could try to set the locale,
SimpleDateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy", Locale.US);
I tried the below code but it gives me the name of the day of week two days ago.
DatePicker picker;
int date = picker.DayOfMonth;
int month = (picker.Month + 1);//month is 0 based
int year = picker.Year;
SimpleDateFormat simpledateformat = new SimpleDateFormat("EEE");
Date dt = new Date(year, month, date);
First convert your Date in to specific Date format using SimpleDateFormat
Use SimpleDateFormat simpleDateFormat = new SimpleDateFormat("EEEE"); to get Day name in week
WHERE EEEE -> Day name in week
SAMPLE CODE
SimpleDateFormat inFormat = new SimpleDateFormat("dd-MM-yyyy");
try {
Date myDate = inFormat.parse(date+"-"+month+"-"+year);
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("EEEE");
String dayName=simpleDateFormat.format(myDate);
} catch (ParseException e) {
e.printStackTrace();
}
SimpleDateFormat dateFormat = new SimpleDateFormat("EEE", Locale.US);
String asWeek = dateFormat.format(dt);
DateTimeFormatter dayOfWeekFormatter
= DateTimeFormatter.ofPattern("EEE", Locale.ENGLISH);
LocalDate date = LocalDate.of(
picker.getYear(), picker.getMonth(), picker.getDayOfMonth());
System.out.println(date.format(dayOfWeekFormatter));
Picking 2018-04-09 this printed
Mon
I am using and recommending java.time, the modern Java date and time API. The Date class is long outdated, and you are using a deprecated constructor. It was deprecated because it works unreliably across time zones, so you shouldn’t. SimpleDateFormat is not only outdated, it is also notoriously troublesome. I recommend you avoid those classes altogether. The modern API is so much nicer to work with.
What went wrong in your code?
You’ve got two bugs apart from using the deprecated Date constructor and the outdated classes:
It’s the Date’s month that is 0-based (not that of DatePicker), so you need to subtract 1, not add 1 (or maybe they are both 0-based??).
The deprecated Date constructor’s year is “1900-based”. This may have seemed a good idea when the class was designed in the 1990’s: you could just specify 95 to get 1995. When you pass 2018 to the constructor, you get year 3918. That’s right. :-(
Question: Can I use java.time on Android?
Yes, java.time works nicely on older and newer Android devices. It just requires at least Java 6.
In Java 8 and later and on newer Android devices (from API level 26, I’m told) the modern API comes built-in.
In Java 6 and 7 get the ThreeTen Backport, the backport of the new classes (ThreeTen for JSR 310; see the links at the bottom).
On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from org.threeten.bp with subpackages.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Java Specification Request (JSR) 310, where java.time was first described.
ThreeTen Backport project, the backport of java.timeto Java 6 and 7 (ThreeTen for JSR-310).
ThreeTenABP, Android edition of ThreeTen Backport
Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.
Calendar calendar = Calendar.getInstance();
DateFormat date4= new SimpleDateFormat("EEEE", Locale.getDefault());
String localTime4 = date4.format(calendar.getTime());
Simple and easy way
just use this
I am getting the above exception while trying to parse. I tried the following date format,
SimpleDateFormat sdf = new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss ", Locale.ENGLISH);
java.time
The SimpleDateFormat class is not only long outdated, it is also notoriously troublesome. I recommend you stop using it and use java.time the modern Java date and time API also known as JSR-310, instead. It is so much nicer to work with.
System.out.println(LocalDateTime.parse("Thu, 7 Dec 2017 07:40:40 ",
DateTimeFormatter.ofPattern("E, d MMM yyyy HH:mm:ss ", Locale.ENGLISH)));
This prints the expected date and time:
2017-12-07T07:40:40
What went wrong
In your format pattern string, you’ve got two spaces before and two spaces after yyyy, where it seems that in your date-time string there is only one space in each of those places. While SimpleDateFormat is infamous for parsing strings that it ought to reject, it does object in this case by throwing the ParseException the message of which you quote in the question title.
If you compare my format pattern string to yours, you will notice I use just one d where you use two. SimpleDateFormat parses 7 with dd where the modern classes are stricter: d matches a date-of-month of either 1 or 2 digits. where dd requires two digits. You may of course exploit this for stricter validation if you need it.
Question: Can I use the modern API with my Java version?
If using at least Java 6, you can.
In Java 8 and later the new API comes built-in.
In Java 6 and 7 get the ThreeTen Backport, the backport of the new classes (ThreeTen for JSR 310).
On Android, use the Android edition of ThreeTen Backport. It’s called ThreeTenABP, and there’s a thorough explanation in this question: How to use ThreeTenABP in Android Project.
For learning to use java.time, see the Oracle tutorial or find other resoureces on the net.
it seems working fine with space as well...what exception you get?
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
public class SimpleDateFormatExample {
public static void main(String[] args) {
SimpleDateFormat sdf = new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss ",Locale.ENGLISH);
String strDate= sdf.format(new Date());
System.out.println(strDate);
}
}
Ouput:Fri, 08 Dec 2017 07:54:08
I got a date time format - "dd MMM yyyy", when trying to parse "6 Aug 2012", I get an java.text.ParseException Unparseable date.
Every thing looks fine, do you see the problem?
You need to mention the Locale as well...
Date date = new SimpleDateFormat("dd MMMM yyyy", Locale.ENGLISH).parse("6 Aug 2012");
Use something like:
DateFormat sdf = new SimpleDateFormat("dd MMM yyyy", Locale.ENGLISH);
Date date = sdf.parse("6 Aug 2012");
Use the split() function with the delimiter " "
String s = “6 Aug 2012”;
String[] arr = s.split(" ");
int day = Integer.parseInt(arr[0]);
String month = arr[1];
int year = Integer.parseInt(arr[2]);
This should work for you. You will need to provide a locale
Date date = new SimpleDateFormat("dd MMM yyyy", Locale.ENGLISH).parse("6 Aug 2012");
Or
Date date = new SimpleDateFormat("dd MMM yyyy", new Locale("EN")).parse("6 Aug 2012");
While the other answers are correct but outdated and since this question is still being visited, here is the modern answer.
java.time and ThreeTenABP
Use java.time, the modern Java date and time API, for your date work. This will work with your Android version/minSDK:
DateTimeFormatter dateFormatter
= DateTimeFormatter.ofPattern("d MMM uuuu", Locale.ENGLISH);
String str = "6 Aug 2012";
LocalDate date = LocalDate.parse(str, dateFormatter);
System.out.println(date);
Output:
2012-08-06
In the format pattern java.time uses just one d for either one or two digit day of month. For year you may use either of yyyy, uuuu, y and u. And as the others have said, specify locale. If Aug is English, then an English-speaking locale.
Question: Doesn’t java.time require Android API level 26?
java.time works nicely on both older and newer Android devices. It just requires at least Java 6.
In Java 8 and later and on newer Android devices (from API level 26) the modern API comes built-in.
In non-Android Java 6 and 7 get the ThreeTen Backport, the backport of the modern classes (ThreeTen for JSR 310; see the links at the bottom).
On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from org.threeten.bp with subpackages.
Links
Similar question to this one: Java - Unparseable date.
Oracle tutorial: Date Time explaining how to use java.time.
Question: uuuu versus yyyy in DateTimeFormatter formatting pattern codes in Java?
Java Specification Request (JSR) 310, where java.time was first described.
ThreeTen Backport project, the backport of java.time to Java 6 and 7 (ThreeTen for JSR-310).
ThreeTenABP, Android edition of ThreeTen Backport
Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.
I've got a SimpleDateFormat to parse a String into a Date:
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ssZ");
When I'm parsing this:
format.parse("2011-08-29T12:44:00+0200");
The result will be, when using Date.toLocaleString:
29 aug. 2011 00:44:00
This should be ofcourse:
29 aug. 2011 12:44:00
And when I'm parsing this:
format.parse("2011-08-29T13:44:00+0200");
Then the result is as expected:
29 aug. 2011 13:44:00
How can I fix this?
Use HH instead of hh for the hours pattern:
H Hour in day (0-23) Number 0
k Hour in day (1-24) Number 24
K Hour in am/pm (0-11) Number 0
h Hour in am/pm (1-12) Number 12
java.time through desugaring
I suggest that you use java.time, the modern Java date and time API, for your date and time work.
Your string is in ISO 8601 format. Define a formatter for it:
private static final DateTimeFormatter ISO_FORMATTER
= new DateTimeFormatterBuilder()
.append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
.appendOffset("+HHMM", "Z")
.toFormatter(Locale.ROOT);
It could have been shorter with a format pattern string, but I prefer to reuse the built-in ISO_LOCAL_DATE_TIME, which already handles ISO 8601. As your question testifies, writing a format pattern string is error-prone. I have also specified that an offset of zero from UTC should be accepted as Z in accordance with ISO 8601 (the parser will accept +0000 too).
Parse like this:
String isoString = "2011-08-29T12:44:00+0200";
OffsetDateTime dateTime = OffsetDateTime.parse(isoString, ISO_FORMATTER);
System.out.println(dateTime);
Output is:
2011-08-29T12:44+02:00
To obtain a string formatted for the user’s locale use a second formatter:
private static final DateTimeFormatter LOCALE_FORMATTER
= DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM);
We still need not write any format pattern string. Format like this:
String localeString = dateTime.format(LOCALE_FORMATTER);
System.out.println(localeString);
Output is exactly what it should be. I ran in nl_NL locale and got:
29 aug. 2011 12:44:00
Please skip the next section.
What if I need an old-fashioned java.util.Date?
No one should use the Date class anymore. Only if you indispensably need a Date for a legacy API that you cannot afford to upgrade to java.time right now, convert:
Date oldfashionedDate = Date.from(dateTime.toInstant());
System.out.println(oldfashionedDate);
Funnily output will be time zone dependent. In my time zone I got:
Mon Aug 29 12:44:00 CEST 2011
Question: Doesn’t java.time require Android API level 26?
java.time works nicely on both older and newer Android devices. It just requires at least Java 6.
In Java 8 and later and on newer Android devices (from API level 26) the modern API comes built-in.
In non-Android Java 6 and 7 get the ThreeTen Backport, the backport of the modern classes (ThreeTen for JSR 310; see the links at the bottom).
On older Android either use desugaring or the Android edition of ThreeTen Backport. It’s called ThreeTenABP. In the latter case make sure you import the date and time classes from org.threeten.bp with subpackages.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Wikipedia article: ISO 8601
Java Specification Request (JSR) 310, where java.time was first described.
ThreeTen Backport project, the backport of java.time to Java 6 and 7 (ThreeTen for JSR-310).
Java 8+ APIs available through desugaring
ThreeTenABP, Android edition of ThreeTen Backport
Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.