Pergunta

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.


Based on the answer from @GriffeyDog.....

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:

  • Have both methods return a String value
  • Modify checkDateFormat so that instead of returning sdFormat.parse(datetime) it assigns that to a Date object
  • Set a new format to standardize a date return String - yyyyMMdd HH:mm:ss
  • Use that format to return a String of the date - sdFormat.format(date)
  • Modify the Oracle calls that did something with the date to use Oracle's to_date() function instead of relying on conversion of a Date object

This seems to do what we want. 20140309020500 will now be allowed as a valid date.

Foi útil?

Solução

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top