Разобрать любую дату на Java

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

Например, дата "ср. 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? Меня не волнуют ошибки, я просто хочу, чтобы они были в основном идеальными.

3 ответа

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

Несколько лет назад я написал немного глупо 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 символов;))

Вы можете легко расширить его самостоятельно с помощью новых шаблонов регулярных выражений и форматов даты.

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

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

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

Вы можете попробовать dateparser.

Он может автоматически распознавать любую строку и правильно и быстро анализировать ее на Date, Calendar, LocalDateTime, OffsetDateTime (1us~1.5us).

Он не основан ни на каких natural language analyzer или SimpleDateFormat или regex.Pattern.

С его помощью вам не нужно готовить какие-либо подходящие шаблоны, такие как yyyy-MM-dd'T'HH:mm:ss.SSSZ или yyyy-MM-dd'T'HH:mm:ss.SSSZZ:

Date date = DateParserUtils.parseDate("2015-04-29T10:15:00.500+0000");
Calendar calendar = DateParserUtils.parseCalendar("2015-04-29T10:15:00.500Z");
LocalDateTime dateTime = DateParserUtils.parseDateTime("2015-04-29 10:15:00.500 +00:00");

Все работает нормально, наслаждайтесь.

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

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

//download library:   org.ocpsoft.prettytime.nlp.PrettyTimeParser
String str = "2020.03.03";
Date date = new PrettyTimeParser().parseSyntax(str).get(0).getDates().get(0);
System.out.println(date)

Я понятия не имею об этом разборе, как это сделать в Python. В java мы можем сделать вот так

SimpleDateFormat sdf1 = new SimpleDateFormat("dd-MM-yyyy");
  java.util.Date normalDate = null;
  java.sql.Date sqlDate = null;
  normalDate = sdf1.parse(date);
  sqlDate = new java.sql.Date(normalDate.getTime());
  System.out.println(sqlDate);

Я думаю, что, как и java, некоторые предопределенные функции будут в python. Вы можете следовать этому методу. Эти методы анализируют String date на Sql Date (dd-MM-yyyy);

import java.text.SimpleDateFormat;
import java.text.ParseException;
public class HelloWorld{
     public static void main(String []args){
        String date ="26-12-2019";
         SimpleDateFormat sdf1 = new SimpleDateFormat("dd-MM-yyyy");
        java.util.Date normalDate = null;
        java.sql.Date sqlDate = null;
        if( !date.isEmpty()) {
            try {
                normalDate = sdf1.parse(date);
                sqlDate = new java.sql.Date(normalDate.getTime());
                System.out.println(sqlDate);
            } catch (ParseException e) {
            }
        }
     }
} 

выполнить это!

Другие вопросы по тегам