Преобразовать строку в объект календаря в Java

175

Я новичок в Java, обычно работаю с PHP.

Я пытаюсь преобразовать эту строку:

Пн мар 14 16:02:37 GMT 2011

В объект календаря, чтобы я мог легко вывести год и месяц следующим образом:

String yearAndMonth = cal.get(Calendar.YEAR)+cal.get(Calendar.MONTH);

Было бы плохой идеей разобрать его вручную? Используете метод подстроки?

Любой совет поможет, спасибо!

Дуг Молинье
источник

Ответы:

397
Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", Locale.ENGLISH);
cal.setTime(sdf.parse("Mon Mar 14 16:02:37 GMT 2011"));// all done

примечание: установить в Localeсоответствии с вашей средой / требованиями


Смотрите также

Джигар Джоши
источник
onlineconversion.com/unix_time.htm . Это онлайн конвертер меток времени. Значение, которое рассчитывается с помощью кода Java, и этот онлайн-конверт получает разные. Зачем?? Можете ли вы пройти через это. Спасибо :)
Sachin J
6
Обратите внимание, что это теряет информацию о часовом поясе. Объект Calendar будет иметь системную TimeZone по умолчанию, а не проанализированную.
Кристиан Враби
Это не должно быть топ / принятый ответ больше. Поскольку Java 8 уже более 4 лет, ответ должен быть обновлен java.time. Этот Q / A довольно заметен в Google.
Сколит
18

ТЛ; др

Современный подход использует классы java.time .

YearMonth.from(
    ZonedDateTime.parse( 
        "Mon Mar 14 16:02:37 GMT 2011" , 
        DateTimeFormatter.ofPattern( "E MMM d HH:mm:ss z uuuu" )
     )
).toString()

2011-03

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

Современный способ - с классами java.time. Старые классы даты и времени, такие как Calendarплохо продуманные, запутанные и хлопотные.

Определите пользовательский форматер, чтобы соответствовать вашему вводу строки.

String input = "Mon Mar 14 16:02:37 GMT 2011";
DateTimeFormatter f = DateTimeFormatter.ofPattern( "E MMM d HH:mm:ss z uuuu" );

Разобрать как ZonedDateTime.

ZonedDateTime zdt = ZonedDateTime.parse( input , f );

Вы заинтересованы в году и месяце. Классы java.time включают YearMonthкласс для этой цели.

YearMonth ym = YearMonth.from( zdt );

При необходимости вы можете опросить номера года и месяца.

int year = ym.getYear();
int month = ym.getMonthValue();

Но toStringметод генерирует строку в стандартном формате ISO 8601 .

String output = ym.toString();

Положите все это вместе.

String input = "Mon Mar 14 16:02:37 GMT 2011";
DateTimeFormatter f = DateTimeFormatter.ofPattern( "E MMM d HH:mm:ss z uuuu" );
ZonedDateTime zdt = ZonedDateTime.parse( input , f );
YearMonth ym = YearMonth.from( zdt );
int year = ym.getYear();
int month = ym.getMonthValue();

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

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

вход: пн мар 14 16:02:37 GMT 2011

zdt: 2011-03-14T16: 02: 37Z [GMT]

ym: 2011-03

Живой код

Посмотрите, как работает этот код на IdeOne.com .

преобразование

Если у вас должен быть Calendarобъект, вы можете преобразовать его, GregorianCalendarиспользуя новые методы, добавленные к старым классам.

GregorianCalendar gc = GregorianCalendar.from( zdt );

О java.time

Java.time каркас встроен в Java 8 и более поздних версий. Эти классы вытеснять неприятные старые устаревшие классы даты и времени , такие как java.util.Date, Calendar, и SimpleDateFormat.

Проект Joda-Time , находящийся сейчас в режиме обслуживания , рекомендует перейти на java.time.

Чтобы узнать больше, смотрите Oracle Tutorial . И поиск переполнения стека для многих примеров и объяснений. Спецификация JSR 310 .

Где взять классы java.time?

  • Java SE 8 и SE 9 и позже
    • Встроенный.
    • Часть стандартного Java API со встроенной реализацией.
    • Java 9 добавляет некоторые незначительные функции и исправления.
  • Java SE 6 и SE 7
    • Большая часть функциональности java.time перенесена на Java 6 и 7 в ThreeTen-Backport .
  • Android

Проект ThreeTen-Extra расширяет java.time дополнительными классами. Этот проект является полигоном для возможных будущих дополнений к java.time. Вы можете найти некоторые полезные классы здесь , такие как Interval, YearWeek, YearQuarter, и более .

Базилик Бурк
источник
14

Ну, я думаю, что было бы плохой идеей копировать код, который уже присутствует в таких классах, как SimpleDateFormat.

С другой стороны, лично я бы посоветовал избегать Calendarи Dateполностью, если вы можете, и использовать вместо этого Joda Time , как гораздо лучше разработанный API даты и времени. Например, вы должны знать, что SimpleDateFormatэто не потокобезопасно, поэтому вам понадобятся локальные потоки, синхронизация или новый экземпляр каждый раз, когда вы его используете. Парсеры и форматеры Joda являются поточно- ориентированными .

Джон Скит
источник
Спасибо за ваш вклад, я непременно буду изучать использование Joda в будущем, похоже, это может быть очень полезно
Doug Molineux
@Jon Skeet Joda не будет десериализоваться в Android. Джода ничего не стоит, если у вас нет необходимости сохранять даты и время.
Фрэнк Заппа
@FrankZappa: Я бы не согласился с этим - вы можете выполнять все свои вычисления даты / времени в Joda Time, но затем конвертировать в другие типы (возможно, просто строки для простоты) для целей сериализации.
Джон Скит
Извините, пришлось понизить голос, ответ слишком старый, он устарел, чтобы быть самым высоким ответом. Сегодня java.timeпуть вперед, Василий Бурк дал отличный ответ.
Сколит
2
@Scolytus: лучший (и принятый) ответ имеет 332 голоса по сравнению с 10 на этом. Я думаю, что если вы пойдете против каждого 7+ -летнего ответа, у которого есть лучшее решение, у вас закончатся отрицательные ответы ... (Я согласен, что ответ Василия хорош, и я проголосовал за это.)
Джон Скит
10

Не нужно создавать новый календарь, SimpleDateFormat уже использует календарь внизу.

SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", Locale.EN_US);
Date date = sdf.parse("Mon Mar 14 16:02:37 GMT 2011"));// all done
Calendar cal = sdf.getCalendar();

(Я пока не могу комментировать, поэтому я создал новый ответ)

GoGoris
источник
1
Ваше решение выглядит элегантно, но имеет два недостатка: 1. JavaDoc не гарантирует, что поведение будет таким, как ожидалось. 2. По крайней мере для Java 6 вы найдете путь в строке 1353, где клонированный объект календаря. Итак, тогда! Date.equals (cal.getTime ()).
Нильс
5

SimpleDateFormatотлично, просто обратите внимание, что HHотличается от hhработы с часами. HHвернет 24-часовые часы, а чч вернет 12-часовые часы.

Например, следующее вернет 12-часовое время:

SimpleDateFormat sdf = new SimpleDateFormat("hh:mm aa");

Пока это вернется через 24 часа:

SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
Филипп
источник
4

Разобрать время с Zчасовым поясом , в шаблоне для часового пояса

String aTime = "2017-10-25T11:39:00+09:00";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.getDefault());
try {
    Calendar cal = Calendar.getInstance();
    cal.setTime(sdf.parse(aTime));
    Log.i(TAG, "time = " + cal.getTimeInMillis()); 
} catch (ParseException e) {
    e.printStackTrace();
}

Вывод: вернет время UTC

1508899140000

введите описание изображения здесь

Если мы не устанавливаем часовой пояс в шаблоне, как yyyy-MM-dd'T'HH:mm:ss. SimpleDateFormatбудет использовать часовой пояс, который установлен вSetting

Фан Ван Линь
источник
3

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

Джон Винт
источник
1

Простой метод:

public Calendar stringToCalendar(String date, String pattern) throws ParseException {
    String DEFAULT_LOCALE_NAME = "pt";
    String DEFAULT_COUNTRY = "BR";
    Locale DEFAULT_LOCALE = new Locale(DEFAULT_LOCALE_NAME, DEFAULT_COUNTRY);
    SimpleDateFormat format = new SimpleDateFormat(pattern, LocaleUtils.DEFAULT_LOCALE);
    Date d = format.parse(date);
    Calendar c = getCalendar();
    c.setTime(d);
    return c;
}
Альберто Черкейра
источник