Вопрос-ответ

Java string to date conversion

Преобразование строки Java в дату

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

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

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

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

Переведено автоматически
Ответ 1

Это сложный путь, и эти java.util.Date методы настройки устарели со времен Java 1.1 (1997). Более того, весь java.util.Date класс де-факто устарел (не рекомендуется) с момента появления java.time API в Java 8 (2014).

Просто отформатируйте дату с помощью DateTimeFormatter шаблона, соответствующего входной строке (руководство доступно здесь).

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


  1. "Январь" - это полный текстовый месяц, поэтому используйте для него MMMM шаблон

  2. "2" - это сокращенный день месяца, поэтому используйте для него шаблон d.

  3. "2010" - это 4-значный год, поэтому используйте для него yyyy шаблон.

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, в которой перечислены все доступные шаблоны форматирования:

































































































































































































СимволЗначениеПрезентацияПримеры
GэпохатекстAD; Anno Domini; A
uгодгод2004; 04
yгод выпускагод2004; 04
Dдень годаколичество189
M/Lмесяц годачисло / текст7; 07; Июля; July; J
dдень месяцаколичество10
Q/qквартал за годчисло / текст3; 03; 3 квартал; 3-й квартал
Yв зависимости от недели-годгод1996; 96
wпо неделям в зависимости от годаколичество27
Wнеделя месяцаколичество4
Eдень неделитекстВт; Tuesday; T
e/cлокализованный день неделичисло / текст2; 02; Вт; Вторник; T
Fнеделя месяцаколичество3
aс утра до вечера текущего днятекстPM
hчасы-время-утра-вечера (1-12)количество12
Kвремя от утра до вечера (0-11)количество0
kчасы-время-утра-вечера (1-24)количество0
Hвремя суток (0-23)количество0
mколичество минут в часколичество30
sсекунда в минутуколичество55
Sдоля секундыдробь978
Aколичество за миллион днейколичество1234
nдоли секундыколичество987654321
Nновинка дняколичество1234000000
Vидентификатор часового поясаидентификатор зоныАмерика/Los_Angeles; Z; -08:30
zназвание часового поясаназвание зоныСтандартное тихоокеанское время; PST
Oлокализованная зона-смещениесмещение-OGMT+8; GMT +08:00; UTC-08:00;
Xзона-смещение 'Z' вместо нулясмещение-XZ; -08; -0830; -08:30; -083015; -08:30:15;
xсмещение зонысмещение-x+0000; -08; -0830; -08:30; -083015; -08:30:15;
Zсмещение зонысмещение-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).


До Java 8

Если вы еще не используете Java 8 или вынуждены использовать java.util.Date, то отформатируйте дату с помощью SimpleDateFormat шаблона формата, соответствующего входной строке.

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, в которой перечислены все доступные шаблоны форматирования:

















































































































































ПисьмоКомпонент даты или времениПрезентацияПримеры
GОбозначение эпохиТекстОБЪЯВЛЕНИЕ
yГодГод1996; 96
YНеделя, годГод2009; 09
M/LМесяц в годуМесяцИюль; Jul; 07
wНеделя в годуЧисло27
WНеделя в месяцеЧисло2
DДень в годуЧисло189
dЧисло в месяцеЧисло10
FДень недели в месяцеЧисло2
EДень в неделеТекстВторник; Вт
uНомер дня неделиЧисло1
aМаркер утра / вечераТекстPM
HЧас в сутках (0-23)Число0
kЧас в сутках (1-24)Число24
KВремя в часах утра / вечера (0-11)Число0
hВремя в часах утра / вечера (1-12)Число12
mМинута в часЧисло30
sСекунда в минутеЧисло55
SМиллисекундаЧисло978
zЧасовой поясОбщий часовой поясСтандартное тихоокеанское время; PST; GMT-08:00
ZЧасовой поясЧасовой пояс RFC 822-0800
XЧасовой поясЧасовой пояс ISO 8601-08; -0800; -08:00

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

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























































Входная строкаШаблон
2001.07.04 Объявление в 12:08:56 PDTyyyy.MM.dd G 'at' HH:mm:ss z
Ср., 4 июля '01EEE, MMM d, ''yy
12:08h:mm a
12 часов вечера по Тихоокеанскому летнему времениhh 'o''clock' a, zzzz
09:08 PDTK:mm a, z
02001.Июль.04 AD 12:08yyyyy.MMMM.dd GGG hh:mm aaa
Ср., 4 июля 2001 г. 12:08:56 -0700EEE, d MMM yyyy HH:mm:ss Z
010704120856-0700yyMMddHHmmssZ
2001-07-04T12:08:56.235-0700yyyy-MM-dd'T'HH:mm:ss.SSSZ
2001-07-04T12:08:56.235-07:00yyyy-MM-dd'T'HH:mm:ss.SSSXXX
2001-W27-3YYYY-'W'ww-u

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

Ответ 2

Ах да, опять обсуждение даты Java. Для работы с датами мы используем Date, Calendar, 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));
Ответ 3
String str_date = "11-June-07";
DateFormat formatter = new SimpleDateFormat("dd-MMM-yy");
Date date = formatter.parse(str_date);
Ответ 4

С 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;
java string date