2010-07-22 2 views
67

Я разбираю файлы сторонних журналов, содержащие дату/время, используя Joda. Дата/время находится в одном из двух разных форматов, в зависимости от возраста файлов журнала, которые я обрабатываю.Использование API дат и времени Joda для анализа нескольких форматов

В настоящее время у меня есть такой код:

try { 
    return DateTimeFormat.forPattern("yyyy/MM/dd HH:mm:ss").parseDateTime(datePart); 
} catch (IllegalArgumentException e) { 
    return DateTimeFormat.forPattern("E, MMM dd, yyyy HH:mm").parseDateTime(datePart); 
} 

Это работает, но нарушающий совет Джошуа Блоха от эффективного Java 2nd Edition (Пункт 57: Используйте исключение только для исключительных условий). Это также затрудняет определение того, происходит ли исключение IllegalArgumentException из-за закрученной даты/времени в файле журнала.

Можете ли вы предложить более хороший подход, который не злоупотребляет исключениями?

+0

Пожалуй, угадав рисунок перед его использованием. –

ответ

126

Вы можете создать несколько парсеров и добавить их к строителю, используя DateTimeFormatterBuilder.append метод:

DateTimeParser[] parsers = { 
     DateTimeFormat.forPattern("yyyy-MM-dd HH").getParser(), 
     DateTimeFormat.forPattern("yyyy-MM-dd").getParser() }; 
DateTimeFormatter formatter = new DateTimeFormatterBuilder().append(null, parsers).toFormatter(); 

DateTime date1 = formatter.parseDateTime("2010-01-01"); 
DateTime date2 = formatter.parseDateTime("2010-01-01 01"); 
+1

Это работает отлично. Думаю, JodaStephen имел в виду это, но когда я пытался делать что-то в соответствии с его инструкциями, синтаксический анализ не удался. –

+1

Это не работает, например, для «5-5-5» и «5-5-2005», если вы хотите как dd-MM-yy, так и dd-MM-yyyy (не может разобрать исключение). Позже я узнал, что dd-MM-yy также отлично разбирает dd-MM-yyyy, так что решил мою проблему. – Steven

+0

Странно, несмотря на разнообразие перегрузок 'append', это единственный, который не генерирует исключение при заданных конфликтующих форматах. – shmosel

6

К сожалению, я не верю, что у Joda Time есть такие возможности. Было бы неплохо иметь метод tryParseDateTime, но он не существует.

Я предлагаю вам изолировать это поведение в своем классе (тот, который отображает список шаблонов и будет стараться каждый по очереди), чтобы уродство было только в одном месте. Если это вызывает проблемы с производительностью, вы можете попытаться использовать некоторые эвристики, чтобы угадать, какой формат попробовать в первую очередь. Например, в вашем случае, если строка начинается с цифры, это, вероятно, первый шаблон.

Обратите внимание, что DateTimeFormatter s в Joda Time традиционно неизменяемы - вы не должны создавать новый каждый раз, когда хотите разбор строки. Создайте их один раз и повторно используйте их.

+0

Этот ответ дает смысл моему комментарию. Я довольно доволен :) Я все еще новичок, поэтому я бы не дал его как ответ –

+0

Спасибо Jon. Я знал, что DateTimeFormatters являются неизменяемыми, но для краткости в моем примере кода они были явно созданы. Нет никаких невыносимых проблем с производительностью, поэтому я думаю, что сделаю то, что вы предлагаете, и создайте класс, чтобы скрыть уродство. –

16

Joda время поддерживает это, позволяя несколько парсеров быть указаны - DateTimeFormatterBuilder#append

Просто создать два форматтеров используя построитель и вызвать toParser() на каждом. Затем используйте построитель, чтобы объединить их, используя append.

+4

Whoa! Ответил прямо от самого человека! Любите свою работу Стефана. –

+2

Хм, я попробовал это, но Joda-Time, похоже, ожидает, что строка будет разобрана, чтобы соответствовать шаблону, который состоит из BOTH шаблонов, прилагаемых вместе, а не одного ИЛИ другого. –

+0

Возможно, форум - лучшее место, чтобы узнать, является ли это ошибкой - http://sourceforge.net/projects/joda-time/forums/forum/337835 – JodaStephen

Смежные вопросы