Unparseable Date Exception SimpleDateFormat for Hmm format - java

While validating the given string text is of Hmm format getting this error
java.text.ParseException: Unparseable date: "1637"
but this is working for text "747".
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Validation{
public void validateDateFormat(String format,String text){
SimpleDateFormat sdfrmt = new SimpleDateFormat(format);
sdfrmt.setLenient(false);
Date testDate = null;
try {
testDate = sdfrmt.parse(text);
} catch (ParseException e) {
System.out.println("dateFormat Exception :");
e.printStackTrace();
}
}
public static void main(String []args){
Validation val = new Validation();
val.validateDateFormat("Hmm","747"); //working
val.validateDateFormat("Hmm","1637");//not working
}
}
This is for validating the given columns from the uploaded file.So wrote this to be dynamic based on the format written in the config for each column.

Well, it should work.
But you should use the newer Java Date and Time API (JSR 310) available in the java.time package.
If you then replace Date with LocalTime, SimpleDateFormat with DateTimeFormatter (using the ofPattern factory method) and ParseException with DateTimeParseException, it'll work.

This is happening because the SimpleDateFormat is unable to parse the given date using the format you have given.
Let's understand - your format is Hmm and you have given the date as 747 then, of course during parsing, the first letter 7 of the date is mapped to the first letter "H" of the format i.e. hours and 47 is mapped to mm i.e. minutes and hence it is able to convert correctly but for the next date 1637 it is failing because it does not know which letter to assign to H.
Here are some options you can try to make it more generic, choose format such as HHmm and always give the date of length 4, for e.g. for 747 enter the input as 0747 and it should work.
Or choose a format that is more clear for the parser to map for e.g. you can choose the format as H:mm and give the inputs as 7:47 or 16:37 since there is a delimiter : between hours and minutes, the parser will be able to parse all types of time irrespective of the length of the given input 3 or 4.

Related

Raise exception when invalid string is passed to SimpleDateFormat in JAVA

I have an incoming string which should be a date in format "yyyyMMdd".(e.g today's Date - 20200507)
But sometimes input string can be an invalid format and Date parser should give an exception(parse exception), but it is not except it is returning a date object.
Sample Code in case when string is wrong or alphanumeric like below:
class Demo {
public static void main(String args[]) throws Exception {
String inputString = "9450524Q";
SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd", Locale.ENGLISH);
System.out.println(formatter.parse(inputString));
}}
Output:
Tue Apr 04 00:00:00 IST 9454
From the JavaDoc of DateFormat from which SimpleDateFormat directly inherits:
By default, parsing is lenient: If the input is not in the form used by this object's format method but can still be parsed as a date, then the parse succeeds. Clients may insist on strict adherence to the format by calling setLenient(false).
java.time
I recommend that you use java.time, the modern Java date and time API, for your date work. Advantages in your particular case include that the formatter you need is already built in and it does throw the exception that you ask for.
For demonstration I am using this auxiliary method:
public static void tryToParse(String dateString) {
try {
LocalDate date
= LocalDate.parse(dateString, DateTimeFormatter.BASIC_ISO_DATE);
System.out.println(dateString + " -> " + date);
} catch (DateTimeParseException dtpe) {
System.out.println(dateString + ": " + dtpe.getMessage());
}
}
Trying it out:
// Valid date
tryToParse("20200507");
// Invalid date value
tryToParse("20210229");
// Text after date
tryToParse("20200623Q");
// Example from question
tryToParse("9450524Q");
Output is:
20200507 -> 2020-05-07
20210229: Text '20210229' could not be parsed: Invalid date 'February 29' as '2021' is not a leap year
20200623Q: Text '20200623Q' could not be parsed, unparsed text found at index 8
9450524Q: Text '9450524Q' could not be parsed at index 6
Please also enjoy the precise and helpful exception messages. What happened in the last case was: year 9450 and month 52 were parsed, but since 4Q is not a valid two-digit date, the exception was thrown (before validating whether 52 is a valid month number).
What happened in your code
The SimpleDateFormat class is a notorious troublemaker. You have discovered a central design problem with it, but certainly not the only one. What it did was: It parsed 4-digit year, 9450, and two-digit month, 52. There are 12 months in a year, but a SimpleDateFormat with standard settings doesn’t care. It converts 48 of the months to 4 years and ends up in the 4th month 4 years later. Finally 4 is parsed as day of month. The remainder of the text, the Q, is ignored.
As I see it your example exhibits three flaws of SimpleDateFormat:
With standard settings it is lenient, it accepts an invalid month number.
When asked to parse two digits and finding only one, it settles with that one digit without reporting the error.
In the case of unparseable text after the parsed text it does not report any error either.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Related questions:
SimpleDateFormat giving wrong date instead of error
Modern answer
SimpleDateFormat parse(string str) doesn't throw an exception when str = 2011/12/12aaaaaaaaa?
Modern answer

Simple Date format year format issue

I am getting issues with Date Format. I am using SimpleDateFormat to parse date and using MM/dd/yyyy format to parse date, its working properly with correct input like 11/11/2011 and its returning correct result (Fri Nov 11 00:00:00 IST 2011)
But if we enter 11/11/11 as input then its not working properly (Wed Nov 11 00:00:00 IST 11), nor giving parse error.
public static void main(String[] args) {
String format = "MM/dd/yyyy";
String dt = "11/11/11";
Date date = null;
try {
date = TestDate.parDate(dt, format);
} catch (ParseException e) {
e.printStackTrace();
}
System.out.println(date);
}
public static Date parDate(String value, String dateFormat) throws ParseException {
Date date = null;
date = new SimpleDateFormat(dateFormat).parse(value);
return date;
}
If you can use Java 8 or above, use DateTimeFormatter and LocalDate classes to parse date values. It will throw an error if the input is not in the expected format.
DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("MM-dd-yyyy");
LocalDate date1 = LocalDate.parse("11-11-2011", formatter1);
System.out.println(date1);
Above will work as expected but if you try to parse "11-11-11" with the same formatter object you will get an exception like
Exception in thread "main" java.time.format.DateTimeParseException: Text '11-11-11' could not be parsed at index 6
at java.time.format.DateTimeFormatter.parseResolved0(Unknown Source)
at java.time.format.DateTimeFormatter.parse(Unknown Source)
at java.time.LocalDate.parse(Unknown Source)
at com.is.TestDate.main(TestDate.java:14)
Use MM/dd/yy for both 11/11/11 and 11/11/2011.
If you want to put a strict check, that would not be possible with SimpleDateFormat. You can instead put a pattern check on the date string:
if (!dt.matches("\\d{2}/\\d{2}/\\d{4}")) {
//throw exception
}
It's not an issue. It's correct accroding to Java API of SimpleDateFormat. It says regarding the pattern of Year:
For parsing, if the number of pattern letters is more than 2, the year
is interpreted literally, regardless of the number of digits. So using
the pattern "MM/dd/yyyy", "01/11/12" parses to Jan 11, 12 A.D.
Thus there is no exception thrown as you provided a valid input.
If you have to deal with two different date formats for a year yyyy and yy convert one version to the other or use two formatter - if you have to use SimpleDateFormat at all.
That's the way since Java 8: How to parse/format dates with LocalDateTime? (Java 8)

String to Date Conversion mm/dd/yy to YYYY-MM-DD in java [duplicate]

This question already has answers here:
Java Date Error
(8 answers)
Closed 4 years ago.
I want to convert String values in the format of mm/dd/yy to YYYY-MM-DD Date. how to do this conversion?
The input parameter is: 03/01/18
Code to convert String to Date is given below
public static Date stringToDateLinen(String dateVlaue) {
Date date = null;
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
try {
date = formatter.parse(dateVlaue);
} catch (ParseException e) {
e.printStackTrace();
}
return date;
}
When tried to convert using this method it shows the following error
java.text.ParseException: Unparseable date: "03/01/18"
As you say the input is in a different format, first convert the String to a valid Date object. Once you have the Date object you can format it into different types , as you want, check.
To Convert as Date,
SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yy");
date = formatter.parse(dateVlaue);
To Print it out in the other format,
SimpleDateFormat formatter1 = new SimpleDateFormat("yyyy-MM-dd");
dateString = formatter1.format(date)
You are writing it the wrong way. In fact, for the date you want to convert, you need to write
SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yy");
The format you are passing to SimpleDateFormat is ("yyyy-MM-dd") which expects date to be in form 2013-03-01 and hence the error.
You need to supply the correct format that you are passing your input as something like below
public static Date stringToDateLinen(String dateVlaue) {
Date date = null;
SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yy");
try {
date = formatter.parse(dateVlaue);
} catch (ParseException e) {
e.printStackTrace();
}
return date;
}
The solution for the above problem
Convert the String date value in the Format of "dd/mm/yy" to Date.
By using the converted Date can able to frame the required date format.
The method has given below
public static String stringToDateLinen(String dateVlaue) {
Date date = null;
SimpleDateFormat formatter = new SimpleDateFormat("dd/mm/yy");
String dateString = null;
try {
// convert to Date Format From "dd/mm/yy" to Date
date = formatter.parse(dateVlaue);
// from the Converted date to the required format eg : "yyyy-MM-dd"
SimpleDateFormat formatter1 = new SimpleDateFormat("yyyy-MM-dd");
dateString = formatter1.format(date);
} catch (ParseException e) {
e.printStackTrace();
}
return dateString;
}
EDIT: Your question said “String values in the format of mm/dd/yy”, but I understand from your comments that you meant “my input format is dd/mm/yy as string”, so I have changed the format pattern string in the below code accordingly. Otherwise the code is the same in both cases.
public static Optional<LocalDate> stringToDateLinen(String dateValue) {
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("dd/MM/yy");
try {
return Optional.of(LocalDate.parse(dateValue, dateFormatter));
} catch (DateTimeParseException dtpe) {
return Optional.empty();
}
}
Try it:
stringToDateLinen("03/01/18")
.ifPresentOrElse(System.out::println,
() -> System.out.println("Could not parse"));
Output:
2018-01-03
I recommend you stay away from SimpleDateFormat. It is long outdated and notoriously troublesome too. And Date is just as outdated. Instead use LocalDate and DateTimeFormatter from java.time, the modern Java date and time API. It is so much nicer to work with. A LocalDate is a date without time of day, so this suites your requirements much more nicely than a Date, which despite its name is a point in time. LocalDate.toString() produces exactly the format you said you desired (though the LocalDate doesn’t have a format in it).
My method interprets your 2-digit year as 2000-based, that is, from 2000 through 2099. Please think twice before deciding that this is what you want.
What would you want to happen if the string cannot be parsed into a valid date? I’m afraid that returning null is a NullPointerException waiting to happen and a subsequent debugging session to track down the root cause. You may consider letting the DateTimeParseException be thrown out of your method (just declare that in Javadoc) so the root cause is in the stack trace. Or even throw an AssertionError if the situation is not supposed to happen. In my code I am returning an Optional, which clearly signals to the caller that there may not be a result, which (I hope) prevents any NullPointerException. In the code calling the method I am using the ifPresentOrElse method introduced in Java 9. If not using Java 9 yet, use ifPresent and/or read more about using Optional elsewhere.
What went wrong in your code?
The other answers are correct: Your format pattern string used for parsing needs to match the input (not your output). The ParseException was thrown because the format pattern contained hyphens and the input slashes. It was good that you got the exception because another problem is that the order of year, month and day doesn’t match, neither does the number of digits in the year.
Link
Oracle tutorial: Date Time explaining how to use java.time.

GET DateTime from String [duplicate]

This question already has answers here:
Parsing ISO-8601 DateTime with offset with colon in Java
(4 answers)
Closed 6 years ago.
I am developing a java sample in which date is in string like - 2016-07-19T16:54:03.000+05:30.
I want to convert it to DateTime object.How can I do it in java?
I have tried this code -
DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSS+Z").parseDateTime("2016-07-19T16:54:03.000+05:30")
It give java.lang.IllegalArgumentException: Invalid format: "2016-07-19T16:54:03.000+05:30" is malformed at "05:30" exception.
You need to use ZZ instead of just Z for the timezone information.
i.e.
DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZZ").parseDateTime("2016-07-19T16:54:03.000+05:30")
Taken from the Javadoc:
The count of pattern letters determine the format.
Zone: 'Z' outputs offset without a colon, 'ZZ' outputs the offset with a colon, 'ZZZ' or more outputs the zone id.
You could use SimpleDateFormat:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
class Main {
public static void main(String[] args) {
try {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX");
Date parsed = format.parse("2016-07-19T16:54:03.000+05:30");
System.out.println(parsed);
} catch (ParseException e){
e.printStackTrace();
}
}
}
Output:
Tue Jul 19 11:54:03 UTC 2016
Try it here!
You can try java.text.DateFormat
String DEFAULT_DATE_PARSE_PATTERN="dd.MM.yyyy";
DateFormat format = new SimpleDateFormat(DEFAULT_DATE_PARSE_PATTERN);
Date result = format.parse(your_value);

Java: unparseable date exception

While trying to transform the date format I get an exception:unparseable date and don't know how to fix this problem.
I am receiving a string which represents an event date and would like to display this date in different format in GUI.
What I was trying to do is the following:
private String modifyDateLayout(String inputDate){
try {
//inputDate = "2010-01-04 01:32:27 UTC";
Date date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z").parse(inputDate);
return new SimpleDateFormat("dd.MM.yyyy HH:mm:ss").format(date);
} catch (ParseException e) {
e.printStackTrace();
return "15.01.2010";
}
}
Anyway the line
String modifiedDateString = originalDate.toString();
is dummy. I would like to get a date string in the following format:
dd.MM.yyyy HH:mm:ss
and the input String example is the following:
2010-01-04 01:32:27 UTC
Does anyone know how to convert the example date (String) above into a String format dd.MM.yyyy HH:mm:ss?
Thank you!
Edit: I fixed the wrong input date format but still it doesn't work. Above is the pasted method and below is the screen image from debugging session.
alt text http://img683.imageshack.us/img683/193/dateproblem.png
#Update
I ran
String[] timezones = TimeZone.getAvailableIDs();
and there is UTC String in the array. It's a strange problem.
I did a dirty hack that works:
private String modifyDateLayout(String inputDate){
try {
inputDate = inputDate.replace(" UTC", "");
Date date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(inputDate);
return new SimpleDateFormat("dd.MM.yyyy HH:mm:ss").format(date);
} catch (ParseException e) {
e.printStackTrace();
return "15.01.2010";
}
}
But still I would prefer to transform the original input without cutting timezone away.
This code is written for Android phone using JDK 1.6.
What you're basically doing here is relying on Date#toString() which already has a fixed pattern. To convert a Java Date object into another human readable String pattern, you need SimpleDateFormat#format().
private String modifyDateLayout(String inputDate) throws ParseException{
Date date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z").parse(inputDate);
return new SimpleDateFormat("dd.MM.yyyy HH:mm:ss").format(date);
}
By the way, the "unparseable date" exception can here only be thrown by SimpleDateFormat#parse(). This means that the inputDate isn't in the expected pattern "yyyy-MM-dd HH:mm:ss z". You'll probably need to modify the pattern to match the inputDate's actual pattern.
Update: Okay, I did a test:
public static void main(String[] args) throws Exception {
String inputDate = "2010-01-04 01:32:27 UTC";
String newDate = new Test().modifyDateLayout(inputDate);
System.out.println(newDate);
}
This correctly prints:
03.01.2010 21:32:27
(I'm on GMT-4)
Update 2: as per your edit, you really got a ParseException on that. The most suspicious part would then be the timezone of UTC. Is this actually known at your Java environment? What Java version and what OS version are you using? Check TimeZone.getAvailableIDs(). There must be a UTC in between.
I encountered this error working in Talend. I was able to store S3 CSV files created from Redshift without a problem. The error occurred when I was trying to load the same S3 CSV files into an Amazon RDS MySQL database. I tried the default timestamp Talend timestamp formats but they were throwing exception:unparseable date when loading into MySQL.
This from the accepted answer helped me solve this problem:
By the way, the "unparseable date" exception can here only be thrown by SimpleDateFormat#parse(). This means that the inputDate isn't in the expected pattern "yyyy-MM-dd HH:mm:ss z". You'll probably need to modify the pattern to match the inputDate's actual pattern
The key to my solution was changing the Talend schema. Talend set the timestamp field to "date" so I changed it to "timestamp" then I inserted "yyyy-MM-dd HH:mm:ss z" into the format string column view a screenshot here talend schema
I had other issues with 12 hour and 24 hour timestamp translations until I added the "z" at the end of the timestamp string.
From Oracle docs, Date.toString() method convert Date object to a String of the specific form - do not use toString method on Date object. Try to use:
String stringDate = new SimpleDateFormat(YOUR_STRING_PATTERN).format(yourDateObject);
Next step is parse stringDate to Date:
Date date = new SimpleDateFormat(OUTPUT_PATTERN).parse(stringDate);
Note that, parse method throws ParseException

Categories