I'm receiving a ParseException with the following code and I can't seem to fix it:
String date = "Tue Mar 13 2012 10:48:05 GMT-0400";
SimpleDateFormat format = new SimpleDateFormat("EEE MMM dd yyyy HH:mm:ss zzzX"); //Tried zzzZ at the end as well
System.out.println(format.parse(date));
If I take out the -0400 and the X (or Z) at the end of the SimpleDateFormat things work fine, but once it's in the code, it simply doesn't work. What symbol should I be using instead? I'm using Java 7.
Here is the parse error I receive:
java.text.ParseException: Unparseable date: "Tue Mar 13 2012 10:48:05 GMT-0400"
at java.text.DateFormat.parse(DateFormat.java:357)
java.text.ParseException: Unparseable date: "Tue Mar 13 2012 10:48:05 GMT-0400"
at java.text.DateFormat.parse(DateFormat.java:357)
at com.throwaway.parse.DateParsing.testDate(TestDate:17)
The GMT part of GMT-0400 of your string is causing the problem.
The Z (or X in java 7) parameter is only matching -4000. You have to escape GMT by using single quotes like this :
DateFormat format = new SimpleDateFormat("EEE MMM dd yyyy HH:mm:ss 'GMT'Z", Locale.US);
Note that it's also a good practice to put a Local in your DateFormat. Without it your code won't work in other countries (like here in France...).
Three issues all dealing with mixed usage. Either:
Use a single lower-case "z" and a ":" separating your hour and time in the time zone when using "GMT(+/-)hh:mm", or
Use a single upper-case "Z" and drop the "GMT" from your timezone, and you can use the "(+/-)hhmm" format, or
Use a single upper-case "X" and still drop the "GMT" but you can use any format of the hhmm zone.
From the Javadoc:
z General time zone Pacific Standard Time; PST; GMT-08:00
Z RFC 822 time zone -0800
X ISO 8601 time zone -08; -0800; -08:00
The pattern zzzz could only parse "GMT-04:00" style strings. Your example can be parsed with this pattern: EEE MMM dd yyyy HH:mm:ss Z
use "EEE MMM dd yyyy HH:mm:ss zzzZ".
zzz is for GMT and Z is for 'RFC 822 time zone' please refer
Check this out
If you always expect your timezone to be represented that way, you could put "GMT" in single quotes in your format string to prevent it from being parsed:
EEE MMM dd yyyy HH:mm:ss 'GMT'XX
It's a bit weird that none of the built-in formats can parse it though. Perhaps the Javadoc is incorrect when it lists GMT-08:00 as an example of z?
Related
I want to convert the date in string to date object being the string "10h 57m 20s October 13 2020". How can be done? may replace firstly the h, m and s to get the format "10:57:20 October 13 2020"? As well, I tried the last format "10:57:20 October 13 2020" to get the date with DateTimeFormat and DateTimeFormatterBuilder() but is does not work with the month or it works but the hour coverts to 00:00:00.
Thanks
java.time
I recommend that you use java.time, the modern Java date and time API, for your date and time work. Like Joop Eggen already wrote, put the letters that are part of your format in single quotes in the format pattern string:
private static final DateTimeFormatter FORMATTER
= DateTimeFormatter.ofPattern("H'h' m'm' s's' MMMM d y", Locale.ENGLISH);
This will allow you to parse like this:
String dateInString = "10h 57m 20s October 13 2020";
LocalDateTime dateTime = LocalDateTime.parse(dateInString, FORMATTER);
System.out.println(dateTime);
Output:
2020-10-13T10:57:20
You shouldn’t take any interest in the old-fashioned Date class. However, sometimes we need to pass a Date to a legacy API not yet upgraded to java.time. The conversion requires that we know the time zone assumed for the parsed date and time. For example:
ZoneId zone = ZoneId.of("America/Tegucigalpa");
Instant i = dateTime.atZone(zone).toInstant();
Date oldfashionedDate = Date.from(i);
System.out.println(oldfashionedDate);
Example output:
Tue Oct 13 10:57:20 CST 2020
Tutorial link
Oracle tutorial: Date Time explaining how to use java.time.
You can place fixed letters in apostrophes.
"HH'h' mm'm' ss's' MMMM dd yyyy"
Furthermore hh is the 12 hour format to be combined wiht a AM/PM.
HH is the 24 hour format.
Also the locale must be correct, maybe explicitly set. Here English.
Is it possible to convert this date string using Java time package
3-6-2017
to this format
"Mon Mar 6 00:00:00 EST 2017"
I created these two formatters, but which time instance should I use? I've tried LocalDate, LocalDateTime, and ZonedDateTime.
DateTimeFormatter inputFormat = DateTimeFormatter.ofPattern("M-d-uuuu");
DateTimeFormatter convertedToFormat = DateTimeFormatter.ofPattern("EEE MMM dd hh:mm:ss zzz yyyy");
I believe that you have three issues:
To accept month in either 1 or 2 digits (like 3 for March and 11 for November) you need to specify one pattern letter M, not two. Similarly for day of month. So your input format pattern string should be M-d-uuuu (or just M-d-u). Edit: You also need d instead of dd in the “converted to” pattern.
To print hour of day (from 00 through 23) you need uppercase HH. Lowercase hh is for clock hour within AM or PM from 01 through 12.
Since your input string did not contain time of day, you need to specify time of day some other way. Similar for time zone since your “converted to” format contains zzz for time zone abbreviation.
So in code I suggest:
DateTimeFormatter inputFormat = DateTimeFormatter.ofPattern("M-d-uuuu");
DateTimeFormatter convertedToFormat = DateTimeFormatter.ofPattern("EEE MMM d HH:mm:ss zzz yyyy");
String input = "3-6-2017";
ZonedDateTime startOfDay = LocalDate.parse(input, inputFormat)
.atStartOfDay(ZoneId.of("America/New_York"));
String output = startOfDay.format(convertedToFormat);
System.out.println(output);
Output from my snippet is the desired:
Mon Mar 6 00:00:00 EST 2017
Or to answer your question a little more directly:
… which time instance should I use?
You need two of them: LocalDate for parsing your input and ZonedDateTime for formatting your output. And then a conversion between the two. The one-arg atStartOfDay method provides the conversion we need. (There is a trick for parsing directly into a ZonedDateTime using default values for time and time zone, but it’s more complicated.)
There are other time zones that will also produce EST as time zone abbreviation. Since your profile says you’re in Boston, I think that America/New_York is the one you want.
I have the following piece of code that is throwing a DateTimeParseException:
String dateString = "Jul 20 09:32:46"
DateTimeFormatter formatter=DateTimeFormatter.ofPattern("L d HH:mm:ss");
return ZonedDateTime.parse(dateString, formatter);
According to the documentation, you will observe that Jul is the example for character L.
However, the exception message is:
java.time.format.DateTimeParseException: Text 'Jul' could not be parsed at index 0
What am I missing?
You have some issues here:
To correctly parse 'Jul' you have to use MMM instead of L (here explains why).
Your date string doesn't have a year. You can't create a ZonedDateTime without the year.
If is a Zoned date time, it has to include the time zone information too, which is not in your date string. You can use a LocalDateTime if you don't want to work with time zones.
Here are some alternatives:
With timezone:
String dateString = "Jul 20 2018 09:32:46+0000";
DateTimeFormatter formatter= DateTimeFormatter.ofPattern("MMM dd y H:mm:ssZ");
return ZonedDateTime.parse(dateString, formatter);
Without timezone:
String dateString = "Jul 20 2018 09:32:46";
DateTimeFormatter formatter= DateTimeFormatter.ofPattern("MMM dd y H:mm:ss");
return LocalDateTime.parse(dateString, formatter);
The answer by Juan Carlos Mendoza is correct. I will give my suggestions as a supplement: either improve your string to include year and time zone, or build a formatter that can parse your current string without them.
Improving your string
String dateString = "Jul 20 2018 09:32:46 America/Argentina/La_Rioja";
DateTimeFormatter formatter
= DateTimeFormatter.ofPattern("LLL d uuuu HH:mm:ss VV", Locale.ROOT);
System.out.println(ZonedDateTime.parse(dateString, formatter));
This prints
2018-07-20T09:32:46-03:00[America/Argentina/La_Rioja]
The same formatter will also parse Jul 20 2018 09:32:46 -08:30 into a ZonedDateTime of 2018-07-20T09:32:46-08:30.
First potential issue is the locale. If “Jul” is in English, give an English-speaking locale, or parsing will likely fail on computers with a language where the month of July is called something else. I recommend you always specify locale with your formatter. Even if you end up going for Locale.getDefault(). It will still tell the reader (and yourself) that you have made a conscious choice.
Next the documentation says that both M and L can give month as number/text and gives examples 7; 07; Jul; July; J. So this line is clearly relevant: “Number/Text: If the count of pattern letters is 3 or greater, use the Text rules above. Otherwise use the Number rules above.” Since “Jul” is text, you need 3 pattern letters or greater. “Less than 4 pattern letters will use the short form.” “Jul” is short, so we need exactly three letters.
The code above works with Java 9.0.4 no matter if I use MMM or LLL in the format pattern string. In jdk1.8.0_131 it works with MMM but funnily fails with LLL, this may be a bug (tested on a Mac). See Juan Carlos Mendoza’s for a treatment of the intended difference between M and L.
Build a formatter that works
String dateString = "Jul 20 09:32:46";
ZoneId zone = ZoneId.of("America/Argentina/La_Rioja");
DateTimeFormatter formatter = new DateTimeFormatterBuilder().appendPattern("LLL d HH:mm:ss")
.parseDefaulting(ChronoField.YEAR, Year.now(zone).getValue())
.toFormatter(Locale.ROOT)
.withZone(zone);
System.out.println(ZonedDateTime.parse(dateString, formatter));
This will parse the string from your question into 2018-07-20T09:32:46-03:00[America/Argentina/La_Rioja]. Please substitute your desired default time zone if it didn’t happen to coincide with the one I picked at random. Also substitute your desired year if you don’t want the current year.
Again my Java 8 requires MMM rather than LLL.
I use the following SimpleDateFormat to parse a string,
SimpleDateFormat ft= new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy");
String notimeZone = ft.format(startDateTime);
Date date = ft.parse(notimeZone);
startDateTime is Date object with value in format "Thu Mar 06 12:27:55 IST 2014".
in notimeZone variable i get, Thu Mar 06 12:27:55 2014
I am expecting output in variable date as, Thu Mar 06 12:27:55 2014
But am getting same , Thu Mar 06 12:27:55 IST 2014.
How to remove the time zone from the date object.
Please help.
java.util.Date does not have a Timezone. It is not aware of TimeZone.
When you print, java picks up the default time zone.
Conceptually, you cannot have a date time without timezone. A date time has to be in one and only one zone. You may convert it to other zones, but it can never be without a zone.
If your business use case requires awareness of Time Zone, I would prefer to use Calendar class, or Joda Time. Avoid playing with Date class. If your business use cases do not require any time zone awareness, then go ahead with date. Assume all Date instances are in your default time zone.
Best thing is to use Calendar (or Joda Time). Calendar is a bit unintuitive but you will be able to get your job done. It is not without reason that Date class is mostly deprecated.
Initialize your Calendar with Timezone (check out available constructors). Use Dateformat to convert and show in UI in whatever time zone you wish to. I posted some code in your previous question. That might help you. I was stuck in a similar problem. I have dates in the DB in one time zone. To display them in another time zone on UI, you need to convert that datetime to another zone.
The following format gives
"EEE MMM dd HH:mm:ss z yyyy"->Thu Mar 06 13:18:02 IST 2014.
"EEE MMM dd HH:mm:ss yyyy" -> Thu Mar 06 13:18:02 2014.
Check if you gave a 'z' by mistake in the date format string.
For more details, Refer - http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html
From DateTimeFormatter javadoc:
Zone names: Time zone names ('z') cannot be parsed.
Therefore timezone parsing like:
System.out.println(new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy").parse("Fri Nov 11 12:13:14 JST 2010"));
cannot be done in Joda:
DateTimeFormatter dtf = DateTimeFormat.forPattern("EEE MMM dd HH:mm:ss z yyyy");
System.out.println(dtf.parseDateTime("Fri Nov 11 12:13:14 JST 2010"));
//Exception in thread "main" java.lang.IllegalArgumentException: Invalid format: "Fri Nov 11 12:13:14 JST 2010" is malformed at "JST 2010"
//at org.joda.time.format.DateTimeFormatter.parseDateTime(DateTimeFormatter.java:673)
I think that the reason is that 'z' timezone names are conventional (not standardized) and ambiguous; i.e. they mean different things depending on your country of origin. For example, "PST" can be "Pacific Standard Time" or "Pakistan Standard Time".
If you are interested, this site has a listing of a large number of timezone names. It is not difficult to spot cases where there is ambiguity.
Probably because some time zone abbreviations are ambiguous and the parser can't know which time zone is meant.
It might of course also be one of the tiny, strange ticks and missing features you find after working with Joda for a while.
Abbreviated time zones are indeed ambiguous and Joda took a step further removing support for them as stated in the DateTimeZone javadoc: