3

I'm running a code that uses Gson Converter with simple date format function and once in a while the date formatting is messes up either it's displaying date back in 1969-1970 depending on time zone or it takes it and displays some random date.

static class DateSerializer implements JsonDeserializer<Date> {
    @Override
    public Date deserialize(JsonElement jsonElement, Type typeOF, JsonDeserializationContext context)
            throws JsonParseException {
        for (SimpleDateFormat simpleDateFormat : DATE_FORMATS) {
            try {
                simpleDateFormat.setLenient(true);

                return simpleDateFormat.parse(jsonElement.getAsString());
            } catch (ParseException e) {
            }
        }
        return null;
    }
}
static {
    final TimeZone GMT_TIMEZONE = TimeZone.getTimeZone("GMT");
    int i = 0;
    for (String format : DATE_FORMAT_STRINGS) {
        SimpleDateFormat dateFormat = new SimpleDateFormat(format, Locale.US);
        dateFormat.setTimeZone(GMT_TIMEZONE);
        DATE_FORMATS[i++] = dateFormat;
    }
}
Gson gson = new GsonBuilder()
            .registerTypeAdapter(Date.class, new DateSerializer())
            .create();
private static final String[] DATE_FORMAT_STRINGS = new String[]{"yyyy-MM-dd'T'HH:mm:ssZZZZ",
                                                                 "yyyy-MM-dd'T'HH:mm:ss'Z'"};
Bryan Herbst
  • 62,910
  • 10
  • 119
  • 113

2 Answers2

4

The problem is that SimpleDateFormat is not thread-safe. Your deserialization is happening across multiple threads to improve performance, but due to the non-thread-safety of SimpleDateFormat, you occasionally will get garbage back in your parsed dates.

Two options for solving this problem are creating a new SimpleDateFormat each time you need it, or enforcing atomicity by doing something such as creating a lock on your date format.

For example, GSON's DefaultDateTypeAdapter takes the latter approach.

Community
  • 1
  • 1
Bryan Herbst
  • 62,910
  • 10
  • 119
  • 113
  • with dateFormat how do i make it take certain format? "yyyy-MM-dd'T'HH:mm:ssZZZZ" – Andrei Chernyshev Jul 10 '15 at 15:56
  • You don't need to use `DateFormat`- I would just keep using `SimpleDateFormat`. `SimpleDateFormat` is a subclass of `DateFormat` anyway. – Bryan Herbst Jul 10 '15 at 15:57
  • This is the correct answer. I just experienced the same random dates problem myself and tracked it down to this issue. Another workaround is to create an instance of the SimpleDateFormat for each thread - as suggested here http://stackoverflow.com/a/817926/1666063 – Espen Riskedal Jan 04 '16 at 21:59
0

The setLenient probably causes it to parse dates in a weird way, depending on the exact format. It's probably better to be more strict with the formats you accept and keep setLenient to false.

Christiaan
  • 2,377
  • 18
  • 25