class DateTimeDetector {

    public OffsetDateTime detectDateTime(String text) {
        if (text == null || text.length() < MIN_DATE_TIME_STR_LENGTH) {
            return null;
        }

        // \p{Z} or \p{Separator}: any kind of whitespace or invisible separator.
        text = text.replaceAll("\\p{Zs}", " ").trim();
        // text = text.replaceAll("\\s+", " ").trim();

        // May be automatically generated date time
        final String finalText = text;
        if (Stream.of(BAD_DATE_TIME_STRING_CONTAINS).anyMatch(finalText::contains)) {
            return null;
        }

        final int dateTimeStart = StringUtils.indexOfAny(text, VALID_WORK_YEARS_ARRAY);
        if (dateTimeStart == StringUtils.INDEX_NOT_FOUND) {
            return null;
        }
        // For example : "2017-12-20 11:18:35"
        final int dateEnd = StringUtils.indexOf(text, " ", dateTimeStart);
        if (dateEnd < 0) {
            // TODO : try getTextDocument date
        }

        // Find the datetime string's end
        final int timeStart = dateEnd + 1;
        int pos = timeStart;
        for (; pos < text.length(); ++pos) {
            Character ch = text.charAt(pos);
            if (!Character.isDigit(ch) && ch != ':') {
                break;
            }
        }
        final int dateTimeEnd = pos;

        String possibleDate = StringUtils.substring(text, dateTimeStart, dateTimeEnd);

        // try getTextDocument datetime
        OffsetDateTime dateTime = null;
        if (possibleDate.length() >= MIN_DATE_TIME_STR_LENGTH) {
            dateTime = parseDateTimeStrictly(possibleDate);
        }

        return dateTime;
    }

    public  DateTimeDetector();
    public  DateTimeDetector(String[] dateFormats, String[] dateTimeFormats);

}