Каков наилучший способ преобразования String
в формате "2 января 2010" в Date
на Java?
В конечном счете, я хочу разбить месяц, день и год как целые числа, чтобы я мог использовать
Date date = new Date();
date.setMonth()..
date.setYear()..
date.setDay()..
date.setlong currentTime = date.getTime();
для преобразования даты во времени.
Это сложный путь, и те методы java.util.Date
setter устарели со времени Java 1.1 (1997). Просто отформатируйте дату, используя SimpleDateFormat
используя шаблон формата, соответствующий входной строке.
В вашем конкретном случае "2 января 2010 года" в качестве входной строки:
MMMM
для негоd
.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 или новее, используйте 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)
LocalDateTime#parse(text, formatter)
LocalDate#parse(text, formatter)
вместо LocalDate#parse(text, formatter)
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
).
O
, как позволить ему печатать UTC+08:00
вместо GMT+08:00
. Я не мог получить ни одного примера.
А да обсуждение Java Date снова. Чтобы справиться с обработкой даты, мы используем 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));
String str_date = "11-June-07";
DateFormat formatter;
Date date;
formatter = new SimpleDateFormat("dd-MMM-yy");
date = formatter.parse(str_date);
С Java 8 мы получаем новый API даты/времени (JSR 310).
Следующий способ можно использовать для разбора даты в Java 8, не полагаясь на Joda-Time:
String str = "January 2nd, 2010";
//если мы 2-й, даже если мы изменили в шаблоне, и это не работает, пожалуйста, тренировка с 2-ым 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);
Список символов форматирования из Javadoc DateTimeFormatter:
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;
Хотя некоторые из ответов являются технически правильными, они нецелесообразны.
Несколько заметок о 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
При работе с классом SimpleDateFormat важно помнить, что дата не является потокобезопасной, и вы не можете использовать один объект Date с несколькими потоками.
Также существует большая разница между "m" и "M", где в течение нескольких минут используется небольшой случай, а для случая с капиталом - месяц. То же самое с "d" и "D". Это может привести к незначительным ошибкам, которые часто пропускаются. См. Javadoc или Руководство по преобразованию String to Date в Java для получения более подробной информации.
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();
}
Он отлично работает для меня.
Кроме того, SimpleDateFormat недоступен для некоторых из клиентских технологий, таких как GWT.
Рекомендуется использовать Calendar.getInstance(), и ваше требование - сравнить две даты; идти на длительный срок.
Вы можете использовать SimpleDateformat для изменения строки на сегодняшний день
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String strDate = "2000-01-01";
Date date = new Date(sdf.parse(strDate).getTime());
Простые два форматирования, которые мы использовали:
Мы анализируем полный формат даты и времени:
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));
}
Моя скромная программа испытаний. Я использую его, чтобы поиграть с форматированием и искать длинные даты, которые я нахожу в лог файлах (но кто их там поместил...).
Моя тестовая программа:
package be.test.package.time;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;
public class TimeWork {
public static void main(String[] args) {
TimeZone timezone = TimeZone.getTimeZone("UTC");
List<Long> longs = new ArrayList<>();
List<String> strings = new ArrayList<>();
//Formatting a date needs a timezone - otherwise the date get formatted to your system time zone.
//Use 24h format HH. In 12h format hh can be in range 0-11, which makes 12 overflow to 0.
DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss.SSS");
formatter.setTimeZone(timezone);
Date now = new Date();
//Test dates
strings.add(formatter.format(now));
strings.add("01-01-1970 00:00:00.000");
strings.add("01-01-1970 00:00:01.000");
strings.add("01-01-1970 00:01:00.000");
strings.add("01-01-1970 01:00:00.000");
strings.add("01-01-1970 10:00:00.000");
strings.add("01-01-1970 12:00:00.000");
strings.add("01-01-1970 24:00:00.000");
strings.add("02-01-1970 00:00:00.000");
strings.add("01-01-1971 00:00:00.000");
strings.add("01-01-2014 00:00:00.000");
strings.add("31-12-1969 23:59:59.000");
strings.add("31-12-1969 23:59:00.000");
strings.add("31-12-1969 23:00:00.000");
//Test data
longs.add(now.getTime());
longs.add(-1L);
longs.add(0L); //Long date presentation at - midnight 1/1/1970 UTC - The timezone is important!
longs.add(1L);
longs.add(1000L);
longs.add(60000L);
longs.add(3600000L);
longs.add(36000000L);
longs.add(43200000L);
longs.add(86400000L);
longs.add(31536000000L);
longs.add(1388534400000L);
longs.add(7260000L);
longs.add(1417706084037L);
longs.add(-7260000L);
System.out.println("===== String to long =====");
//Show the long value of the date
for (String string: strings) {
try {
Date date = formatter.parse(string);
System.out.println("Formated date : " + string + " = Long = " + date.getTime());
} catch (ParseException e) {
e.printStackTrace();
}
}
System.out.println("===== Long to String =====");
//Show the date behind the long
for (Long lo : longs) {
Date date = new Date(lo);
String string = formatter.format(date);
System.out.println("Formated date : " + string + " = Long = " + lo);
}
}
}
Результаты тестирования:
===== String to long =====
Formated date : 05-12-2014 10:17:34.873 = Long = 1417774654873
Formated date : 01-01-1970 00:00:00.000 = Long = 0
Formated date : 01-01-1970 00:00:01.000 = Long = 1000
Formated date : 01-01-1970 00:01:00.000 = Long = 60000
Formated date : 01-01-1970 01:00:00.000 = Long = 3600000
Formated date : 01-01-1970 10:00:00.000 = Long = 36000000
Formated date : 01-01-1970 12:00:00.000 = Long = 43200000
Formated date : 01-01-1970 24:00:00.000 = Long = 86400000
Formated date : 02-01-1970 00:00:00.000 = Long = 86400000
Formated date : 01-01-1971 00:00:00.000 = Long = 31536000000
Formated date : 01-01-2014 00:00:00.000 = Long = 1388534400000
Formated date : 31-12-1969 23:59:59.000 = Long = -1000
Formated date : 31-12-1969 23:59:00.000 = Long = -60000
Formated date : 31-12-1969 23:00:00.000 = Long = -3600000
===== Long to String =====
Formated date : 05-12-2014 10:17:34.873 = Long = 1417774654873
Formated date : 31-12-1969 23:59:59.999 = Long = -1
Formated date : 01-01-1970 00:00:00.000 = Long = 0
Formated date : 01-01-1970 00:00:00.001 = Long = 1
Formated date : 01-01-1970 00:00:01.000 = Long = 1000
Formated date : 01-01-1970 00:01:00.000 = Long = 60000
Formated date : 01-01-1970 01:00:00.000 = Long = 3600000
Formated date : 01-01-1970 10:00:00.000 = Long = 36000000
Formated date : 01-01-1970 12:00:00.000 = Long = 43200000
Formated date : 02-01-1970 00:00:00.000 = Long = 86400000
Formated date : 01-01-1971 00:00:00.000 = Long = 31536000000
Formated date : 01-01-2014 00:00:00.000 = Long = 1388534400000
Formated date : 01-01-1970 02:01:00.000 = Long = 7260000
Formated date : 04-12-2014 15:14:44.037 = Long = 1417706084037
Formated date : 31-12-1969 21:59:00.000 = Long = -7260000
Ссылка на источник
Для Android
Calendar.getInstance(). GetTime() дает
Thu Jul 26 15:54:13 GMT+05:30 2018
использование
String oldDate = "Thu Jul 26 15:54:13 GMT+05:30 2018";
DateFormat format = new SimpleDateFormat("EEE LLL dd HH:mm:ss Z yyyy");
Date updateLast = format.parse(oldDate);
У меня была задача, когда мне пришлось писать код, который бы взял любую строку и попытался преобразовать ее в дату, когда формат строки неизвестен заранее.
Я написал интересную полезность. Вот статья, в которой описывается идея: Java 8 java.time package: синтаксический анализ любой строки на сегодняшний день. Это было реализовано на Java 8, но идея могла быть реализована и в ранних версиях.
JavaScript-решение:
добавить скрытое поле с тем же именем ввода и сохранить дату в правильном формате в этом поле
требуется moment.js
$(window).load(function () {
$("input.hasDatepicker").each(function () {
var thisRef = $(this);
var datePickerName = thisRef.attr("name");
thisRef.attr("name", datePickerName + "Display");
var hiddenField = $('<input type="hidden" name="' + datePickerName + '" />');
thisRef.parent().prepend(hiddenField);
thisRef.change(function () {
$(hiddenField).val($(this).val() != "" ? moment($(this).val(), "DD-MM-YYYY").format() : "");
});
if (thisRef.val() != "") thisRef.trigger("change");
});
});
Попробуйте это
String date = get_pump_data.getString("bond_end_date");
DateFormat format = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH);
Date datee = (Date)format.parse(date);