0

In spring batch I'm loading csv file where I'm also parsing dates. Everything seems to be working fine except for one single row where I get exception

Unparseable date: "2014-03-09 02:07:07", format: [yyyy-MM-dd HH:mm:ss]

I've double checked my input file and there are no special/invisible characters in this failed row.

Caused by: java.lang.IllegalArgumentException: Unparseable date: "2014-03-09 02:07:07", format: [yyyy-MM-dd HH:mm:ss]
    at org.springframework.batch.item.file.transform.DefaultFieldSet.parseDate(DefaultFieldSet.java:778)
    at org.springframework.batch.item.file.transform.DefaultFieldSet.readDate(DefaultFieldSet.java:595)

Thanks for help!


EDIT

When I change hour in date from 02 to something else (e.g. '2014-03-09 03:07:07'), it works. When I then change it manually back to 02 it fails again. How can this be possible? Changing other elements of date does not help. Only changing hour.

I only experience this on our unix server with America/New_York timezone. From my local machine everything is working. JDK version on both are identical.

Community
  • 1
  • 1
Majky
  • 1,943
  • 1
  • 18
  • 30

1 Answers1

1

It was caused by combination of TimeZone settings, daylight saving and SimpleDateFormat.lenient property.

Our linux host has America/New_York timezone.

Date for which I was getting error is 9-MAR-2014 @ 2:07:07 am which is exact date and time when in NYK timezone time shifts 1 hour forward - daylight saving (from 2am to 3am).

Normally when SimpleDateFormat converts such date it automatically changes it to 3am. Setting lenient property to false (default value for is true) prevents this and throws exception - HOUR_OF_DAY: 2 -> 3.

This exception is consumed in process and at the end we get only IllegalArgumentException with Unparseable date: "2014-03-09 02:07:07", format: [yyyy-MM-dd HH:mm:ss] message.

Here I'm using spring-boot DefaultFieldSet which has implementation where it is specifically setting lenient to false.

/* ... some other code ... */
private DateFormat dateFormat = new SimpleDateFormat(DEFAULT_DATE_PATTERN);
{
    dateFormat.setLenient(false);
}

/* ... some other code ... */

@Override
public Date readDate(int index, String pattern) {
    SimpleDateFormat sdf = new SimpleDateFormat(pattern);
    sdf.setLenient(false);
    return parseDate(readAndTrim(index), sdf);
}
/* ... some other code ... */

As we are not doing any manipulation with dates in our code, I simply fixed it with changing default timezone to UTC.

TimeZone.setDefault(TimeZone.getTimeZone("UTC"));

Other valid approach would be to write custom implementation of FieldSet.

Community
  • 1
  • 1
Majky
  • 1,943
  • 1
  • 18
  • 30