Використання Joda Date & Time API для синтаксичного аналізу декількох форматів


76

Я аналізую файли журналів сторонніх розробників, що містять дату / час, за допомогою 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);
}

Це працює, але суперечить порадам Джошуа Блоха від Effective Java 2nd Edition (Пункт 57: Використовувати винятки лише у виняткових умовах). Крім того, важко визначити, чи виникає IllegalArgumentException через викривлену дату / час у файлі журналу.

Чи можете ви запропонувати більш приємний підхід, який не зловживає винятками?


Можливо, відгадавши шаблон перед його використанням.
sly7_7

Відповіді:


147

Ви можете створити кілька аналізаторів і додати їх до конструктора, використовуючи метод 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 це мав на увазі, але коли я спробував зробити щось за його вказівками, синтаксичний розбір не вдався.
Steve McLeod

2
Це не працює, наприклад, "5-5-5" та "5-5-2005", якщо ви хочете як dd-MM-yy, так і dd-MM-yyyy (не вдалося проаналізувати виняток). Пізніше я дізнався, що dd-MM-yy також аналізує dd-MM-yyyy просто чудово, так що це вирішило мою проблему.
Стівен

1
Дивно, але, незважаючи на різноманітність appendперевантажень, це єдине, що не створює винятків, якщо даються конфліктні формати.
shmosel

17

Joda-Time підтримує це, дозволяючи вказати декілька аналізаторів - DateTimeFormatterBuilder # append

Просто створіть свої два форматування за допомогою конструктора та зателефонуйте toParser()кожному. Потім використовуйте конструктор, щоб поєднати їх за допомогою append.


4
Вау! Відповів безпосередньо від самої людини! Любіть свою роботу Стівене.
Steve McLeod

3
Хм, я спробував це, але Joda-Time тоді, здається, очікує, що аналізований рядок буде відповідати шаблону, який складається І З шаблонів, що додаються разом, а не з одного АБО з іншого.
Steve McLeod

Можливо, форум є кращим місцем, щоб перевірити, чи це помилка - sourceforge.net/projects/joda-time/forums/forum/337835
JodaStephen

7

На жаль, я не вірю, що Joda Time має такі можливості. Було б непогано мати метод "tryParseDateTime", але він не існує.

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

Зауважте, що DateTimeFormatters у Joda Time звичайно незмінні - вам не слід створювати новий кожен раз, коли ви хочете проаналізувати рядок. Створіть їх один раз і використовуйте повторно.


Ця відповідь дає сенс моєму коментарю. Я дуже задоволений :) Я все ще новачок, тому не дав би відповіді
sly7_7

Дякую, Джон. Я знав про незмінність DateTimeFormatters, але для стислості в моєму прикладі коду явно їх створив. Немає нестерпних проблем із продуктивністю, тому я думаю, що я зроблю те, що ви запропонуєте, і створу клас, щоб приховати потворність.
Steve McLeod

Boo Java через відсутність функцій TryParse, таких як DotNet. Відсутність процедур tryParse та стирання загального типу - це два мої найбільші проблеми. docs.oracle.com/javase/tutorial/java/generics/erasure.html
granadaCoder
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.