class ObjectReaderImplDate
        extends DateTimeCodec
        implements ObjectReader {
    public static final ObjectReaderImplDate INSTANCE = new ObjectReaderImplDate(null, null);

    public static ObjectReaderImplDate of(String format, Locale locale) {
        if (format == null) {
            return INSTANCE;
        }
        return new ObjectReaderImplDate(format, locale);
    }

    public ObjectReaderImplDate(String format, Locale locale) {
        super(format, locale);
    }

    @Override
    public Class getObjectClass() {
        return Date.class;
    }

    @Override
    public Object readJSONBObject(JSONReader jsonReader, Type fieldType, Object fieldName, long features) {
        if (jsonReader.isInt()) {
            long millis = jsonReader.readInt64Value();
            if (formatUnixTime) {
                millis *= 1000;
            }
            return new Date(millis);
        }

        if (jsonReader.readIfNull()) {
            return null;
        }

        return readDate(jsonReader);
    }

    @Override
    public Object readObject(JSONReader jsonReader, Type fieldType, Object fieldName, long features) {
        if (jsonReader.isInt()) {
            long millis = jsonReader.readInt64Value();
            if (formatUnixTime) {
                millis *= 1000;
            }
            return new Date(millis);
        }

        if (jsonReader.readIfNull()) {
            return null;
        }

        return readDate(jsonReader);
    }

    private Object readDate(JSONReader jsonReader) {<FILL_FUNCTION_BODY>}
}

        long millis;
        if (useSimpleFormatter) {
            String str = jsonReader.readString();
            try {
                return new SimpleDateFormat(format).parse(str);
            } catch (ParseException e) {
                throw new JSONException(jsonReader.info("parse error : " + str), e);
            }
        }

        if (jsonReader.nextIfNullOrEmptyString()) {
            return null;
        }

        if ((formatUnixTime || formatMillis) && jsonReader.isString()) {
            millis = jsonReader.readInt64Value();
            if (formatUnixTime) {
                millis *= 1000L;
            }
        } else if (format != null) {
            ZonedDateTime zdt;
            if (yyyyMMddhhmmss19) {
                if (jsonReader.isSupportSmartMatch()) {
                    millis = jsonReader.readMillisFromString();
                } else {
                    millis = jsonReader.readMillis19();
                }
                if (millis != 0 || !jsonReader.wasNull()) {
                    return new Date(millis);
                }
                zdt = jsonReader.readZonedDateTime();
            } else {
                DateTimeFormatter formatter = getDateFormatter(jsonReader.getLocale());

                if (formatter != null) {
                    String str = jsonReader.readString();
                    if (str.isEmpty() || "null".equals(str)) {
                        return null;
                    }

                    LocalDateTime ldt;
                    if (!formatHasHour) {
                        if (!formatHasDay) {
                            TemporalAccessor parsed = formatter.parse(str);
                            int year = parsed.get(ChronoField.YEAR);
                            int month = parsed.get(ChronoField.MONTH_OF_YEAR);
                            int dayOfYear = 1;
                            ldt = LocalDateTime.of(
                                    LocalDate.of(year, month, dayOfYear),
                                    LocalTime.MIN
                            );
                        } else {
                            LocalDate localDate;
                            if (str.length() == 19 && jsonReader.isEnabled(JSONReader.Feature.SupportSmartMatch)) {
                                ldt = DateUtils.parseLocalDateTime(str, 0, str.length());
                            } else {
                                if (format.indexOf('-') != -1 && str.indexOf('-') == -1 && TypeUtils.isInteger(str)) {
                                    millis = Long.parseLong(str);
                                    return new Date(millis);
                                }

                                localDate = LocalDate.parse(str, formatter);
                                ldt = LocalDateTime.of(localDate, LocalTime.MIN);
                            }
                        }
                    } else {
                        if (str.length() == 19
                                && (yyyyMMddhhmm16
                                    || jsonReader.isEnabled(JSONReader.Feature.SupportSmartMatch)
                                    || "yyyy-MM-dd hh:mm:ss".equals(format))) {
                            int length = yyyyMMddhhmm16 ? 16 : 19;
                            ldt = DateUtils.parseLocalDateTime(str, 0, length);
                        } else {
                            ldt = LocalDateTime.parse(str, formatter);
                        }
                    }
                    zdt = ldt.atZone(jsonReader.getContext().getZoneId());
                } else {
                    zdt = jsonReader.readZonedDateTime();
                }
            }

            if (zdt == null) {
                return null;
            }

            long seconds = zdt.toEpochSecond();
            int nanos = zdt.toLocalTime().getNano();
            if (seconds < 0 && nanos > 0) {
                millis = (seconds + 1) * 1000;
                long adjustment = nanos / 1000_000 - 1000;
                millis += adjustment;
            } else {
                millis = seconds * 1000L;
                millis += nanos / 1000_000;
            }
        } else {
            if (jsonReader.isDate()) {
                return jsonReader.readDate();
            }

            if (jsonReader.isTypeRedirect() && jsonReader.nextIfMatchIdent('"', 'v', 'a', 'l', '"')) {
                jsonReader.nextIfMatch(':');
                millis = jsonReader.readInt64Value();
                jsonReader.nextIfObjectEnd();
                jsonReader.setTypeRedirect(false);
            } else {
                millis = jsonReader.readMillisFromString();
            }

            if (millis == 0 && jsonReader.wasNull()) {
                return null;
            }

            if (formatUnixTime) {
                millis *= 1000;
            }
        }

        return new Date(millis);
    
<methods>public void <init>(java.lang.String) ,public void <init>(java.lang.String, java.util.Locale) ,public java.time.format.DateTimeFormatter getDateFormatter() ,public java.time.format.DateTimeFormatter getDateFormatter(java.util.Locale) <variables>java.time.format.DateTimeFormatter dateFormatter,public final non-sealed java.lang.String format,protected final non-sealed boolean formatHasDay,protected final non-sealed boolean formatHasHour,public final non-sealed boolean formatISO8601,public final non-sealed boolean formatMillis,public final non-sealed boolean formatUnixTime,public final non-sealed java.util.Locale locale,protected final non-sealed boolean useSimpleDateFormat,public final non-sealed boolean useSimpleFormatter,protected final non-sealed boolean yyyyMMdd10,protected final non-sealed boolean yyyyMMdd8,protected final non-sealed boolean yyyyMMddhhmm16,protected final non-sealed boolean yyyyMMddhhmmss14,protected final non-sealed boolean yyyyMMddhhmmss19