I'm trying to read data from RSS feeds and one of the fields is when the feed was last updated.
I'm using something similar to this:
Date date;
String output;
SimpleDateFormat formatter;
String pattern = "EEE, dd MMM, HH:mm:ss Z";
formatter = new SimpleDateFormat(pattern, Locale.ENGLISH);
date = formatter.parse("Wed, 25 Mar 2020 08:00:00 +0200");
output = date.toString();
System.out.println(pattern + " | " + output);
but I get this error:
Exception in thread "main" java.text.ParseException: Unparseable date: "Wed, 25 Mar 2020 08:00:00 +0200"
at java.text.DateFormat.parse(DateFormat.java:366)
at HelloWorld.main(HelloWorld.java:16)
java.time
java.time is the modern java date and time API and has a built-in formatter for your string:
String lastUpdatedString = "Wed, 25 Mar 2020 08:00:00 +0200";
OffsetDateTime dateTime = OffsetDateTime
.parse(lastUpdatedString, DateTimeFormatter.RFC_1123_DATE_TIME);
System.out.println(dateTime);
Output:
2020-03-25T08:00+02:00
So there’s no need to write our own format pattern string, which is always error-prone, and certainly no need to use the SimpleDateFormat class. That class is a notoriously troublemaker of a class, so we had wanted to avoid it anyway.
Link: Oracle tutorial: Date Time explaining how to use java.time.
Related
DateUtils.parseDateStrictly("28 Sep 2018" , "dd MMMM yyyy")
The format of the above date should be dd MMM yyyy (MMM denotes shorter month) , but MMMM also parses shorter month which causes invalid parsing. I am already using parseDateStrictly method. Any other suggestions ?
java.time
I recommend that you use java.time for your date and time work. Apache DateUtils was useful once we only had the poorly designed Date and SimpleDateFormat classes to work with. We don’t need it anymore. For a long time now we haven’t needed it.
java.time behaves the way you expect out of the box.
DateTimeFormatter dateFormatter
= DateTimeFormatter.ofPattern("dd MMMM uuuu", Locale.ENGLISH);
String dateString = "28 Sep 2018";
LocalDate.parse(dateString, dateFormatter);
Result:
Exception in thread "main" java.time.format.DateTimeParseException: Text '28 Sep 2018' could not be parsed at index 3
at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2046)
at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1948)
at java.base/java.time.LocalDate.parse(LocalDate.java:428)
(etc.)
Link
Oracle tutorial: Date Time explaining how to use java.time.
The column format is dd MMMM yyyy and it should parse dates like 28
September 2018 and should throw error on values such as 28 Sep 2018
DateUtils uses the date-time API of java.util and their formatting API, SimpleDateFormat which are outdated and error-prone. I suggest you should stop using them completely and switch to the modern date-time API.
Using the modern date-time API:
import java.time.DateTimeException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
// Test strings
String[] arr = { "28 September 2018", "28 Sep 2018", "28 09 2018" };
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd MMMM uuuu", Locale.ENGLISH);
for (String s : arr) {
try {
LocalDate date = LocalDate.parse(s, formatter);
// ...Process date e.g.
System.out.println(DateTimeFormatter.ofPattern("MMMM dd, uuuu", Locale.ENGLISH).format(date));
} catch (DateTimeException e) {
System.out.println(s + " is not a valid string.");
}
}
}
}
Output:
September 28, 2018
28 Sep 2018 is not a valid string.
28 09 2018 is not a valid string.
Learn more about the modern date-time API at Trail: Date Time.
If you are doing it for your 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.
I have this String
Fri, 07 Aug 2020 18:00:00 +0000
And I need to convert it to a LocalDateTime
I tryed several ways:
create a DateTimeFormatter and parse the String
String dateString = "Fri, 07 Aug 2020 18:00:00 +0000";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("E, dd MMM yyyy HH:mm:ss", Locale.getDefault());
LocalDateTime parsedDate = LocalDateTime.parse(publishedString, formatter);
Convert it to a Date with a SimpleDateFormat and then convert the resultDate to a LocalDateTime
String dateString = "Fri, 07 Aug 2020 18:00:00 +0000";
SimpleDateFormat dateFormatter = new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss Z");
Date date = dateFormatter.parse(publishedString);
LocalDateTime localDateTime = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
both solution gives me the same exception:
java.time.format.DateTimeParseException: Text 'Fri, 07 Aug 2020 18:00:00 +0000' could not be parsed
at index 0 at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2046)
How can I convert that String?
I'd say use Locale.ROOT and don't forget the Z in the DateTimeFormatter class
String dateString = "Fri, 07 Aug 2020 18:00:00 +0000";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("E, dd MMM yyyy HH:mm:ss Z", Locale.ROOT);
LocalDateTime parsedDate = LocalDateTime.parse(dateString, formatter);
tl;dr
OffsetDateTime.parse(
"Fri, 07 Aug 2020 18:00:00 +0000" ,
DateTimeFormatter.RFC_1123_DATE_TIME
)
See this code run live at IdeOne.com.
LocalDateTime is the wrong class
Your input string contains +0000 which indicates an offset-from-UTC.
So you should not be using LocalDateTime. That class purposely lacks any concept of time zone or offset. With LocalDateTime, your string Fri, 07 Aug 2020 18:00:00 +0000 will become 6M on August 7th 2020, but we won't know if that is 6 PM in Tokyo Japan, 6 PM in Toulouse France, or 6 PM in Toledo Ohio US — all different moments several hours apart.
OffsetDateTime
Instead, this value should be parsed as OffsetDateTime.
Parsing
Your input's format is that of RFC 1123. That particular format is predefined in java.time.
String input = "Fri, 07 Aug 2020 18:00:00 +0000";
DateTimeFormatter f = DateTimeFormatter.RFC_1123_DATE_TIME;
OffsetDateTime odt = OffsetDateTime.parse( input , f );
odt.toString(): 2020-08-07T18:00Z
I understand that you need a LocalDateTime for an API that due to a design problem beyond your control is trying to use LocalDateTime for a point in time.
If an external contract dictates in which time zone or at which UTC offset the LocalDateTime is to be understood, LocalDateTime can be made to work, at least for 99.977 % of cases. You will still have a programming error waiting to happen on the day when some colleague programmer does not read the contract, a problem that we cannot solve in the code, only try to mitigate through good commenting.
If for example the contract says UTC, then we need to make sure we convert the time to UTC. And we need the offset from the string for doing so.
ZoneOffset contractualOffset = ZoneOffset.UTC;
String stringWeveGot = "Fri, 07 Aug 2020 18:00:00 +0000";
LocalDateTime convertedDateTime = OffsetDateTime
.parse(stringWeveGot, DateTimeFormatter.RFC_1123_DATE_TIME)
.withOffsetSameInstant(contractualOffset)
.toLocalDateTime();
System.out.println(convertedDateTime);
Output:
2020-08-07T18:00
If the offset in the string is required to be 0 already, you need to validate that it is, or errors will go unnoticed and users will get wrong results. For example:
OffsetDateTime parsedOdt = OffsetDateTime
.parse(stringWeveGot, DateTimeFormatter.RFC_1123_DATE_TIME);
if (! parsedOdt.getOffset().equals(contractualOffset)) {
throw new IllegalStateException("Offset must be " + contractualOffset
+ ", was " + parsedOdt.getOffset());
}
LocalDateTime convertedDateTime = parsedOdt.toLocalDateTime();
If the contract mentions some time zone, convert to that time zone. I am taking Australia/Victoria as an example.
ZoneId contractualZone = ZoneId.of("Australia/Victoria");
String stringWeveGot = "Fri, 07 Aug 2020 18:00:00 +0000";
LocalDateTime convertedDateTime = OffsetDateTime
.parse(stringWeveGot, DateTimeFormatter.RFC_1123_DATE_TIME)
.atZoneSameInstant(contractualZone)
.toLocalDateTime();
System.out.println(convertedDateTime);
2020-08-08T04:00
You will get an ambiguous result at time anomalies where the clock is turned backward, for example at the fall back when summer time (DST) ends.
What went wrong in your code?
The cause of your exception is explained here:
new SimpleDateFormat(“hh:mm a”, Locale.getDefault()).parse(“04:30 PM”) giving Unparseable exception
java DateTimeFormatterBuilder fails on testtime
This question already has answers here:
Java string to date conversion
(17 answers)
Closed 6 years ago.
I am trying to parse this date with SimpleDateFormat and it is not working:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Formaterclass {
public static void main(String[] args) throws ParseException{
String strDate = "Thu Jun 18 20:56:02 EDT 2009";
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
Date dateStr = formatter.parse(strDate);
String formattedDate = formatter.format(dateStr);
System.out.println("yyyy-MM-dd date is ==>"+formattedDate);
Date date1 = formatter.parse(formattedDate);
formatter = new SimpleDateFormat("dd-MMM-yyyy");
formattedDate = formatter.format(date1);
System.out.println("dd-MMM-yyyy date is ==>"+formattedDate);
}
}
If I try this code with strDate="2008-10-14", I have a positive answer. What's the problem? How can I parse this format?
PS. I got this date from a jDatePicker and there is no instruction on how modify the date format I get when the user chooses a date.
You cannot expect to parse a date with a SimpleDateFormat that is set up with a different format.
To parse your "Thu Jun 18 20:56:02 EDT 2009" date string you need a SimpleDateFormat like this (roughly):
SimpleDateFormat parser=new SimpleDateFormat("EEE MMM d HH:mm:ss zzz yyyy");
Use this to parse the string into a Date, and then your other SimpleDateFormat to turn that Date into the format you want.
String input = "Thu Jun 18 20:56:02 EDT 2009";
SimpleDateFormat parser = new SimpleDateFormat("EEE MMM d HH:mm:ss zzz yyyy");
Date date = parser.parse(input);
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
String formattedDate = formatter.format(date);
...
JavaDoc: http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html
The problem is that you have a date formatted like this:
Thu Jun 18 20:56:02 EDT 2009
But are using a SimpleDateFormat that is:
yyyy-MM-dd
The two formats don't agree. You need to construct a SimpleDateFormat that matches the layout of the string you're trying to parse into a Date. Lining things up to make it easy to see, you want a SimpleDateFormat like this:
EEE MMM dd HH:mm:ss zzz yyyy
Thu Jun 18 20:56:02 EDT 2009
Check the JavaDoc page I linked to and see how the characters are used.
We now have a more modern way to do this work.
java.time
The java.time framework is bundled with Java 8 and later. See Tutorial. These new classes are inspired by Joda-Time, defined by JSR 310, and extended by the ThreeTen-Extra project. They are a vast improvement over the troublesome old classes, java.util.Date/.Calendar et al.
Note that the 3-4 letter codes like EDT are neither standardized nor unique. Avoid them whenever possible. Learn to use ISO 8601 standard formats instead. The java.time framework may take a stab at translating, but many of the commonly used codes have duplicate values.
By the way, note how java.time by default generates strings using the ISO 8601 formats but extended by appending the name of the time zone in brackets.
String input = "Thu Jun 18 20:56:02 EDT 2009";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern ( "EEE MMM d HH:mm:ss zzz yyyy" , Locale.ENGLISH );
ZonedDateTime zdt = formatter.parse ( input , ZonedDateTime :: from );
Dump to console.
System.out.println ( "zdt : " + zdt );
When run.
zdt : 2009-06-18T20:56:02-04:00[America/New_York]
Adjust Time Zone
For fun let's adjust to the India time zone.
ZonedDateTime zdtKolkata = zdt.withZoneSameInstant ( ZoneId.of ( "Asia/Kolkata" ) );
zdtKolkata : 2009-06-19T06:26:02+05:30[Asia/Kolkata]
Convert to j.u.Date
If you really need a java.util.Date object for use with classes not yet updated to the java.time types, convert. Note that you are losing the assigned time zone, but have the same moment automatically adjusted to UTC.
java.util.Date date = java.util.Date.from( zdt.toInstant() );
How about getSelectedDate? Anyway, specifically on your code question, the problem is with this line:
new SimpleDateFormat("yyyy-MM-dd");
The string that goes in the constructor has to match the format of the date. The documentation for how to do that is here. Looks like you need something close to "EEE MMM d HH:mm:ss zzz yyyy"
In response to:
"How to convert Tue Sep 13 2016 00:00:00 GMT-0500 (Hora de verano central (México)) to dd-MM-yy in Java?", it was marked how duplicate
Try this:
With java.util.Date, java.text.SimpleDateFormat, it's a simple solution.
public static void main(String[] args) throws ParseException {
String fecha = "Tue Sep 13 2016 00:00:00 GMT-0500 (Hora de verano central (México))";
Date f = new Date(fecha);
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
sdf.setTimeZone(TimeZone.getTimeZone("-5GMT"));
fecha = sdf.format(f);
System.out.println(fecha);
}
Does anyone know how to parse a date such as: Mon Aug 04 16:07:00 CEST 2014
to dd/MM/YYYY HH:MM:SS using DateTime formatter from Joda.
I've tried that:
final DateTimeFormatter sdf = DateTimeFormat.forPattern(DATE_FORMAT);
DateTime lastDateOnline = sdf.parseDateTime(lastCommunicationToDisplay.getDateOnLine().toString());
return lastDateOnline.toString();
DATE_FORMAT = dd/MM/YYYY HH:MM:SS and
lastCommunicationToDisplay.getDateOnLine().toString() = Mon Aug 04 16:07:00 CEST 2014
I can't find clear explanations about that library. I'm requested to use that instead of SimpleDateFormat because it's not threadsafe.
Solutions
If all you have to do is convert a LocalDate to a string respecting the pattern: "dd/MM/YYYY HH:mm:ss", then you can do it in a simpler way, using the overloaded toString() methods on LocalDate:
a) the one which receives the format string directly:
LocalDate date = lastCommunicationToDisplay.getDateOnLine();
System.out.println(date.toString("dd/MM/YYYY HH:mm:ss"));
b) the one which receives a DateTimeFormatter initialized with the aforementioned string:
DateTimeFormatter dtf = DateTimeFormat.forPattern("dd/MM/YYYY HH:mm:ss");
LocalDate date = lastCommunicationToDisplay.getDateOnLine();
System.out.println(date.toString(dtf));
What went wrong in your code
The format string you are using is not compatible with the date string you are sending as input. The way you used DateTimeFormatter is used for parsing strings that are in that format to LocalDates, not the other way around.
The format would be appropriate if your input string would look like the following:
04/08/2014 22:44:33
Since yours looks differently, the following value of the format is compatible (provided your timezone is always CEST):
DATE_FORMAT = "E MMM dd HH:mm:ss 'CEST' YYYY";
So the entire code should look like this:
String dateString = "Mon Aug 04 16:07:00 CEST 2014";
DateTimeFormatter dtf = DateTimeFormat.forPattern("E MMM dd HH:mm:ss 'CEST' YYYY");
LocalDate date = dtf.parseLocalDate(dateString);
System.out.println(date.toString("MM/dd/yyyy")); // or use toString(DateTimeFormatter) and use your pattern with a small adjusment here (dd/MM/YYYY HH:mm:ss)
However, I recommend one of the first 2 suggestions.
I have used the following
SimpleDateFormat df = new SimpleDateFormat("dd-mm-yyyy hh:mm:ss zzz");
Date date = new Date();
String formattedDate= df.format(date);
Date dateWithTime = df.parse(formattedDate);
i got the formatted date as string when i conver this into date i got error like
java.text.ParseException: Unparseable date: "Tue Feb 26 11:45:43 IST 2013"
How would convert to date or how i format a current date and get as date?
I think your code wouldn't throw ParseException. But it sure would definitely yield wrong output. your format should be:
"dd-MM-yyyy hh:mm:ss zzz"
Note that
MM---> Months
mm---> Minutes
Test with your code with out correcting the format:
Sat Jan 26 06:24:07 GMT 2013
Test with your code with correcting the format:
Tue Feb 26 06:20:51 GMT 2013
The date format should be as follows as shown in the exception. Change it to -
EEE MMM d hh:mm:ss z yyyy
The correct simpledateformat will be
SimpleDateFormat df = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
Please refer the link for proper date formatting and parsing
SimpleDateFormat