I'm trying to execute this code:
Date date = null;
if (detailsBean.getDiscoveryProjectBean ().getCreatedDate ()==null ||
detailsBean.getDiscoveryProjectBean ().getCreatedDate ().equalsIgnoreCase(""))
{
projectDetails.getDiscoveryProject().setCreationTime(new Date());
}
else
{
try
{
date = new SimpleDateFormat (FormatUtils.simpleFormat).
parse (detailsBean.getDiscoveryProjectBean ().getCreatedDate ());
} catch (Exception e) {
throw new PanDaApplicationException (e.getMessage ());
}
projectDetails.getDiscoveryProject().setCreationTime(date);
}
in the try block a ParseException exception is thrown. I don't know the cause of that as the code seems fine, however. the definition of the FormatUtils.simpleFormat is public static final String simpleFormat = "dd-MMM-yyyy" and detailsBean.getDiscoveryProjectBean().getCreatedDate() have value like 28-Feb-2013
I really don't have any clues why this exception is thrown and I need help.
My guess is that the problem is the way that SimpleDateFormat uses your default locale - if your locale doesn't use "Feb" as an abbreviated month name, you'll have problems. So if all your data is actually in English, you might want:
DateFormat format = new SimpleDateFormat(FormatUtils.simpleFormat, Locale.US);
format.setTimeZone(...); // See below
date = format.parse(detailsBean.getDiscoveryProjectBean().getCreatedDate());
Note the part about setting the time zone. Again, SimpleDateFormat will use your system default if you don't specify anything else. (You'll get the instant of "midnight in the specified time zone" as the Date value.)
I would also strongly urge you to consider using Joda Time instead of the built-in Date/Calendar types - it's a much better date/time API.
Locale.setDefault (Locale.ROOT);
System.out.println (new SimpleDateFormat ("dd-MMM-yyyy").parse ("28-Feb-2013"));
Locale.setDefault (Locale.forLanguageTag ("ru"));
System.out.println (new SimpleDateFormat ("dd-MMM-yyyy").parse ("28-Feb-2013"));
For me output is:
Thu Feb 28 00:00:00 MSK 2013
Exception in thread "main" java.text.ParseException: Unparseable date: "28-Feb-2013"
at java.text.DateFormat.parse(DateFormat.java:357)
at DateFormat.main(DateFormat.java:19)
So the same date successfully parsed with ROOT locale, but failed with Russian.
Related
I wanted to validate date in client side so I wrote the following code. But instead of getting an exception I am getting a proper date object for 31st of February date string, which is clearly an invalid date.
public class Test {
public static void main(String[] args) {
String dateFormat = "HH:mm:ss MM/dd/yyyy";
String dateString = "11:30:59 02/31/2015";
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(dateFormat, Locale.US);
try {
LocalDateTime date = LocalDateTime.parse(dateString, dateTimeFormatter);
System.out.println(date);
} catch (Exception e) {
// Throw invalid date message
}
}
}
Output : 2015-02-28T11:30:59
Does anyone know why LocalDateTime is parsing this date instead of throwing an exception.
You just need a strict ResolverStyle.
Parsing a text string occurs in two phases. Phase 1 is a basic text parse according to the fields added to the builder. Phase 2 resolves the parsed field-value pairs into date and/or time objects. This style is used to control how phase 2, resolving, happens.
Sample code - where withResolverStyle(ResolverStyle.STRICT) is the important change, along with the use of uuuu rather than yyyy (where uuuu is "year" and "yyyy" is "year of era", and therefore ambiguous):
import java.time.*;
import java.time.format.*;
import java.util.*;
public class Test {
public static void main(String[] args) {
String dateFormat = "HH:mm:ss MM/dd/uuuu";
String dateString = "11:30:59 02/31/2015";
DateTimeFormatter dateTimeFormatter = DateTimeFormatter
.ofPattern(dateFormat, Locale.US)
.withResolverStyle(ResolverStyle.STRICT);
try {
LocalDateTime date = LocalDateTime.parse(dateString, dateTimeFormatter);
System.out.println(date);
} catch (DateTimeParseException e) {
// Throw invalid date message
System.out.println("Exception was thrown");
}
}
}
The Java 8 DateTimeFormatter uses yyyy to mean YEAR_OF_ERA, and uuuu to mean YEAR. You need to modify your pattern string as follows:
String dateFormat = "HH:mm:ss MM/dd/uuuu";
The DateTimeFormatter defaults to using the SMART resolver style, but you want it to use the STRICT resolver style. Modify your dateTimeFormatter initialization code as follows:
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(dateFormat, Locale.US)
.withResolverStyle(ResolverStyle.STRICT);
It is not rounding down. February has never had 31 days, and it is impossible to use a validating date / time object to represent a day that doesn't exist.
As a result, it takes the invalid input and gives you the best approximation to the correct date (the last date of February that year).
SimpleDateFormat inherits from DateFormat which has a setLenient(boolean value) method on it. I would expect that if you called setLenient(true) prior to parsing, it would probably complain more, as detailed in the javadocs.
try {
SimpleDateFormat df = new java.text.SimpleDateFormat("HH:mm:ss MM/dd/yyyy");
df.setLenient(false);
System.out.println(df.parse("11:30:59 02/29/2015"));
} catch (java.text.ParseException e) {
System.out.println(e);
}
I found one solution to recognize date as a valid date with DateFormat.setLenient(boolean). If you try to parse any invalid date it will throws parse exception.
Edit:
Java 8, but this will raise exception if a month is not between 1 and 12, if a day is more than 32. Exactly not working. But for month its working.
try {
TemporalAccessor ta = DateTimeFormatter.ofPattern("HH:mm:ss MM/dd/yyyy").parse("11:30:59 02/32/2015");
} catch (Exception e) {
System.out.println(e);
}
Output:
java.time.format.DateTimeParseException: Text '11:30:59 02/32/2015' could not be
parsed: Invalid value for DayOfMonth (valid values 1 - 28/31): 32
LocalDateTime.parse will only throw an error if the String passed in contains invalid characters, a number of days exceeding 31 or a month exceeding 12.
For example, if you modified your code as such:
String dateString = "11:30:59 0zz2/31/2015";
an exception would be thrown caused by the invalid 'zz' characters within your given date. As to why it's 'rounding-down' the date so to speak, that I don't know.
Source: https://docs.oracle.com/javase/8/docs/api/java/time/LocalDateTime.html#parse-java.lang.CharSequence-
I have a small block of code which parses response generation time from the response itself and turns it into a date for future purposes. It goes like this:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
Date responseTime = sdf.parse(RStime);
And it almost works like a charm. To be precise, it works 99.9% of the time, with the exception of one case: When the millisecond part is 000 then the Server doesn't append the .000 milliseconds at all, hence we have a problem.
Now, according to SimpleDateFormat docs if parsing fails, the function returns null. However, I probably misinterpreted it as it just throws an exception.
I am very new to Java and try-catch mechanisms, so could anyone please provide an elegant good-practice solution for handling such cases?
Thanks!
java.time
String rsTime = "2018-04-09T10:47:16.999-02:00";
OffsetDateTime responseTime = OffsetDateTime.parse(rsTime);
System.out.println("Parsed date and time: " + responseTime);
Output from this snippet is:
Parsed date and time: 2018-04-09T10:47:16.999-02:00
It works just as well for the version with the 000 milliseconds omitted:
String rsTime = "2018-04-09T10:47:16-02:00";
Parsed date and time: 2018-04-09T10:47:16-02:00
The classes you used, SimpleDateFormat and Date, are poorly designed and long outdated (the former in particular notoriously troublesome). So it is not only in this particular case I recommend using java.time, the modern Java date and time API, instead. However, the strings from your server are in ISO 8601 format, and OffsetDateTime and the other classes of java.time parse this format as their default, that is, without any explicit formatter, which already makes the task remarkably easier. Furthermore, in the standard the fractional seconds are optional, which is why both the variants of the string are parsed without any problems. OffsetDateTime also prints ISO 8601 back from it’s toString method, which is why in both cases a string identical to the parsed one is printed.
Only in case you indispensably need an old-fashioned Date object for a legacy API that you cannot change just now, convert like this:
Instant responseInstant = responseTime.toInstant();
Date oldfashionedDateObject = Date.from(responseInstant);
System.out.println("Converted to old-fashioned Date: " + oldfashionedDateObject);
Output on my computer in Europe/Copenhagen time zone is:
Converted to old-fashioned Date: Mon Apr 09 14:47:16 CEST 2018
Link: Oracle tutorial: Date Time explaining how to use java.time.
According to the SimpleDateFormat doc that you mentioned the parse method:
public Date parse(String text, ParsePosition pos)
Throws:
NullPointerException - if text or pos is null.
So one option is to catch that exception and do what you need inside the catch, for example:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
try {
Date responseTime = sdf.parse(RStime, position);
} catch (NullPointerException e) {
e.printStackTrace();
//... Do extra stuff if needed
}
Or the inherited method from DateFormat:
public Date parse(String source)
Throws:
ParseException - if the beginning of the specified string cannot be
parsed.
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
try {
Date responseTime = sdf.parse(RStime);
} catch (ParseException e) {
e.printStackTrace();
//... Do extra stuff if needed
}
Is it actually an exceptional situation? If it is not then you probably shouldn't use exceptions in that case. In my opinion it is normal that time can end with .000ms. In this case you can check if the string contains . (dot) and if not append .000 to the end.
if(!RStime.contains(".")){
RStime+=".000";
}
Edit: I've forgot about time zone in the time String. You probably need something a little bit more complicated for that. Something like this should do it:
if(!RStime.contains(".")){
String firstPart = RStime.substring(0, 21);
String secondPart = RStime.substring(21);
RStime = firstPart + ".000" + secondPart;
}
You can check for a dot and then use the first or second format:
String timeString = "2018-04-09T10:47:16.999-02:00";
//String timeString = "2018-04-09T10:47:16-02:00";
String format = timeString.contains(".") ? "yyyy-MM-dd'T'HH:mm:ss.SSSXXX" : "yyyy-MM-dd'T'HH:mm:ssXXX";
Date responseTime = new SimpleDateFormat(format).parse(timeString);
System.out.println("responseTime: " + responseTime);
If you comment-out the first line and comment-in the second and run it again, it will both print out:
responseTime: Mon Apr 09 14:47:16 CEST 2018
By the way:
Java 7 (the version you use obviously) returns a java.text.ParseException: Unparseable date: "2018-04-09T10:47:16-02:00"
Optionals are supported since Java 8.
I am reciving a input in this format 2012-01-13T00:00:00.000-05:00 and which i need to convert this into yyyyMMdd Format .
I have also set the SimpleDateFormat.setLenient(false);
This is my coding for parsing the Date
public static String getparsedDate(String date) throws Exception {
DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS", Locale.US);
sdf.setLenient(false);
String s1 = date;
String s2 = null;
Date d;
try {
d = sdf.parse(s1);
s2 = (new SimpleDateFormat("yyyyMMdd")).format(d);
} catch (ParseException e) {
e.printStackTrace();
}
return s2;
}
But i am getting a Exception at
java.text.ParseException: Unparseable date: "201201"
at java.text.DateFormat.parse(Unknown Source)
Could anybody please let me know , what might be the issue ?
You are missing the timezone in your format string. If you check the argument, it is finishing with -05:00 and you are also using Lenient==false.
Unfortunately, the time zone formats available to SimpleDateFormat are not ISO8601 compliant. SimpleDateFormat understands time zone strings like "GMT+01:00" or "+0100", the latter according to RFC822. Therefore using SimpleDateFormat does not seem as an option in your case (since you use UTC−05:00 as timezone).
Instead of SimpleDateFormat you need to use JodaTime for that type of date format.
I am trying to do date validation. When the user enters something like: 2552533 Jan 2012 1340001 this gets parsed as: Wed Sep 03 07:41:00 EDT 9000. Here is my code:
SimpleDateFormat sdf = new SimpleDateFormat("dd MMM yyyy kkmm");
...
Date test;
try {
test = sdf.parse(dateString);
} catch (Exception e) {
...
Here dateString is a string that I'm trying to parse into a date. If the string isn't a valid date, like: 552533 Jan 2012 1340001, I was hoping for an error to be thrown. What am I doing wrong?
Try this (before parsing the actual date):
sdf.setLenient(false);
See also:
Make SimpleDateFormat.parse() fail on invalid dates (e.g. month is greater than 12)
SimpleDateFormat.parse does not throw any exception in case of error, it returns null. From the javadoc:
Returns:
A Date parsed from the string. In case of error, returns null.
Throws:
NullPointerException - if text or pos is null.
So you can do:
SimpleDateFormat sdf = new SimpleDateFormat("dd MMM yyyy kkmm");
...
Date test = sdf.parse(dateString);
if(test == null) {
// there was an error
}
As Tudor mentions, SimpleDateFormat does not throw an exception when it fails to parse. One alternative is DateUtils.parseDate90 (javadocs) from the Apache Commons available here.
I'm parsing this date format from XML:=> "2011-12-06T07:41:14.016+00:00", and I'm getting this error:
W/System.err(574): java.text.ParseException: Unparseable date:
"2011-12-06T07:41:14.016+00:00"
I'm certain it's the formatting statement I'm using, but I can't figure out what it SHOULD be...
Here's the statement I'm using:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSSZ:ss");
I get how to create a format for this part: "2011-12-06T07:41:14....", it's this other part :=> ".016+00:00" that's throwing me for a loop.
I've looked for answers here already: Android SimpleDateFormat Page, and here Oracle SimpleDateFormat Page, but I fear I'm missing something fundamental....
Do you have any suggestions on a proper format statement for that particular date format, or pertinent resources to peruse?
Big Thanks in advance!
The "Z" pattern matches +0000 and not +00:00 so if you remove the last ":" before you parse then it will work.
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSSZ");
try {
Date myDate = sdf.parse( "2011-12-06T07:41:14.016+00:00".replaceAll( "([0-9\\-T]+:[0-9]{2}:[0-9.+]+):([0-9]{2})", "$1$2" ) );
System.out.println( myDate );
} catch (ParseException e) {
e.printStackTrace();
}
"yyyy-MM-dd'T'HH:mm:ss.SSSZ" 2001-07-04T12:08:56.235-0700
The :ss at the end looks incorrect
As one of the answers in the question I linked shows, you can use
String string = "2011-12-06T07:41:14.016+00:00";
Calendar cal = DatatypeConverter.parseDateTime(string);
What's the best way to parse an XML dateTime in Java?