Apache date utils parseDateStrictly method dosen't work properly - java

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.

Related

java - Unparseable date when using SimpleDateFormat

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.

Different values when parsing date [duplicate]

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);
}

Parser Exception for format EEEE, MMMM d, YYYY h:mm:ss a z

I'm getting parser exception on trying to parse string value:
"Thursday, July 27, 2006 10:10:02 PM PST"
To format:
"EEEE, MMMM d, YYYY h:mm:ss a z"
This is the program sample:
DateTime.parse("Thursday, July 27, 2006 10:10:02 PM PDT", DateTimeFormat.forPattern("EEEE, MMMM d, yyyy h:mm:ss a z"));
And this is the error message:
Invalid format: "Thursday, July 27, 2006 10:10:02 PM PDT" is malformed at "PDT"
this is my sample program
String str = "Thursday, July 27, 2006 10:10:02 PM PDT";
DateTimeFormatter formatterDateTime = DateTimeFormat.forPattern("EEEE, MMMM d, YYYY h:mm:ss a z");
try{
DateTime dt = DateTime.parse(str, formatterDateTime);
}catch(Exception ex)
{
System.out.println(ex.getMessage());
}
From the JodaTime docs:
Zone names: Time zone names ('z') cannot be parsed.
However SimpleDateFormat does support parsing of timezones.
SimpleDateFormat format = new SimpleDateFormat("EEEE, MMMM dd, YYYY h:mm:ss aa zzz");
Date date = format.parse("Thursday, July 27, 2006 10:10:02 PM PST");
As suggested by marba, the error most likely is caused by using Java 7 specific pattern with a Java 6.
Your code for parsing the date can look like this:
SimpleDateFormat df = new SimpleDateFormat("EEEE, MMMM dd, yyyy h:mm:ss aa zzz");
Date d = df.parse("Thursday, July 27, 2006 10:10:02 PM PST");
To test that the parsed date is the same as the provided date:
df.setTimeZone(TimeZone.getTimeZone("Pacific/Pitcairn"));
System.out.println(df.format(d));
Prints:
Thursday, July 27, 2006 10:10:02 PM PST
Refer to the Javadoc for more patterns.
What locale do you use? I think you have to explicitly provide Locale.US as a second parameter to SimpleDateFormat.
For Joda-Time library you can use following code to adjust locale:
DateTimeFormat.forPattern("EEEE, MMMM d, YYYY h:mm:ss a z").withLocale(Locale.US);
Update: Just found this related SO question, looks like you need to use SimpleDateFormat instead. Joda-Time parser does not support time zones:
SimpleDateFormat df = new SimpleDateFormat("EEEE, MMMM d, YYYY h:mm:ss a z");
Date d = df.parse("Thursday, July 27, 2006 10:10:02 PM PDT");
There are two problems with your code:
You have used Y (which specifies Week year) instead of y (which specifies Year). Check the documentation to learn more about symbols. Learn more about it here.
Your date-time string is in English and therefore your code won't work in an expected manner if you run it on a JVM with non-English Locale. Date-time parsing/formatting types are Locale-sensitive. Learn more about here.
java.time
The legacy date-time API (java.util date-time types and their formatting API, SimpleDateFormat) is outdated and error-prone. It is recommended to stop using it completely and switch to java.time, the modern date-time API*.
Solution using the modern API:
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("EEEE, MMMM d, u h:m:s a z", Locale.ENGLISH);
ZonedDateTime zdt = ZonedDateTime.parse("Thursday, July 27, 2006 10:10:02 PM PST", dtf);
System.out.println(zdt);
}
}
Output:
2006-07-27T22:10:02-07:00[America/Los_Angeles]
In case you need to convert this object of ZonedDateTime to an object of java.util.Date, you can do so as follows:
java.util.Date date = Date.from(zdt.toInstant());
Learn more about the the modern date-time API* from Trail: Date Time.
Solution using the legacy API:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
public class Main {
public static void main(String[] args) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("EEEE, MMMM d, y h:m:s a z", Locale.ENGLISH);
Date date = sdf.parse("Thursday, July 27, 2006 10:10:02 PM PST");
//...
}
}
* 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.

Getting wrong data when using SimpleDateFormat.parse()

I am getting the strangest error, when trying to parse a string as a calendar.
It seems that it messes up the Date object which I use to set the result calendar's time. The error is pretty inconsistent (or I see no logic in it). Can anyone point out what I might be doing wrong ?
public class caltest{
public static final SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss.SSS");
public static void main(String[] args) {
String date1 = "1992-03-11 12:00:12.123";
String date2 = "1993-03-11 12:00:12.123";
String date3 = "1994-03-11 12:00:12.123";
String date4 = "1995-03-11 12:00:12.123";
parseStringAsCalendar(date1);
parseStringAsCalendar(date2);
parseStringAsCalendar(date3);
parseStringAsCalendar(date4);
}
public static String calendarToString(Calendar cal) {
return sdf.format(cal.getTime());
}
public static Calendar parseStringAsCalendar(String s) {
Date time = null;
try {
time = sdf.parse(s);
} catch (ParseException e) {
System.out.println("Exception");
e.printStackTrace();
}
System.out.println(time.toString());
GregorianCalendar ret = new GregorianCalendar();
ret.setTime(time);
return ret;
}
}
The output is :
Sun Dec 29 12:00:12 CET 1991
Sun Dec 27 12:00:12 CET 1992
Sun Dec 26 12:00:12 CET 1993
Sun Jan 01 12:00:12 CET 1995
You're using YYYY in your format specifier, which is week year (as of Java 7, I believe). You want yyyy, which is just "year". (See the SimpleDateFormat documentation.)
I suspect the rest of the date was out because you tried to also specify the month and day, which aren't really "features" in the week year... if you'd specified the "week of week year" and day of week, it might have given some more sensible results, but only if you really meant to use week years, which I doubt :)
Use this:
public static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
It's lower case y for year, not upper case Y. With that, the result is:
Wed Mar 11 12:00:12 EST 1992
Thu Mar 11 12:00:12 EST 1993
Fri Mar 11 12:00:12 EST 1994
Sat Mar 11 12:00:12 EST 1995
See here:
http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html
java.time
The question and existing answers use SimpleDateFormat which was the correct thing to do in 2012. In Mar 2014, the java.util date-time API and their formatting API, SimpleDateFormat were supplanted by the modern Date-Time API. Since then, it is strongly recommended to stop using the legacy date-time API.
Solution using the modern date-time API: As you can learn from the documentation, the symbol Y is used for week-based-year whereas we need y (year-of-era) in this case. However, I prefer u to y.
Note that your date-time string has just date and time units (no time-zone or time-zone offset etc.). The java.time API provides you with LocalDateTime to represent such an object.
In case, you need to obtain a date-time object with time-zone or one representing just a moment in time, java.time provides you with specific types. You can check overview of java.time types here.
With Java 8, java.util date-time API was also upgraded to make it easy to switch to java.time API e.g. if you need java.util.Date instance from a an Instant, you can use Date#from.
Demo:
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.util.Date;
import java.util.Locale;
class Main {
public static void main(String[] args) {
String strDateTime = "1992-03-11 12:00:12.123";
DateTimeFormatter parser = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.SSS", Locale.ENGLISH);
// An alternative parser
DateTimeFormatter ldtParser = new DateTimeFormatterBuilder().append(DateTimeFormatter.ISO_LOCAL_DATE)
.appendLiteral(' ').append(DateTimeFormatter.ISO_LOCAL_TIME).toFormatter(Locale.ENGLISH);
LocalDateTime ldt = LocalDateTime.parse(strDateTime, parser);
System.out.println(ldt);
// Parsing using the alternative parser
ldt = LocalDateTime.parse(strDateTime, ldtParser);
System.out.println(ldt);
// Converting LocalDateTime to a ZonedDateTime
// Replace ZoneId.systemDefault() with applicable ZoneId e.g.
// ZoneId.of("America/New_York")
ZoneId zoneId = ZoneId.systemDefault();
ZonedDateTime zdt = ldt.atZone(zoneId);
System.out.println(zdt);
// Alternatively,
zdt = ZonedDateTime.of(ldt, zoneId);
System.out.println(zdt);
// Obtaining an Instant
Instant instant = zdt.toInstant();
System.out.println(instant);
// In case you need an instance of java.util.Date
Date date = Date.from(instant);
}
}
Output in my time-zone, Europe/London:
1992-03-11T12:00:12.123
1992-03-11T12:00:12.123
1992-03-11T12:00:12.123Z[Europe/London]
1992-03-11T12:00:12.123Z[Europe/London]
1992-03-11T12:00:12.123Z
ONLINE DEMO
Learn more about the modern Date-Time API from Trail: Date Time.
Note: Check this answer and this answer to learn how to use java.time API with JDBC.

Unparseable date exception in java

These lines of codes
SimpleDateFormat formatter = new SimpleDateFormat("dd/mm/yy");
ContentValues values = new ContentValues();
values.put(COL_EVENT_ID, appointment.mEventId);
try {
values.put(COL_START_DATE, String.valueOf(formatter.parse(appointment.mStartDate.toString())));
values.put(COL_END_DATE, String.valueOf(formatter.parse(appointment.mEndDate.toString())));
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
causees this exception
10-15 11:44:38.150: WARN/System.err(3861): java.text.ParseException: Unparseable date: "Mon Jan 10 00:10:00 GMT+02:00 2011"
what is the possible solution ?
Your format is completely wrong. Not only are you using mm (which means minutes) when you probably meant MM, but this:
Mon Jan 10 00:10:00 GMT+02:00 2011
is clearly not in the format
dd/MM/yy
You probably want something like
EEE MMM dd HH:mm:ss z yyyy
EDIT: That works for me in desktop Java:
import java.text.*;
public class Test {
public static void main(String[] args) throws ParseException {
String value = "Mon Jan 10 00:10:00 GMT+02:00 2011";
String pattern = "EEE MMM dd HH:mm:ss z yyyy";
DateFormat format = new SimpleDateFormat(pattern);
System.out.println(format.parse(value));
}
}
You may want to set the culture of the SimpleDateFormat of course.
java.time
The java.util Date-Time API and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern Date-Time API*.
Solution using java.time, the modern Date-Time API:
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
String strDateTime = "Mon Jan 10 00:10:00 GMT+02:00 2011";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("EEE MMM d H:m:s OOOO uuuu", Locale.ENGLISH);
ZonedDateTime zdt = ZonedDateTime.parse(strDateTime, dtf);
System.out.println(zdt);
}
}
Output:
ONLINE DEMO
Notes:
m specifies minute-of-hour whereas M specifies month-of-year. You have wrongly used the former.
The pattern used with the parser (DateTimeFormatter or SimpleDateFormat) should match the input date-time string. Your pattern, dd/mm/yy is off by far.
Never use SimpleDateFormat or DateTimeFormatter without a Locale.
Learn more about 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.

Categories

Resources