We ran into an issue with a job when it tried to use a SimpleDateFormat.parse(datestr)
call when the datestr
included times that happened to fall within DST rules (i.e. a ParseException
happened with 20140309020100
(yyyyMMddHHmmss
).
I am trying to build code to handle this issue and make it generic to work with all our different formats:
public static Date validDateTimestamp(String datetime, String [] formats)
throws ParseException
{
for (int inx=0; inx < formats.length; inx++)
{
try {
return checkDateFormat(datetime, formats[inx]);
}
catch (ParseException e1)
{
// ignore this error, just try the next format
}
}
// no good date returned using any format, throw an exception
throw new ParseException("bad date: " + datetime, 0);
}
private static Date checkDateFormat(String datetime, String format)
throws ParseException
{
SimpleDateFormat sdFormat = new SimpleDateFormat(format);
sdFormat.setLenient(false);
try {
return sdFormat.parse(datetime);
} catch (ParseException e)
{
throw e;
}
}
This still has the same issue as before (ParseException
for datetime
).
I have tried associating the SimpleDateFormat
to a TimeZone
, but that made it so that the returned date was offset by 5 hours.
TimeZone utc = TimeZone.getTimeZone("UTC");
sdFormat.setTimeZone(utc);
Is there a way to use a SimpleDateFormat
to parse a date so that it doesn't change the datetime from what was passed in on the String, will ensure that the date is valid, and also will ignore Daylight Saving Time offsets (i.e. won't throw a ParseException
)?
We are not looking to add any new libraries to the project, but to get it working with the standard Java classes.
The Date
object returned from the SimpleDateFormat.parse()
call will be in the timezone of where it is run. In my case, EDT. Even setting the timezone of the SimpleDateFormat
will not help with that - other than the fact that it will parse what was a bad datetimestamp for EDT; what will get into the Date object will be converted to local time. Since changing the JVM settings for this are not a viable option (shared servers), instead I modified the code as follows:
String
valuecheckDateFormat
so that instead of returning sdFormat.parse(datetime)
it assigns that to a Date
objectString
- yyyyMMdd HH:mm:ss
String
of the date - sdFormat.format(date)
to_date()
function instead of relying on conversion of a Date
objectThis seems to do what we want. 20140309020500
will now be allowed as a valid date.
You are returning a Date
object, which represents an exact number of milliseconds since 1/1/1970 00:00 UTC. A SimpleDateFormat#parse
cannot give you such a Date
object if you're not providing it with a valid date/time. In order to convert your date/time string into a Date
, SimpleDateFormat
needs a time zone to work with. It will use your default locale's time zone if you don't provide it with one. And in your default time zone, DST exists, and you are not providing a valid date/time string for those considerations.