Разобрать строку даты для некоторого объекта Java - PullRequest
30 голосов
/ 13 января 2012

Я работаю в проекте, который читает файлы и обрабатывает данные. Там я начал работать с датами, например:

  1. 2012-01-10 23: 13: 26
  2. 13 января 2012 г.

Я нашел пакет Joda, довольно интересный пакет, но я не знаю, самый ли это легкий.

Мне удалось разобрать первый пример с объектом DateTime (Joda) reg-ex и манипулированием String. (Например: заменив пробел на '-' и передав его конструктору.

new DateTime("2012-01-10 23:13:26".replace(' ', '-'))

Полагаю, это сработало, но проблема во втором формате. Как я могу использовать такой вход для извлечения объекта, предпочтительно объекта Joda. Я уверен, что могу написать функцию, чтобы изменить формат на тот, который поддерживает Joda, но мне было интересно, есть ли другой способ (даже некоторая нативная библиотека Java) сделать это.

Если есть что-то лучше, чем Йода, пожалуйста, дайте мне знать об этом.

Спасибо.

Ответы [ 6 ]

39 голосов
/ 13 января 2012

Используя Joda-Time, взгляните на DateTimeFormat ;это позволяет анализировать оба вида строк даты, которые вы упоминаете (и почти любые другие произвольные форматы).Если ваши потребности еще сложнее, попробуйте DateTimeFormatterBuilder .

Для разбора №1:

DateTimeFormatter f = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");
DateTime dateTime = f.parseDateTime("2012-01-10 23:13:26");

Редактировать: на самом деле LocalDateTime является болееподходящий тип для даты и времени без часового пояса:

LocalDateTime dateTime = f.parseLocalDateTime("2012-01-10 23:13:26");

И для # 2:

DateTimeFormatter f = DateTimeFormat.forPattern("MMMM dd, yyyy");
LocalDate localDate = f.parseLocalDate("January 13, 2012");

И да, Joda-Time определенно является подходом, насколько Javaдата и время обработки.:)

Как большинство согласится, Joda - это исключительно удобная библиотека.Например, я никогда раньше не проводил такого анализа с Joda, но мне потребовалось всего несколько минут, чтобы выяснить это из API и написать его.

Обновление (2015)

Если вы используете Java 8 , в большинстве случаев вам следует просто использовать java.time вместо Joda-Время.Он содержит почти все хорошие вещи - или их эквиваленты - от Joda.Для тех, кто уже знаком с API-интерфейсами Joda, пригодится руководство по миграции Стефана Колебурна * Joda-Time на java.time .

Вот java.time-версии приведенных выше примеров.

Для анализа # 1:

DateTimeFormatter f = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime dateTime = LocalDateTime.from(f.parse("2012-01-10 23:13:26"));

Вы не можете разобрать это в ZonedDateTime или OffsetDateTime (которые являются аналогами DateTime Joda, использованного в моем первоначальном ответе), но это имеет смысл, потому что в информации о часовых поясах нетанализируемая строка.

Для анализа # 2:

DateTimeFormatter f = DateTimeFormatter.ofPattern("MMMM dd, yyyy");
LocalDate localDate = LocalDate.from(f.parse("January 13, 2012"));

Здесь LocalDate является наиболее подходящим типом для анализа (как и в Joda-Time).

23 голосов
/ 13 января 2012

SimpleDateFormat будет анализировать даты в объектах Java Date:

http://docs.oracle.com/javase/1.4.2/docs/api/java/text/SimpleDateFormat.html

SimpleDateFormat format1 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); // first example
SimpleDateFormat format2 = new SimpleDateFormat("MMMMM dd,yyyy"); // second example

Date d1 = format1.parse( dateStr1 );
Date d2 = format2.parse( dateStr2 );
7 голосов
/ 13 января 2012

Я бы подумал, что у Йоды есть что-то от Formatter, чтобы сделать это для вас.Я нашел это с помощью быстрого поиска в Google: http://johannburkard.de/blog/programming/java/date-time-parsing-formatting-joda-time.html

DateTimeFormatter parser1 =
    DateTimeFormat.forPattern("dd/MMM/yyyy:HH:mm:ss Z");

DateTimeFormatter parser2 =
    DateTimeFormat.forPattern("yyyy-MM-dd HH:mm");

DateTime time = parser1.parseDateTime("<data>");

Синтаксис, используемый для оценки шаблонов, можно найти в ссылке X-Zero .

4 голосов
/ 13 января 2012

JodaTime в значительной степени считается стандартом де-факто для обработки даты и времени в Java - они работают над тем, чтобы добавить его в следующую версию библиотеки Java (ну, эффективно).

Для получения дат JodaTime из строк вам нужно изучить класс DateTimeFormat .

2 голосов
/ 13 января 2012

Самым простым было бы правильно настроить SimpleDateFormat в соответствии с ожидаемым форматом и использовать его метод синтаксического анализа, чтобы получить объект Date

1 голос
/ 17 июля 2016

tl; dr

LocalDateTime ldt = LocalDateTime.parse( "2012-01-10 23:13:26".replace( " " , "T" ) );

… и…

LocalDate localDate = LocalDate.parse ( "January 13, 2012" , DateTimeFormatter.ofLocalizedDate ( FormatStyle.LONG ).withLocale ( Locale.US ) );

Подробности

Ответ от Jonik в основном правильный, но пропускает некоторыеважные вопросы.

java.time

Если есть что-то лучше, чем Йода, пожалуйста, дайте мне знать об этом.

ДаЕсть кое-что получше, фреймворк java.time .Команда Joda-Time рекомендует перейти на java.time в качестве преемника.

Инфраструктура java.time встроена в Java 8 и более поздние версии.Эти классы вытесняют старые проблемные классы даты и времени, такие как java.util.Date, .Calendar, & java.text.SimpleDateFormat.

Чтобы узнать больше, см. Oracle Tutorial .И найдите в Stack Overflow множество примеров и объяснений.

Большая часть функциональности java.time перенесена в Java 6 & 7 в ThreeTen-Backport и дополнительно адаптирована для Android в ThreeTenABP .

Дата-время

Ваш первый ввод - это дата плюс время суток.В нем отсутствует какая-либо смещение от UTC или информация о часовом поясе , поэтому мы анализируем ее как объект LocalDateTime.«Местный…» означает любой населенный пункт, без определенного населенного пункта.Так что это не фактический момент времени, а скорее грубая идея о моменте.

Для анализа входной строки 2012-01-10 23:13:26 мы можем заменить ПРОБЕЛ в середине на T, чтобы соответствовать каноническому стилю для ISO 8601 стандартного формата значений даты и времени,

Классы java.time по умолчанию используют форматы ISO 8601 при анализе и генерации текстовых представлений значений даты и времени.Поэтому нет необходимости определять шаблон разбора.

String input = "2012-01-10 23:13:26".replace( " " , "T" );
LocalDateTime ldt = LocalDateTime.parse( input );

Если вы знаете предполагаемый часовой пояс из контекста этого значения, примените его для определения фактического момента на временной шкале.

ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ldt.atZone( zoneId );

Дамп на консоль.

System.out.println ( "input: " + input + " | zdt: " + zdt );

Ввод: 2012-01-10T23: 13: 26 |zdt: 2012-01-10T23: 13: 26-05: 00 [Америка / Монреаль]

Только дата

Второй из вводимых вами данных - это значение только для даты безвремя суток и без часового пояса.Для этого нам нужен класс LocalDate.

Я признаю формат этого ввода как соответствующий языковым (английским) и культурным нормам Соединенных Штатов.Поэтому нет необходимости явно указывать шаблон форматирования.Мы можем просто запросить форматировщик, который знает этот формат США, указав Locale.Мы указываем FormatStyle.LONG в зависимости от длины этого формата.

String input = "January 13, 2012";
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDate ( FormatStyle.LONG ).withLocale ( Locale.US );
LocalDate localDate = LocalDate.parse ( input , formatter );

Дамп на консоль.

System.out.println ( "input: " + input + " | localDate: " + localDate );

ввод: 13 января,2012 |localDate: 2012-01-13

...