package io.gitlab.jfronny.commons.serialize.databind.impl.adapter; import io.gitlab.jfronny.commons.serialize.databind.api.SerializerFor; import io.gitlab.jfronny.commons.serialize.databind.api.TypeAdapter; import io.gitlab.jfronny.commons.serialize.ISO8601Utils; import io.gitlab.jfronny.commons.serialize.databind.impl.PreJava9DateFormatProvider; import io.gitlab.jfronny.commons.serialize.MalformedDataException; import io.gitlab.jfronny.commons.serialize.SerializeReader; import io.gitlab.jfronny.commons.serialize.SerializeWriter; import java.text.DateFormat; import java.text.ParseException; import java.text.ParsePosition; import java.text.SimpleDateFormat; import java.util.*; @SerializerFor(targets = Date.class) public class DefaultDateTypeAdapter extends TypeAdapter { private static final String SIMPLE_NAME = "DefaultDateTypeAdapter"; /** * List of 1 or more different date formats used for de-serialization attempts. The first of them * is used for serialization as well. */ private final List dateFormats = new ArrayList<>(); public DefaultDateTypeAdapter() { dateFormats.add(DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.US)); if (!Locale.getDefault().equals(Locale.US)) { dateFormats.add(DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT)); } dateFormats.add(PreJava9DateFormatProvider.getUsDateTimeFormat(DateFormat.DEFAULT, DateFormat.DEFAULT)); } @Override public > void serialize(Date value, Writer writer) throws TEx, MalformedDataException { DateFormat dateFormat = dateFormats.getFirst(); String dateFormatAsString; // Needs to be synchronized since JDK DateFormat classes are not thread-safe synchronized (dateFormats) { dateFormatAsString = dateFormat.format(value); } writer.value(dateFormatAsString); } @Override public > Date deserialize(Reader reader) throws TEx, MalformedDataException { String s = reader.nextString(); // Needs to be synchronized since JDK DateFormat classes are not thread-safe synchronized (dateFormats) { for (DateFormat dateFormat : dateFormats) { TimeZone originalTimeZone = dateFormat.getTimeZone(); try { return dateFormat.parse(s); } catch (ParseException ignored) { // OK: try the next format } finally { dateFormat.setTimeZone(originalTimeZone); } } } try { return ISO8601Utils.parse(s, new ParsePosition(0)); } catch (ParseException e) { throw new MalformedDataException( "Failed parsing '" + s + "' as Date; at path " + reader.getPreviousPath(), e); } } @Override public String toString() { DateFormat defaultFormat = dateFormats.getFirst(); if (defaultFormat instanceof SimpleDateFormat) { return SIMPLE_NAME + '(' + ((SimpleDateFormat) defaultFormat).toPattern() + ')'; } else { return SIMPLE_NAME + '(' + defaultFormat.getClass().getSimpleName() + ')'; } } }