I have the following Java:
DateFormat formatter = new SimpleDateFormat(
"EEE MMM dd yyyy HH:mm:ss zZ (zzzz)", Locale.ENGLISH);
Calendar cal = Calendar.getInstance();
cal.set(2011, Calendar.APRIL, 1);
out.println(formatter.format(cal.getTime()));
out.println();
Date date;
try {
date = formatter
.parse("Fri Apr 01 2011 00:00:00 GMT-0400 (Eastern Daylight Time)");
} catch (ParseException e) {
out.println("Failed to parse date: " + e.getMessage());
e.printStackTrace(out);
}
This is in a servlet, and the Calendar-constructed date comes out as:
Fri Apr 01 2011 16:42:24 EDT-0400 (Eastern Daylight Time)
This looks like the same format as the date string I'm trying to parse, except for EDT-0400 versus the desired GMT-0400. The code fails when trying to parse the date string:
java.text.ParseException: Unparseable date: "Fri Apr 01 2011 00:00:00 GMT-0400 (Eastern Daylight Time)"
How can I parse such a string? This is coming from a JavaScript date in a Sencha Touch 1.1.1 model, stored in WebSQL local storage.
For some reason GMT-0400 isnt' working, and UTC-0400 is working. You can replace GMT with UTC.
Note that this part will be completely ignored - the timezone will be resolved from what's found in the brackets (at least on my machine, JDK 6)
I debugged SimpleDateFormat and it seems that it will only parse GMT-04:00 but not GMT-0400.
It will accept UTC-0400, however it will throw away the hours/minutes modifier and will incorrectly parse it as UTC. (This happens with any other timezone designation, except for GMT)
It will also parse -0400 correctly, so the most robust solution is probably to simply remove GMT from your date string.
The upshot of the story is that SimpleDateFormat is anything but simple.
Update: Another lesson is that I could've saved a lot of time by passing a ParsePosition object to the parse() method:
DateFormat formatter = new SimpleDateFormat(
"EEE MMM dd yyyy HH:mm:ss zzzz", Locale.ENGLISH);
Date date;
ParsePosition pos = new ParsePosition( 0 );
date = formatter
.parse("Fri Apr 01 2011 00:00:00 UTC-0400", pos);
System.out.println( pos.getIndex() );
Will print out 28, indicating that the parsing ended at character index 28, just after UTC.
Related
I am updating my old date formatting code to Java 8 and trying the ZonedDateTime API.
The format of date is same as the Javascript Date object format, e.g. -
Thu May 25 2017 10:00:00 GMT+1200 (New Zealand Standard Time)
I was using the below format previously -
EEE MMM dd yyyy hh:mm:ss 'GMT'Z '('zzzz')'
This format fails to parse the date string using DateTimeFormatter.ofPattern method.
Here's the code:
public static final String DATE_FORMAT = "EEE MMM dd yyyy hh:mm:ss 'GMT'Z '('zzzz')'";
public static void main(String[] args) throws ParseException {
String sDate = "Thu May 25 2017 10:00:00 GMT+1200 (New Zealand Standard Time)";
parseDate(sDate);
}
private static void parseDate(String sDate) throws ParseException {
// works
DateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT);
Date oldDate = dateFormat.parse(sDate);
//FIXME: can't parse?!
ZonedDateTime newDate = ZonedDateTime.parse(
sDate, DateTimeFormatter.ofPattern(DATE_FORMAT)); // <- this is the line 25!
}
Here's my full code for reference that can be compiled and run - https://gist.github.com/bhabanism/470e03db54981ad6ddedbba316dcaa9a
This fails at line#25 with:
Exception in thread "main" java.time.format.DateTimeParseException:
Text 'Thu May 25 2017 10:00:00 GMT+1200 (New Zealand Standard Time)'
could not be parsed: Unable to obtain ZonedDateTime from
TemporalAccessor: {HourOfAmPm=10, MilliOfSecond=0, MinuteOfHour=0,
OffsetSeconds=43200, MicroOfSecond=0, NanoOfSecond=0,
SecondOfMinute=0},ISO,Pacific/Auckland resolved to 2017-05-25 of type
java.time.format.Parsed
Note, I can't change the input format of the Date, it has to be
Thu May 25 2017 10:00:00 GMT+1200 (New Zealand Standard Time)
I can surely modify the formatter
EEE MMM dd yyyy hh:mm:ss 'GMT'Z '('zzzz')'
It seems there was a bug in your format string all the time. Lowercase hh is for hour within AM or PM, in the range 1 through 12. Since you don’t have AM/PM in your string, I suspect this was never what you wanted, and I wonder how the error went unnoticed.
Uppercase HH is for hour of day, 0 through 23:
public static final String DATE_FORMAT = "EEE MMM dd yyyy HH:mm:ss 'GMT'Z '('zzzz')'";
With this change both the old and the new way of parsing works on my computer.
When adding Locale.ENGLISH to both formatters, that is. You may want to do the same.
The results I get are
Thu May 25 00:00:00 CEST 2017
2017-05-25T10:00+12:00[Pacific/Auckland]
Since CEST is 2 hours ahead of UTC, this is the same point in time, only rendered differently.
I have an array of Strings with the dates e.g.:
Tue, 09 Feb 2016 14:07:00 GMT;
Tue, 09 Feb 2016 19:55:00 GMT.
Now I want to find the most recent date on this list. In order to do that, I try to deserialize these strings to java.util.Date objects and after that compare them.
The code sample of java.util.Date object generation:
strDate = "Tue, 09 Feb 2016 14:07:00 GMT";
DateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z");
Date date;
try {
date = format.parse(strDate);
//Result: Tue Feb 09 16:07:00 IST 2016
System.out.println("Result: " + date.toString());
} catch(ParseException e) {
e.printStackTrace();
}
My questions:
Why is the result in IST 2016 time zone and not in GMT? What does the IST 2016 stand for? Is it India Standard Time or Irish Standard Time or Israel Standard Time?
The initial string is in EEE, dd MMM format, the SimpleDateFormat pattern is also in this format, thus, why the result is in EEE, MMM dd format?
How can get a java.util.Date object in the same timezone as the initial string, in my case — GMT?
Is the approach I'm using to find the most recent date in the list is OK or there is more convenient/modern way to do that in Java 8, e.g., with the usage of LocalDateTime?
You are relying to Date.toString() to print your date when you should format it to a String with a formatter. What you are seeing is just the default pattern of Date.toString(). What you must keep in mind is that a Date does not have a timezone. You are seeing the output with the IST timezone, this must be because the current locale for the JVM is set to some specific locale for which the timezone name is "IST".
With regard to your point 4, yes, you can do it much cleaner with Java Time API introduced in Java 8. You can create a List of your strings to parse, create a DateTimeFormatter to parse it, and keep the maximum date value.
public static void main(String[] args) {
List<String> dates = Arrays.asList("Tue, 09 Feb 2016 14:07:00 GMT", "Tue, 09 Feb 2016 19:55:00 GMT");
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss z", Locale.ENGLISH);
ZonedDateTime maxDate = dates.stream()
.map(s -> ZonedDateTime.parse(s, formatter))
.max(ZonedDateTime::compareTo)
.get(); // or .orElse(null)
System.out.println(maxDate);
}
This code is using a ZonedDateTime to keep the time-zone of the incoming strings.
Your computer seems to be set to IST. To force GMT output, import java.util.TimeZone and do this in your try block:
format.setTimeZone(TimeZone.getTimeZone("GMT"));
date = format.parse(strDate);
System.out.println("Result: " + format.format(date));
I need help parsing the String date
"Thu Oct 22 13:51:51 CEST 2015"
with SimpleDateFormat, but I'm not able to find the correct pattern.
Here is what I've tried
String date = "Thu Oct 22 13:51:51 CEST 2015";
try {
SimpleDateFormat dateFormat = new SimpleDateFormat("E M d H:m:s z y");
d1 = dateFormat.parse(date);
} catch (ParseException e1) {
Log.e(null, String.valueOf(e1));
}
I get back the error:
java.text.ParseException: Unparseable date: "Thu Oct 22 13:51:51 CEST 2015" (at offset 0)
UPDATE
I tried the solution below by durron597 adapting it to my needs:
String date = "Thu Oct 22 13:51:51 CEST 2015";
try {
SimpleDateFormat dateFormat = new SimpleDateFormat("E MMM dd HH:mm:ss zzzz yyyy", Locale.US);
Date d1 = dateFormat.parse(date);
} catch (ParseException e1) {
Log.e("null", String.valueOf(e1));
}
but in the logcat I keep getting the error:
java.text.ParseException: Unparseable date: "Thu Oct 22 13:51:51 CEST 2015" (at offset 20)
Use more letters for the longer versions of the Date elements.
In particular the problem in your case was probably the Month portion, which you can see from this part of the Javadoc for SimpleDateFormat:
Month: If the number of pattern letters is 3 or more, the month is interpreted as text; otherwise, it is interpreted as a number.
You only had one character for Month, it tried to interpet it as a number, found a letter, and failed.
You also need to specify the US locale, as these are United States dates.
Specify the Locale to use in translating the name of the day of the week, “Thu”. You are in Italy (it says so in your profile); when I use Locale.Italy on my machine, I get the same error as you do. If you specify Locale.US as in the below code, it should work.
Update: Android doesn't support three letter time zones, according to this:
Other than the special cases "UTC" and "GMT" (which are synonymous in this context, both corresponding to UTC), Android does not support the deprecated three-letter time zone IDs used in Java 1.1.
You should be able to replace your Europe time zone with the full name of the time zone defined in the official “tz” time zone database (formerly known as Olson database). For example, Europe/Rome instead of "CEST".
Try this instead:
SimpleDateFormat dateFormat = new SimpleDateFormat("E MMM dd HH:mm:ss zzzz yyyy", Locale.US);
date.replace("CEST", "Europe/Rome");
Date d1 = dateFormat.parse(date);
Here's a full working example:
public class DateExample {
public static void main(String[] args) {
String date = "Thu Oct 22 13:51:51 CEST 2015";
try {
SimpleDateFormat dateFormat = new SimpleDateFormat("E MMM dd HH:mm:ss zzzz yyyy", Locale.US);
date.replace("CEST", "Europe/Rome");
Date d1 = dateFormat.parse(date);
System.out.println(d1);
} catch (ParseException e1) {
e1.printStackTrace();
}
}
}
Output:
Thu Oct 22 06:51:51 CDT 2015
As an input I have Date object(for example, exDate=Fri Aug 01 00:00:00 EEST 2014) that must be formated. After the parsing of the date, I get wrong date.
SimpleDateFormat sdf = new SimpleDateFormat(
"dd-MMM-YYYY hh.mm.ss.SSSSSSSSS aa", Locale.ENGLISH);
String dateStart = sdf.format(exDate);
Date dateF = sdf.parse(dateStart);
dateStart will be equal to
01-Aug-2014 12.00.00.000000000 AM
and the resut, dateF will be equal to
Sun Dec 29 00:00:00 EET 2013
So, after the parsing of a string with date, the result is wrong.
Maybe, somebody know the source of the problem? Or another way to format date in another SimpleDateFormat?
The problem is the YYYY which means:
Y Week year;
The actual year, which is what you are looking for would be yyyy.
I really recommend that you go in the link above to see the full list.
You should also replace the milliseconds to .SSS as you can't get more precise than that.
I need to convert from Date(the object :insuree.getBirthDate()) into Calendar(the object : request_MDP.setBIRTH_DATE)
but i get the error :
21/02/13 15:20:26 ERROR [MdmInsureeService]: ServiceProxy Update
exception: 'Unparseable date: "Mon Nov 15 15:00:00 IST 1982"' 21/02/13
15:20:26 ERROR [MdmInsureeService]: ServiceProxy Update exception
(toString): 'java.text.ParseException: Unparseable date: "Mon Nov 15
15:00:00 IST 1982"
This is my code :
DateFormat formatter = new SimpleDateFormat("EEE MMM d HH:mm:ss zzz yyyy");
Date date_MDP =(Date)formatter.parse(insuree.getBirthDate().toString());
Calendar cal_MDP=Calendar.getInstance();
cal_MDP.setTime(date_MDP);
request_MDP.setBIRTH_DATE(cal_MDP);
How can I convert the Date(insuree.getBirthDate()) into Calendar(setBIRTH_DATE) ?
Thanks
try this code:
SimpleDateFormat df = new SimpleDateFormat("KK:mm aa");
Date date = df.parse("10:30 PM");
System.out.print(date);
Calendar cal = GregorianCalendar.getInstance();
cal.setTimeInMillis(date.getTime());
System.out.print(cal.getTime());
Is it possible that you run this code on a system with a non-English locale? Such a locale might not recognize the weekday or month in your example date ("Mon Nov 15 15:00:00 IST 1982"), because it uses different names (e.g. "Tue" would be "Di" in German).
Replace the first line in your snippet with
DateFormat formatter =
new SimpleDateFormat("EEE MMM d HH:mm:ss zzz yyyy", Locale.US);
and it will work with your example date. Either way, you have to use the same format and locale that was used to generate those date strings. Maybe you can even convince the generator to use some standard format like ISO 8601.