Преобразовать строку в объект календаря в 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();

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


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;
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.