Преобразование строки Java в дату - PullRequest
822 голосов
/ 18 ноября 2010

Как лучше всего преобразовать String в формате '2 января 2010 г.' в Date в Java?

В конечном счете, я хочу выделить месяц, день и год как целые числа, чтобы я мог использовать

Date date = new Date();
date.setMonth()..
date.setYear()..
date.setDay()..
date.setlong currentTime = date.getTime();

для преобразования даты во время.

Ответы [ 13 ]

1557 голосов
/ 18 ноября 2010

Это трудный путь, и эти java.util.Date методы установки устарели с Java 1.1 (1997). Просто отформатируйте дату, используя SimpleDateFormat, используя шаблон формата, соответствующий входной строке .

В вашем конкретном случае «2 января 2010» в качестве входной строки:

  1. «Январь» - это полнотекстовый месяц, поэтому используйте для него шаблон MMMM
  2. «2» - короткий день месяца, поэтому используйте для него шаблон d.
  3. "2010" - это четырехзначный год, поэтому используйте для него шаблон yyyy.

String string = "January 2, 2010";
DateFormat format = new SimpleDateFormat("MMMM d, yyyy", Locale.ENGLISH);
Date date = format.parse(string);
System.out.println(date); // Sat Jan 02 00:00:00 GMT 2010

Обратите внимание на важность явного аргумента Locale. Если вы его опустите, он будет использовать локаль по умолчанию , которая не обязательно является английской, как используется в названии месяца входной строки. Если языковой стандарт не совпадает с входной строкой, вы получите путаницу java.text.ParseException, даже если шаблон формата кажется действительным.

Вот выдержка из javadoc , в которой перечислены все доступные шаблоны форматов:

Letter  Date or Time Component  Presentation        Examples
------  ----------------------  ------------------  -------------------------------------
G       Era designator          Text                AD
y       Year                    Year                1996; 96
Y       Week year               Year                2009; 09
M/L     Month in year           Month               July; Jul; 07
w       Week in year            Number              27
W       Week in month           Number              2
D       Day in year             Number              189
d       Day in month            Number              10
F       Day of week in month    Number              2
E       Day in week             Text                Tuesday; Tue
u       Day number of week      Number              1
a       Am/pm marker            Text                PM
H       Hour in day (0-23)      Number              0
k       Hour in day (1-24)      Number              24
K       Hour in am/pm (0-11)    Number              0
h       Hour in am/pm (1-12)    Number              12
m       Minute in hour          Number              30
s       Second in minute        Number              55
S       Millisecond             Number              978
z       Time zone               General time zone   Pacific Standard Time; PST; GMT-08:00
Z       Time zone               RFC 822 time zone   -0800
X       Time zone               ISO 8601 time zone  -08; -0800; -08:00

Обратите внимание, что шаблоны чувствительны к регистру и текстовые шаблоны из четырех и более символов представляют полную форму; в противном случае используется короткая или сокращенная форма, если таковая имеется. Так, например MMMMM или больше не требуется.

Вот несколько примеров допустимых SimpleDateFormat шаблонов для анализа заданной строки на сегодняшний день:

Input string                            Pattern
------------------------------------    ----------------------------
2001.07.04 AD at 12:08:56 PDT           yyyy.MM.dd G 'at' HH:mm:ss z
Wed, Jul 4, '01                         EEE, MMM d, ''yy
12:08 PM                                h:mm a
12 o'clock PM, Pacific Daylight Time    hh 'o''clock' a, zzzz
0:08 PM, PDT                            K:mm a, z
02001.July.04 AD 12:08 PM               yyyyy.MMMM.dd GGG hh:mm aaa
Wed, 4 Jul 2001 12:08:56 -0700          EEE, d MMM yyyy HH:mm:ss Z
010704120856-0700                       yyMMddHHmmssZ
2001-07-04T12:08:56.235-0700            yyyy-MM-dd'T'HH:mm:ss.SSSZ
2001-07-04T12:08:56.235-07:00           yyyy-MM-dd'T'HH:mm:ss.SSSXXX
2001-W27-3                              YYYY-'W'ww-u

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


Обновление Java 8

Если вы используете Java 8 или новее, используйте DateTimeFormatter (также здесь, нажмите на ссылку, чтобы увидеть все предопределенные форматеры и доступные шаблоны форматов; учебник доступен здесь ). Этот новый API основан на JodaTime .

String string = "January 2, 2010";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMMM d, yyyy", Locale.ENGLISH);
LocalDate date = LocalDate.parse(string, formatter);
System.out.println(date); // 2010-01-02

Примечание: если ваш шаблон формата также содержит часть времени, тогда используйте LocalDateTime#parse(text, formatter) вместо LocalDate#parse(text, formatter). И, если ваш шаблон формата также содержит часовой пояс, используйте вместо него ZonedDateTime#parse(text, formatter).

Вот выдержка из javadoc , в которой перечислены все доступные шаблоны форматов:

Symbol  Meaning                     Presentation  Examples
------  --------------------------  ------------  ----------------------------------------------
G       era                         text          AD; Anno Domini; A
u       year                        year          2004; 04
y       year-of-era                 year          2004; 04
D       day-of-year                 number        189
M/L     month-of-year               number/text   7; 07; Jul; July; J
d       day-of-month                number        10

Q/q     quarter-of-year             number/text   3; 03; Q3; 3rd quarter
Y       week-based-year             year          1996; 96
w       week-of-week-based-year     number        27
W       week-of-month               number        4
E       day-of-week                 text          Tue; Tuesday; T
e/c     localized day-of-week       number/text   2; 02; Tue; Tuesday; T
F       week-of-month               number        3

a       am-pm-of-day                text          PM
h       clock-hour-of-am-pm (1-12)  number        12
K       hour-of-am-pm (0-11)        number        0
k       clock-hour-of-am-pm (1-24)  number        0

H       hour-of-day (0-23)          number        0
m       minute-of-hour              number        30
s       second-of-minute            number        55
S       fraction-of-second          fraction      978
A       milli-of-day                number        1234
n       nano-of-second              number        987654321
N       nano-of-day                 number        1234000000

V       time-zone ID                zone-id       America/Los_Angeles; Z; -08:30
z       time-zone name              zone-name     Pacific Standard Time; PST
O       localized zone-offset       offset-O      GMT+8; GMT+08:00; UTC-08:00;
X       zone-offset 'Z' for zero    offset-X      Z; -08; -0830; -08:30; -083015; -08:30:15;
x       zone-offset                 offset-x      +0000; -08; -0830; -08:30; -083015; -08:30:15;
Z       zone-offset                 offset-Z      +0000; -0800; -08:00;

Обратите внимание, что у него есть несколько предопределенных форматеров для более популярных шаблонов. Так, например, вместо DateTimeFormatter.ofPattern("EEE, d MMM yyyy HH:mm:ss Z", Locale.ENGLISH);, вы можете использовать DateTimeFormatter.RFC_1123_DATE_TIME. Это возможно, потому что они, в отличие от SimpleDateFormat, безопасны для потоков. Таким образом, вы также можете определить свой собственный, если это необходимо.

Для определенного формата входной строки вам не нужно использовать явную DateTimeFormatter: стандартную ISO 8601 дату, например 2016-09-26T17: 44: 57Z, можно анализировать напрямую с LocalDateTime#parse(text), поскольку он уже использует форматер ISO_LOCAL_DATE_TIME. Аналогично, LocalDate#parse(text) анализирует дату ISO без компонента времени (см. ISO_LOCAL_DATE), а ZonedDateTime#parse(text) анализирует дату ISO со смещением и добавлен часовой пояс (см. ISO_ZONED_DATE_TIME).

69 голосов
/ 19 ноября 2010

Ах да, обсуждение Java Date, опять же. Для работы с датами мы используем Дата , Календарь , GregorianCalendar и SimpleDateFormat . Например, используя вашу дату в январе в качестве ввода:

Calendar mydate = new GregorianCalendar();
String mystring = "January 2, 2010";
Date thedate = new SimpleDateFormat("MMMM d, yyyy", Locale.ENGLISH).parse(mystring);
mydate.setTime(thedate);
//breakdown
System.out.println("mydate -> "+mydate);
System.out.println("year   -> "+mydate.get(Calendar.YEAR));
System.out.println("month  -> "+mydate.get(Calendar.MONTH));
System.out.println("dom    -> "+mydate.get(Calendar.DAY_OF_MONTH));
System.out.println("dow    -> "+mydate.get(Calendar.DAY_OF_WEEK));
System.out.println("hour   -> "+mydate.get(Calendar.HOUR));
System.out.println("minute -> "+mydate.get(Calendar.MINUTE));
System.out.println("second -> "+mydate.get(Calendar.SECOND));
System.out.println("milli  -> "+mydate.get(Calendar.MILLISECOND));
System.out.println("ampm   -> "+mydate.get(Calendar.AM_PM));
System.out.println("hod    -> "+mydate.get(Calendar.HOUR_OF_DAY));

Тогда вы можете манипулировать этим что-то вроде:

Calendar now = Calendar.getInstance();
mydate.set(Calendar.YEAR,2009);
mydate.set(Calendar.MONTH,Calendar.FEBRUARY);
mydate.set(Calendar.DAY_OF_MONTH,25);
mydate.set(Calendar.HOUR_OF_DAY,now.get(Calendar.HOUR_OF_DAY));
mydate.set(Calendar.MINUTE,now.get(Calendar.MINUTE));
mydate.set(Calendar.SECOND,now.get(Calendar.SECOND));
// or with one statement
//mydate.set(2009, Calendar.FEBRUARY, 25, now.get(Calendar.HOUR_OF_DAY), now.get(Calendar.MINUTE), now.get(Calendar.SECOND));
System.out.println("mydate -> "+mydate);
System.out.println("year   -> "+mydate.get(Calendar.YEAR));
System.out.println("month  -> "+mydate.get(Calendar.MONTH));
System.out.println("dom    -> "+mydate.get(Calendar.DAY_OF_MONTH));
System.out.println("dow    -> "+mydate.get(Calendar.DAY_OF_WEEK));
System.out.println("hour   -> "+mydate.get(Calendar.HOUR));
System.out.println("minute -> "+mydate.get(Calendar.MINUTE));
System.out.println("second -> "+mydate.get(Calendar.SECOND));
System.out.println("milli  -> "+mydate.get(Calendar.MILLISECOND));
System.out.println("ampm   -> "+mydate.get(Calendar.AM_PM));
System.out.println("hod    -> "+mydate.get(Calendar.HOUR_OF_DAY));
45 голосов
/ 15 января 2013
String str_date = "11-June-07";
DateFormat formatter;
Date date;
formatter = new SimpleDateFormat("dd-MMM-yy");
date = formatter.parse(str_date);
38 голосов
/ 04 марта 2014

В Java 8 мы получаем новый API даты / времени ( JSR 310 ).

Следующий способ можно использовать для анализа даты в Java 8, не полагаясь на Joda-Time :

 String str = "January 2nd, 2010";

// if we 2nd even we have changed in pattern also it is not working please workout with 2nd 
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMMM Q, yyyy", Locale.ENGLISH);
LocalDate date = LocalDate.parse(str, formatter);

// access date fields
int year = date.getYear(); // 2010
int day = date.getDayOfMonth(); // 2
Month month = date.getMonth(); // JANUARY
int monthAsInt = month.getValue(); // 1

LocalDate - это стандартный класс Java 8 для представления даты (безвремя).Если вы хотите проанализировать значения, которые содержат информацию о дате и времени, вы должны использовать LocalDateTime .Для значений с часовыми поясами используйте ZonedDateTime .Оба предоставляют метод parse(), аналогичный LocalDate:

LocalDateTime dateWithTime = LocalDateTime.parse(strWithDateAndTime, dateTimeFormatter);
ZonedDateTime zoned = ZonedDateTime.parse(strWithTimeZone, zoneFormatter);

Символы форматирования списка из DateTimeFormatter Javadoc :

All letters 'A' to 'Z' and 'a' to 'z' are reserved as pattern letters. 
The following pattern letters are defined:

Symbol  Meaning                     Presentation      Examples
------  -------                     ------------      -------
 G       era                         text              AD; Anno Domini; A
 u       year                        year              2004; 04
 y       year-of-era                 year              2004; 04
 D       day-of-year                 number            189
 M/L     month-of-year               number/text       7; 07; Jul; July; J
 d       day-of-month                number            10

 Q/q     quarter-of-year             number/text       3; 03; Q3; 3rd quarter
 Y       week-based-year             year              1996; 96
 w       week-of-week-based-year     number            27
 W       week-of-month               number            4
 E       day-of-week                 text              Tue; Tuesday; T
 e/c     localized day-of-week       number/text       2; 02; Tue; Tuesday; T
 F       week-of-month               number            3

 a       am-pm-of-day                text              PM
 h       clock-hour-of-am-pm (1-12)  number            12
 K       hour-of-am-pm (0-11)        number            0
 k       clock-hour-of-am-pm (1-24)  number            0

 H       hour-of-day (0-23)          number            0
 m       minute-of-hour              number            30
 s       second-of-minute            number            55
 S       fraction-of-second          fraction          978
 A       milli-of-day                number            1234
 n       nano-of-second              number            987654321
 N       nano-of-day                 number            1234000000

 V       time-zone ID                zone-id           America/Los_Angeles; Z; -08:30
 z       time-zone name              zone-name         Pacific Standard Time; PST
 O       localized zone-offset       offset-O          GMT+8; GMT+08:00; UTC-08:00;
 X       zone-offset 'Z' for zero    offset-X          Z; -08; -0830; -08:30; -083015; -08:30:15;
 x       zone-offset                 offset-x          +0000; -08; -0830; -08:30; -083015; -08:30:15;
 Z       zone-offset                 offset-Z          +0000; -0800; -08:00;
24 голосов
/ 13 февраля 2014

Хотя некоторые ответы технически правильны, они не рекомендуются.

  • Классы java.util.Date & Calendar печально известны своими проблемами.Из-за недостатков в дизайне и реализации, избегайте их.К счастью, у нас есть выбор из двух других превосходных библиотек даты и времени:
    • Joda-Time
      Эта популярная бесплатная библиотека с открытым исходным кодом можетиспользоваться в нескольких версиях Java.Многие примеры его использования можно найти на StackOverflow.Чтение некоторых из них поможет вам быстро освоиться.
    • java.time. * Package
      Этот новый набор классов вдохновлен Joda-Время и определено JSR 310. Эти классы встроены в Java 8. В настоящее время ведется проект по обратному переносу этих классов в Java 7, но это резервное копирование не поддерживается Oracle.
  • Как КристоферДжонсон правильно отметил в своем комментарии к вопросу, другие ответы игнорируют жизненно важные вопросы:
    • Время дня
      Дата имеет как часть даты, так и часть времени дня)
    • Часовой пояс
      Начало дня зависит от часового пояса.Если вам не удается указать часовой пояс, применяется часовой пояс JVM по умолчанию.Это означает, что поведение вашего кода может измениться при запуске на других компьютерах или с измененной настройкой часового пояса.Вероятно, не то, что вам нужно.
    • Языковой стандарт
      Язык языкового стандарта определяет, как следует интерпретировать слова (названия месяца и дня), встречающиеся во время синтаксического анализа.(Ответ от BalusC обрабатывает это должным образом.) Кроме того, языковой стандарт влияет на вывод некоторых форматеров при генерации строкового представления вашей даты и времени.

Joda-Time

Далее следует несколько заметок о Joda-Time.

Часовой пояс

В Joda-Time , DateTime объект действительно знает свой назначенный часовой пояс.Это контрастирует с классом java.util.Date, который , кажется, имеет часовой пояс, но не имеет его.

Обратите внимание в приведенном ниже примере кода, как мы передаем объект часового пояса в средство форматирования, которое анализируетстрока.Этот часовой пояс используется для интерпретации даты и времени как произошедших в этом часовом поясе.Поэтому вам нужно подумать и определить часовой пояс, представленный этим строковым вводом.

Поскольку у вас нет временной части во входной строке, Joda-Time назначает первый момент дня указанного часового пояса каквремя суток.Обычно это означает 00:00:00, но не всегда, из-за перехода на летнее время (DST) или других аномалий.Кстати, вы можете сделать то же самое с любым экземпляром DateTime, вызвав withTimeAtStartOfDay.

Шаблон форматера

Символы, используемые в шаблоне форматера, похожи в Joda-Time на символы в java.util.Date / Calendar но не совсем то же самое.Внимательно прочитайте документ.

Неизменность

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

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

Вам понадобятся объекты java.util.Date дляиспользовать с другими классами / фреймворками, которые не знают об объектах Joda-Time.К счастью, очень легко перемещаться вперед и назад.

Переход от объекта java.util.Date (здесь он называется date) к Joda-Time DateTime…

org.joda.time.DateTime dateTime = new DateTime( date, timeZone );

Идетдругое направление от Joda-Time к объекту java.util.Date…

java.util.Date date = dateTime.toDate();

Пример кода

String input = "January 2, 2010";

java.util.Locale locale = java.util.Locale.US;
DateTimeZone timeZone = DateTimeZone.forID( "Pacific/Honolulu" ); // Arbitrarily chosen for example.
DateTimeFormatter formatter = DateTimeFormat.forPattern( "MMMM d, yyyy" ).withZone( timeZone ).withLocale( locale );
DateTime dateTime = formatter.parseDateTime( input );

System.out.println( "dateTime: " + dateTime );
System.out.println( "dateTime in UTC/GMT: " + dateTime.withZone( DateTimeZone.UTC ) );

При запуске…

dateTime: 2010-01-02T00:00:00.000-10:00
dateTime in UTC/GMT: 2010-01-02T10:00:00.000Z
20 голосов
/ 02 декабря 2011

При работе с классом SimpleDateFormat важно помнить, что Date не является поточно-ориентированным, и вы не можете совместно использовать один объект Date с несколькими потоками.

Также существует большая разница между «m» и «M», когда для минут используется маленький регистр, а для месяца - прописной. То же самое с "D" и "D". Это может вызвать незначительные ошибки, которые часто упускаются из виду. См. Javadoc или Руководство по преобразованию строки в дату в Java для получения дополнительной информации.

16 голосов
/ 04 декабря 2013
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date date;
try {
    date = dateFormat.parse("2013-12-4");
    System.out.println(date.toString()); // Wed Dec 04 00:00:00 CST 2013

    String output = dateFormat.format(date);
    System.out.println(output); // 2013-12-04
} 
catch (ParseException e) {
    e.printStackTrace();
}

У меня отлично работает.

6 голосов
/ 06 мая 2016

Мы использовали два простых средства форматирования:

  1. Какой формат даты мы хотим?
  2. Какой формат даты на самом деле присутствует?

Анализируем полный формат даты и времени:

date="2016-05-06 16:40:32";

public static String setDateParsing(String date) throws ParseException {

    // This is the format date we want
    DateFormat mSDF = new SimpleDateFormat("hh:mm a");

    // This format date is actually present
    SimpleDateFormat formatter = new SimpleDateFormat("yyyy-mm-dd hh:mm");
    return mSDF.format(formatter.parse(date));
}
6 голосов
/ 10 декабря 2012

Кроме того, SimpleDateFormat недоступен с некоторыми технологиями на стороне клиента, такими как GWT .

Это хорошая идея, чтобы перейти к Calendar.getInstance (), и вы должны сравнить две даты; идти на длинное свидание.

5 голосов
/ 25 июля 2017

Вы можете использовать SimpleDateformat для изменения строки на дату

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String strDate = "2000-01-01";
Date date = new Date(sdf.parse(strDate).getTime());
...