Разбор любой даты в Java

Я знаю, что этот вопрос задан совсем немного, и, очевидно, вы не можете разобрать какую-либо произвольную дату. Тем не менее, я нахожу, что библиотека python-dateutil может анализировать каждую дату, которую я бросаю на нее, при этом требуя абсолютно нулевого усилия при вычислении строки формата даты. Время в Joda всегда продается как отличный синтаксический анализатор дат, но по-прежнему требуется, чтобы вы определили, в каком формате находится ваша дата, прежде чем выбрать формат (или создать свой собственный). Вы не можете просто вызвать DateFormatter.parse(mydate) и волшебным образом вернуть объект Date.

Например, дата "Wed Mar 04 05:09:06 GMT-06: 00 2009" правильно разобрана с python-dateutil:

import dateutil.parser
print dateutil.parser.parse('Wed Mar 04 05:09:06 GMT-06:00 2009')

но следующий часовой вызов Joda не работает:

    String date = "Wed Mar 04 05:09:06 GMT-06:00 2009";
    DateTimeFormatter fmt = ISODateTimeFormat.dateTime();
    DateTime dt = fmt.parseDateTime(date);
    System.out.println(date);

И создание собственного DateTimeFormatter приводит к поражению цели, поскольку это похоже на использование SimpleDateFormatter с правильной строкой формата.

Есть ли сопоставимый способ для синтаксического анализа даты на Java, например python-dateutil? Меня не волнуют ошибки, я просто хочу, чтобы это было в основном совершенным.

Ответ 1

Лучше всего попросить помочь регулярному выражению, чтобы он соответствовал шаблону формата даты и/или для принудительного форматирования.

Несколько лет назад я написал немного глупый DateUtil класс, который выполнял эту работу. Здесь выдержка релевантности:

private static final Map<String, String> DATE_FORMAT_REGEXPS = new HashMap<String, String>() {{
    put("^\\d{8}$", "yyyyMMdd");
    put("^\\d{1,2}-\\d{1,2}-\\d{4}$", "dd-MM-yyyy");
    put("^\\d{4}-\\d{1,2}-\\d{1,2}$", "yyyy-MM-dd");
    put("^\\d{1,2}/\\d{1,2}/\\d{4}$", "MM/dd/yyyy");
    put("^\\d{4}/\\d{1,2}/\\d{1,2}$", "yyyy/MM/dd");
    put("^\\d{1,2}\\s[a-z]{3}\\s\\d{4}$", "dd MMM yyyy");
    put("^\\d{1,2}\\s[a-z]{4,}\\s\\d{4}$", "dd MMMM yyyy");
    put("^\\d{12}$", "yyyyMMddHHmm");
    put("^\\d{8}\\s\\d{4}$", "yyyyMMdd HHmm");
    put("^\\d{1,2}-\\d{1,2}-\\d{4}\\s\\d{1,2}:\\d{2}$", "dd-MM-yyyy HH:mm");
    put("^\\d{4}-\\d{1,2}-\\d{1,2}\\s\\d{1,2}:\\d{2}$", "yyyy-MM-dd HH:mm");
    put("^\\d{1,2}/\\d{1,2}/\\d{4}\\s\\d{1,2}:\\d{2}$", "MM/dd/yyyy HH:mm");
    put("^\\d{4}/\\d{1,2}/\\d{1,2}\\s\\d{1,2}:\\d{2}$", "yyyy/MM/dd HH:mm");
    put("^\\d{1,2}\\s[a-z]{3}\\s\\d{4}\\s\\d{1,2}:\\d{2}$", "dd MMM yyyy HH:mm");
    put("^\\d{1,2}\\s[a-z]{4,}\\s\\d{4}\\s\\d{1,2}:\\d{2}$", "dd MMMM yyyy HH:mm");
    put("^\\d{14}$", "yyyyMMddHHmmss");
    put("^\\d{8}\\s\\d{6}$", "yyyyMMdd HHmmss");
    put("^\\d{1,2}-\\d{1,2}-\\d{4}\\s\\d{1,2}:\\d{2}:\\d{2}$", "dd-MM-yyyy HH:mm:ss");
    put("^\\d{4}-\\d{1,2}-\\d{1,2}\\s\\d{1,2}:\\d{2}:\\d{2}$", "yyyy-MM-dd HH:mm:ss");
    put("^\\d{1,2}/\\d{1,2}/\\d{4}\\s\\d{1,2}:\\d{2}:\\d{2}$", "MM/dd/yyyy HH:mm:ss");
    put("^\\d{4}/\\d{1,2}/\\d{1,2}\\s\\d{1,2}:\\d{2}:\\d{2}$", "yyyy/MM/dd HH:mm:ss");
    put("^\\d{1,2}\\s[a-z]{3}\\s\\d{4}\\s\\d{1,2}:\\d{2}:\\d{2}$", "dd MMM yyyy HH:mm:ss");
    put("^\\d{1,2}\\s[a-z]{4,}\\s\\d{4}\\s\\d{1,2}:\\d{2}:\\d{2}$", "dd MMMM yyyy HH:mm:ss");
}};

/**
 * Determine SimpleDateFormat pattern matching with the given date string. Returns null if
 * format is unknown. You can simply extend DateUtil with more formats if needed.
 * @param dateString The date string to determine the SimpleDateFormat pattern for.
 * @return The matching SimpleDateFormat pattern, or null if format is unknown.
 * @see SimpleDateFormat
 */
public static String determineDateFormat(String dateString) {
    for (String regexp : DATE_FORMAT_REGEXPS.keySet()) {
        if (dateString.toLowerCase().matches(regexp)) {
            return DATE_FORMAT_REGEXPS.get(regexp);
        }
    }
    return null; // Unknown format.
}

(кашель, инициализация двойной скобки, кашель, это было просто для того, чтобы все это соответствовало 100 char max length;))

Вы можете легко развернуть его с помощью новых шаблонов regex и dateformat.

Ответ 2

Есть хорошая библиотека под названием Natty, которая, как мне кажется, подходит для ваших целей:

Natty - это парсер с естественным языком, написанный на Java. Учитывая дату выражение, natty будет применять стандартное распознавание языка и перевод методы для составления списка соответствующих дат с необязательным анализом и информация о синтаксисе.

Вы также можете попробовать в Интернете!

Ответ 3

То, что я видел, это класс Date util, который содержит несколько типичных форматов даты. Таким образом, когда вызывается DateUtil.parse(date), он пытается проанализировать дату с каждым форматом даты внутри и выдает только исключения, если ни один из внутренних форматов не может ее проанализировать.

Это в основном подход грубой силы к вашей проблеме.