Inconsistent ParseExeption with Data Format in Java - java

I wrote a simple Util method to convert a String in Java to util.Date. What I am not able to figure out is why the method works for the first input, and fails for the second one, given that the inputs are identical:
Code:
package util;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class StringToDate {
public Date getDateFromString(String strDate, String dateFormat) {
DateFormat df = new SimpleDateFormat(dateFormat);
Date date = null;
try {
date = df.parse(strDate);
} catch (ParseException e) {
e.printStackTrace();
}
System.out.println(date);
return date;
}
public static void main(String[] args) {
StringToDate s2d = new StringToDate();
s2d.getDateFromString("12-18-11, 10:36 AM","MM-dd-yy, hh:mm a");
s2d.getDateFromString("02-04-12, 01:17 PM","MM-dd-yy, hh:mm a");
}
}
Output:
Sun Dec 18 10:36:00 CET 2011
null
java.text.ParseException: Unparseable date: "02-04-12, 01:17 PM"
at java.text.DateFormat.parse(DateFormat.java:337)
at util.StringToDate.getDateFromString(StringToDate.java:17)
at util.StringToDate.main(StringToDate.java:33)
Logically, the output should've been Sat Feb 04 13:17:00 CET 2012 going by the first output. Why is the ParseException being thrown?
EDIT: The following two lines work correctly:
s2d.getDateFromString("02-04-12", "MM-dd-yy");
s2d.getDateFromString("01:17 PM", "hh:mm a");
Output:
Sat Feb 04 00:00:00 CET 2012
Thu Jan 01 13:17:00 CET 1970
But the exception happens when I try to parse both date and time together.

Do you have a non-breaking space, or some other Unicode space character, somewhere in either your date string or format mask?
I was able to reproduce your error if I replaced one of the spaces in the second of your date strings with a non-breaking space, such as Unicode character 160.

Related

While Using JsonFormat annotation some dates are formatted to next year [duplicate]

This caused a Y2K-style bug in my software if you can imagine. Strange thing is the off-by-one year calculation only occurs for two days in the year, which I'm less sure how to troubleshoot.
The output:
03-Jan-2013
02-Jan-2013
01-Jan-2013
31-Dec-2013 ** strange
30-Dec-2013 ** strange
29-Dec-2012
28-Dec-2012
27-Dec-2012
26-Dec-2012
25-Dec-2012
I am not sure which part of the Java date utilities could cause such an error.
The code (since the test is so small I included a complete working program):
import java.util.Calendar;
import java.util.Date;
import java.text.SimpleDateFormat;
public class DateT {
private static String getFormattedBackscanStartTime(int days) {
SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MMM-YYYY");
Calendar workingDate = Calendar.getInstance();
workingDate.add(Calendar.DATE, -1 * days);
String formattedStartTime = dateFormat.format(workingDate.getTime());
return formattedStartTime;
}
public static void main(String args[]) {
for(int i = 35; i < 45; i++) {
System.out.println(getFormattedBackscanStartTime(i));
}
}
}
This is the problem:
"dd-MMM-YYYY"
YYYY is the week-year, not the calendar year. You want yyyy instead.
The last two days of calendar year 2012 were in the first week of week-year 2013. You should normally only use the week year in conjunction with the "week of year" specifier (w).
I am assuming you are using java 1.7.
The code snippet above will not work with java 1.6 as SimpleDateFormat("dd-MMM-YYYY") will raise an java.lang.IllegalArgumentException (YYYY is not available in java 1.6)
You need to use yyyy instead of YYYY.
Y -> week-year
y -> year
here
EDIT
Works great with yyyy:
$ java DateT
03-Jan-2013
02-Jan-2013
01-Jan-2013
31-Dec-2012
30-Dec-2012
29-Dec-2012
28-Dec-2012
27-Dec-2012
26-Dec-2012
25-Dec-2012
The problem lies in your date format string - year should be yyyy not YYYY.
If you print the value of workingDate.getTime() in each iteration of the loop, you'll see it has the expected values:
Thu Jan 03 11:19:33 EST 2013
Wed Jan 02 11:19:33 EST 2013
Tue Jan 01 11:19:33 EST 2013
Mon Dec 31 11:19:33 EST 2012
Sun Dec 30 11:19:33 EST 2012
Sat Dec 29 11:19:33 EST 2012
Fri Dec 28 11:19:33 EST 2012
Thu Dec 27 11:19:33 EST 2012
Wed Dec 26 11:19:33 EST 2012
Tue Dec 25 11:19:33 EST 2012
Therefore the problem lies in the SimpleDateFormat usage.
For the sake of completeness, here’s the modern answer using LocalDate (as recommended by Basil Bourque in a comment).
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class DateT {
private static DateTimeFormatter dateFormatter
= DateTimeFormatter.ofPattern("dd-MMM-uuuu", Locale.US);
private static String getFormattedBackscanStartTime(int days) {
return LocalDate.now(ZoneId.systemDefault()).minusDays(days).format(dateFormatter);
}
public static void main(String args[]) {
for(int i = 155; i < 165; i++) {
System.out.println(getFormattedBackscanStartTime(i));
}
}
}
Running this today I got
04-Jan-2017
03-Jan-2017
02-Jan-2017
01-Jan-2017
31-Dec-2016
30-Dec-2016
29-Dec-2016
28-Dec-2016
27-Dec-2016
26-Dec-2016
A few things to note:
Give an explicit locale to your formatter to control the langauge of your output. Even if you just pass Locale.getDefault() you are telling the reader that you have thought about locale and made a decision.
Similarly give an explicit time zone to LocalDate.now() to tell the reader you’ve made a decision (for example ZoneId.of("America/New_York") for a specific time zone; ZoneId.systemDefault() for the JVM’s current time zone setting).
I find the code simpler and more straightforward than the code using the oldfashioned Calendar class. This is typical for the newer classes.
I have used uuuu for year. yyyy (lowercase) works too, there will only be a difference for years before the common era (AKA BC).
You need to use lower case y for the year. Try this:
SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MMM-yyyy");

SimpleDateFormat for a HTTP Date

I can parse a HTTP Date but I don't get what I want, i.e. in this Example
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
public class Example01 {
public static void main(String[] argv) throws Exception {
Date date = null;
String dateValue = "Tue, 27 Jan 2015 07:33:54 GMT";
SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US);
dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println("date = " + date);
}
}
And the output I got is
date = Tue Jan 27 08:33:54 CET 2015.
What should I change, in order to get
date = Tue, 27 Jan 2015 08:33:54 GMT?
There are a few problems with your code:
You never initialize date to anything other than null, thus System.out.println("date = " + date); will print date = null, not date = Tue Jan 27 08:33:54 CET 2015.
The date string you provide is Tue, 27 Jan 2015 07:33:54 GMT, yet you ask the output to be Tue, 27 Jan 2015 08:33:54 GMT. The output is one hour later than the date string provided. I'm going to assume it's a typo on your side and you actually want the former as output.
You didn't use the SimpleDateFormat dateFormat object that you've got when printing out the date. System.out.println("date = " + date); calls the Date.toString() method which uses your local timezone.
A working version is:
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
public class Example01 {
public static void main(String[] argv) throws Exception {
Date date = null;
String dateValue = "Tue, 27 Jan 2015 07:33:54 GMT";
SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
date = dateFormat.parse(dateValue);
dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println("date = " + dateFormat.format(date));
}
}

Unparseable Date Or Wrong date

Hi I know there are many post on this but I can't figure out what's happening. I'm getting a date as a String from db and trying to convert it to another form.
Didn't understand that had to FIRST parse the string and then use another SimpleDateFormat to Format that date. I know get what I expected when printed.
Date one: Mon Jun 16 04:00:00 EDT 2014
06-16-2014
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
public class DateCheck {
public static void main(String[] args) {
try {
String str = "2014-06-16 04:00:00.0";
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
Date date1 = df.parse(str);
System.out.println(" Date one: " + date1);
SimpleDateFormat df2 = new SimpleDateFormat("MM-dd-yyyy");
System.out.println(df2.format(date1));
} catch (ParseException e) {
e.printStackTrace();
}
}
}
2 things to note, if i uncomment out the setLenient method i get unparseable date exception.
If commented out i get:Mon Oct 06 00:00:00 EDT 2183
Any help?
EDIT: Sorry that was just stupid. I know get Thu Jan 16 00:06:00 EST 2014
which is correct but i wanted it like 01-16-14
Your format doesn't match your input String.
The input String is in the format of "yyyy-MM-dd hh:mm.s" (there is an assumption on the format as we don't have enough information to make an accurate prediction)
String str = "2014-06-09 00:00.0";
DateFormat df = new SimpleDateFormat("MM-dd-yy");
df.setLenient(true);
Date result = df.parse(str);
Which outputs
Mon Jun 09 00:00:00 EST 2014
So either your format is wrong or the value in the database is wrong. This will depended on your requirements

Parse string to date using different formats/patterns

I need to parse a string to a date but have no prior knowledge which pattern the string will be in. This is similar to the question How to convert String to Date without knowing the format?.
To solve this I adopted couple of patterns to test the outcome. However, what I am getting is a bit strange.
Example 1:
import java.util.Date;
import org.apache.commons.lang3.time.DateUtils;
public Date extractDate(String dateStr) {
String [] datePatterns = {"yyyy-MM-dd", "dd-MM-yyyy"};
Date date = null;
try {
date = DateUtils.parseDate(dateStr, datePatterns);
}
catch (Exception except) {
except.printStackTrace();
}
return date;
}
public static void main(String[] args) throws Exception {
System.out.println ("2013-09-30:" + extractDate("2013-09-30") );
System.out.println ("30-09-2013:" + extractDate("30-09-2013") );
}
This gives:
2013-10-30:Wed Oct 30 00:00:00 EAT 2013
30-09-2013:Mon Mar 05 00:00:00 EAT 36
The result from parsing '30-09-2013' is obviously strange.
Example 2: Here I only switch the pattern
String [] datePatterns = {"dd-MM-yyyy", "yyyy-MM-dd"};
This gives:
2013-10-30:Mon Mar 05 00:00:00 EAT 36
30-09-2013:Mon Sep 30 00:00:00 EAT 2013
In example 2 the result from parsing '2013-10-30' is strange.
How can one parse date strings using different formats/patterns so that the resulting dates are correct?
Update to use parseDateStrictly. When I did this I got the following output:
2013-09-30:Mon Sep 30 00:00:00 EDT 2013
30-09-2013:Mon Sep 30 00:00:00 EDT 2013
My answer would be same. Without any prior knowledge of the format you can't parse date.
Few examples of writing a date would be: DD-MM-YYYY, MM-DD-YYYY, DD/MM/YYYY, MM/DD/YYYY, MM/DD/YY, DD/MM/YY. For only these many types of dates can you find any common pattern?
NO! Without knowing the format which user enters you can't parse it.
If you come up with pattern matching, a date such as 10-09-2010 which matches with MM-DD-YYYY format and DD-MM-YYYY format too. Here you will have a problem

java Date class - Why I have other date output in these lines?

My code:
SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss");
Date date = new Date();
System.out.println(sdf.format(date));
System.out.println(sdf.format(sdf.parse(sdf.format(date))));
and this output I get:
2013-02-08 15:48:37
2013-12-30 15:48:37
expected output:
2013-02-08 15:48:37
2013-02-08 15:48:37
look at the day and month of date
The problem comes from the method "parse"
==> "Parses text from the beginning of the given string to produce a date. The method may not use the entire text of the given string. "
The method may not use the entire text of the given string.
I've run your code and got the following :
System.out.println(sdf.format(date));
System.out.println(sdf.parse(sdf.format(date)));
System.out.println(sdf.format(sdf.parse(sdf.format(date))));
Result :
2013-02-08 14:54:39
Mon Dec 31 14:54:39 CET 2012
2013-12-31 14:54:39
As you can see the parse function converts the time correctly, but not the date itself. I think it is not intended to be used that way and therefore produces a weird result.
However, this is the first time I notice this, so I will not be able to give more details :)
To keep things simple, lets use a basic test case:
String date = "2013-02-08 15:48:37";
SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss");
System.out.println(sdf.parse(date));
// Output: Mon Dec 31 15:48:37 CET 2012
According to the SimpleDateFormat Javadoc, the format specifier Y is used to denote the "Week year". The correct format specifier for the "Year" is y - with this, we get the correct output:
sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(sdf.parse(date));
// Output: Fri Feb 08 15:48:37 CET 2013
Assuming that log is some kind of a logger, its standard practice for them to print out the time date and log level for every line. It makes it easier to debug from the log if need be,
I cannot reproduce this:
public static void main(String[] args) {
// TODO code application logic here
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = new Date();
Logger log = Logger.getLogger("InfoLogging");
log.info(sdf.format(date));
try {
log.info(sdf.format(sdf.parse(sdf.format(date))));
} catch (Exception e) {
e.printStackTrace();
}
}
Gives output:
Feb 8, 2013 2:57:09 PM javaapplication2.JavaApplication2 main
INFO: 2013-02-08 14:57:08
Feb 8, 2013 2:57:09 PM javaapplication2.JavaApplication2 main
INFO: 2013-02-08 14:57:08
Which Logger are you using?

Categories