I am trying to parse dates, for example "Sat, 29 Dec 2012 04:07:09 +0100"
I am using SimpleDateFormatter with format set as
new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z", Locale.getDefault());
Unfortunately I am getting
12-29 04:44:29.890: E/MainActivity(3995): Unparseable date: "Sat, 29 Dec 2012 04:07:09 +0100" (at offset 0)
12-29 04:44:29.890: E/MainActivity(3995): java.text.ParseException: Unparseable date: "Sat, 29 Dec 2012 04:07:09 +0100" (at offset 0)
Which I absolutely dont get as that parameter regular expression is copy and pasted directly from documentation http://docs.oracle.com/javase/6/docs/api/java/text/SimpleDateFormat.html under Examples
Thanks!
Whatever the locale returned by Locale.getDefault() is doesn't support dates formatted that way.
Changing it to Locale.US for example, will work.
Related
This question already has answers here:
java DateTimeFormatterBuilder fails on testtime [duplicate]
(2 answers)
Closed 1 year ago.
Trying to parse incoming dates from a third-party source, some dates work as expected others throw an exception:
Text 'Fri, 11 Jun 2021 02:25:23 +0000' could not be parsed at index 8
Looking at the dates I can't spot a difference in them, and looking at my formatter I can't see where I've gone wrong.
Example failing date: Fri, 11 Jun 2021 02:25:23 +0000
Example passing date: Sun, 30 May 2021 11:42:03 +0000
The code I'm using to parse the dates:
ZonedDateTime.parse(incomingDate, DateTimeFormatter.ofPattern("E, d MMM yyyy HH:mm:ss Z"));
The only thing I can think that some date months are shorthand vs others that are not (May vs Jun for example).
Would love some help.
String incomingDate1 = "Fri, 11 Jun 2021 02:25:23 +0000";
String incomingDate2 = "Sun, 30 May 2021 11:42:03 +0000";
ZonedDateTime parsed = ZonedDateTime.parse(incomingDate1,
DateTimeFormatter.ofPattern("E, d MMM yyyy HH:mm:ss Z", Locale.ENGLISH));
System.out.println(parsed);
I have a Java application which basically contains the following code in a test and expects it to throw an Exception:
String date = "Fr August 21 16:41:32 CEST 2015";
DateFormat dateFormat = new SimpleDateFormat("EEE MMMM dd HH:mm:ss z yyyy", Locale.GERMANY);
dateFormat.parse(date);
While the application ran under Suns Java 1.7 it always failed, as expected, with this Exception:
java.text.ParseException: Unparseable date: "Fr August 21 16:41:32 CEST 2015"
It failed because CEST wasn't a legit time zone with German Locale. When I now run the same test under IBMs Java 1.8, it now successfully parses to
Fr August 21 16:41:32 MESZ 2015
So I wonder which behaviour is the correct one? Do I now have a bug or did I have one before? Or did I somehow miss-configure something?
I have an issue with SimpleDateFormat:
Error:
Unparseable date: "Thu, 09 Nov 2017 16:17:42 GMT"
Code:
DF_SERVER_FORMAT="EEE, dd MMM yyyy HH:mm:ss'Z'"
....
var formater=SimpleDateFormat(DF_SERVER_FORMAT)
formater.parse(source)
as per SimpleDateFormat documentation, Z (capitalized) is for an RFC 822 time zone, e.g. -0800
for a General time zone use z.
this should work:
DF_SERVER_FORMAT="EEE, dd MMM yyyy HH:mm:ss z"
Try "EEE, d MMM yyyy HH:mm:ss z" this pattern works for me.
You can try to format some date using your pattern, to see the difference and then fix your pattern accordingly. Here is what I did in J2SE:
SimpleDateFormat df = new SimpleDateFormat("EEE dd MMM yyyy HH:mm:ss'Z'");
System.out.println(df.format(new Date()));
This is producing:
Thu 09 Nov 2017 17:49:07Z
But, when I used the pattern "EEE, dd MMM yyyy HH:mm:ss z", it produced the expected result:
Thu, 09 Nov 2017 17:51:09 CET
For anyone who either is fine with an external dependency (temporarily) or is using Java 8 or later I wanted to contribute the modern answer. Because I consider SimpleDateFormat long outdated.
The modern Java date and time API is generally much nicer to work with. In addition, your string is in RFC 1123 format, and the modern API comes with a formatter for this format. So no need to build your format pattern string yourself (my code is pure Java, I trust you to adopt to Kotlin):
String dateString = "Thu, 09 Nov 2017 16:17:42 GMT";
OffsetDateTime dateTime = OffsetDateTime.parse(dateString,
DateTimeFormatter.RFC_1123_DATE_TIME);
This produces an OffsetDateTime of 2017-11-09T16:17:42Z as expected.
To use this on Android, get ThreeTenABP, see this question: How to use ThreeTenABP in Android Project. Java 8 and later come with the modern API built-in. If using Java 6 or 7 on non-Android, you need the ThreeTen Backport.
What went wrong in your code? With your format pattern string you were asking for a literal Z right after the seconds, with no space in between. Since your input string didn’t have a Z there, parsing failed (instead it had a space and the offset ID GMT). In addition, your code seems to be sensitive to locale: if your default locale is one where the abbreviation for Thursday is not Thu or for November not Nov, parsing will fail (in contrast, RFC_1123_DATE_TIME expects (and requires) day and month abbreviations in English independently of locale).
I've got a silly problem, here's my code:
SimpleDateFormat dateFormat = new SimpleDateFormat("EEE MMM dd yyyy HH:mm:ss zZ",Locale.US);
System.out.println(dateFormat.format(new Date()));
try {
wou.setDateStart(dateFormat.parse(date));
wou.setDateEnd(dateFormat.parse(date));
} catch (ParseException e) {
System.out.println(e.getCause() + " " + e.getMessage());
e.printStackTrace();
}
the result is following:
Fri Jun 05 2015 15:34:29 GMT+0000
null Unparseable date: "Fri Jun 05 2015 17:30:00 GMT+0000"
What's wrong with my format? It outputs the current date in the same format as the date I want to parse, but keeps telling me that the date is unparseable...
I'm struggling that for over an hour and I'm completely lost...
EDIT:
I have no control over the date I need to parse (if I did, I would change it in a source to a format that I could consume)
Following code:
String date = request.getParameter("absencyDate");
SimpleDateFormat dateFormat = new SimpleDateFormat("EEE MMM dd yyyy HH:mm:ss z",Locale.US);
try {
System.out.println(dateFormat.format(new Date()));
System.out.println(date);
System.out.println(dateFormat.parse(date));
} catch (ParseException e1) {
Produces same error:
Fri Jun 05 2015 16:09:15 GMT
Fri Jun 05 2015 12:30:00 GMT+0000
java.text.ParseException: Unparseable date: "Fri Jun 05 2015 12:30:00 GMT+0000"
The problem is your use of zZ in the date format. It expects a simple name-based zone (z), followed by an RFC-822 zone (Z).
It works well if the default zone (or the zone set in the format) is not GMT, because then it just parses up to that point (matches the z), and then it parses the +0000 as the Z.
But when the zone is GMT, it actually tries to parse the part that follows it (+0000) as part of the z, because "GMT+hh:mm" is a valid zone for z, and that fails.
The date format appears deceivingly correct. But combining two timezone formats is not. It should either be a named time zone (which includes "GMT+00:00"), or an RFC 822 offset (which doesn't include the "GMT" designation).
Edit following OP edit
So you get your date parameter from somewhere, and they are sending it to you with a non-standard zone designation. GMT+0000 matches neither general time zone (should be GMT or GMT+00:00), RFC 822 time zone (should be +0000 without GMT), nor ISO 8601 time zone (should be +00 or +0000 or +00:00).
If you know that they will always be using GMT in their dates, I think the best you can do is:
"EEE MMM dd yyyy HH:mm:ss 'GMT'Z"
Which will take the GMT part as a literal string rather than a time zone designator, then interpret the time zone from whatever follows it.
Or if the source that generates that parameter is under your control, fix its format to use a proper time zone matching one of the standards.
java.time
The legacy date-time API (java.util date-time types and their formatting API, SimpleDateFormat) are outdated and error-prone. It is recommended to stop using them completely and switch to java.time, the modern date-time API*.
Demo using modern date-time API:
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.util.Locale;
public class Main {
public static void main(String args[]) {
String dateStr = "Fri Jun 05 2015 17:30:00 GMT+0000";
DateTimeFormatter dtf = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.appendPattern("EEE MMM d u H:m:s")
.appendLiteral(' ')
.appendZoneId()
.appendPattern("X")
.toFormatter(Locale.ENGLISH);
ZonedDateTime zdt = ZonedDateTime.parse(dateStr, dtf);
System.out.println(zdt);
}
}
Output:
2015-06-05T17:30Z[GMT]
For any reason, if you need an object of java.util.Date from this object of ZonedDateTime, you can so as follows:
Date date = Date.from(zdt.toInstant());
Learn more about the the modern date-time API* from Trail: Date Time.
* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.
Why is it throwing an exception, That date is pretty straight forward isnt it?
long date = Date.parse(request.getParameter("date")); //Wed Apr 03 00:00:00 BST 2013
String formattedDate = new SimpleDateFormat("dd/MM/yyyy").format(date);
reportParams.put("p_date", formattedDate);
Caused by: java.lang.IllegalArgumentException at
java.util.Date.parse(Date.java:595)
Don't use Date.parse() to parse dates. As you can see in the API documentation, that method is deprecated, which means it is replaced by another method. The API documentation even mentions what you should use instead: DateFormat.parse().
Create a SimpleDateFormat object with the format that matches your input string, and use that to parse it into a Date object.
String text = "Wed Apr 03 00:00:00 BST 2013";
DateFormat df = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", Locale.ENGLISH);
Date date = df.parse(text);
The main issue is that you have the date at the end of the string. It should come after the month, e.g:
Wed, 03 Apr 2013 00:00:00 BST
Please read the documentation for a full description. Note also that Date.parse is deprecated in favour of DateFormat.parse.
1) Date.parse is deprecated
2) Date.parse API says It accepts many syntaxes; in particular, it recognizes the IETF standard date syntax: "Sat, 12 Aug 1995 13:30:00 GMT". It also understands the continental U.S. time-zone abbreviations, but for general use, a time-zone offset should be used: "Sat, 12 Aug 1995 13:30:00 GMT+0430" (4 hours, 30 minutes west of the Greenwich meridian). If no time zone is specified, the local time zone is assumed. GMT and UTC are considered equivalent. But your syntax is none of the described.
3) Use SimleDateFormat instead