Анализ любой даты в Java
Я знаю, что этот вопрос задают довольно часто, и, очевидно, вы не можете проанализировать любую произвольную дату. Однако я обнаружил, что библиотека python-dateutil способна анализировать каждую дату, которую я в нее добавляю, при этом не требуя абсолютно никаких усилий для определения строки формата даты. Joda time всегда продавался как отличный 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 time не работает:
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 символов максимальной длины ;))
Вы можете легко расширить ее самостоятельно с помощью новых шаблонов регулярных выражений и dateformat.
Ответ 2
Есть хорошая библиотека под названием Natty, которая, я думаю, подходит для ваших целей:
Natty - это анализатор даты на естественном языке, написанный на Java. Получив выражение даты, natty применит стандартные методы распознавания языка и перевода для создания списка соответствующих дат с дополнительной информацией о синтаксическом анализе.
Вы также можете попробовать это онлайн!
Ответ 3
Вы могли бы попробовать dateparser.
Он может автоматически распознавать любую строку и корректно и быстро преобразовывать ее в Дату, Календарь, 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");
Все работает нормально, пожалуйста, наслаждайтесь.
Ответ 4
То, что я видел, сделано с помощью класса Date util, который содержит несколько типичных форматов дат. Итак, когда вызывается DateUtil.parse(date) , он пытается проанализировать дату с каждым внутренним форматом даты и выдает исключения только в том случае, если ни один из внутренних форматов не может ее проанализировать.
По сути, это подход грубой силы к вашей проблеме.