Ответ 1
Оригинальный ответ
Я предполагаю, что в разделе "Формат даты XML" вы имеете в виду что-то вроде "2010-11-04T19: 14Z". Фактически это ISO 8601.
Вы можете преобразовать его с помощью SimpleDateFormat, как предложили другие, FastDateFormat или с помощью Joda Time, который, я считаю, специально создан для для этой цели.
Изменить: образцы кода и многое другое
Как заработок, указанный в комментарии, этот ответ можно улучшить с помощью примеров.
Во-первых, мы должны четко указать, что исходный ответ довольно устарел. Это потому, что Java 8 вводит классы для манипулирования датой и временем - пакет java.time
должен представлять интерес. Если вам посчастливилось использовать Java 8, вы должны использовать один из них. Однако эти вещи на удивление трудно получить.
LocalDate (время), которое не является
Рассмотрим следующий пример:
LocalDateTime dateTime = LocalDateTime.parse("2016-03-23T18:21");
System.out.println(dateTime); // 2016-03-23T18:21
Вначале может показаться, что мы используем здесь локальную (к дате и времени пользователя). Однако, если вы осмелитесь спросить, вы получите другой результат:
System.out.println(dateTime.getChronology()); // ISO
Это фактически время ISO. Я считаю, что он должен читать "UTC", но, тем не менее, это не имеет понятия о местном часовом поясе. Поэтому мы должны считать это универсальным.
Обратите внимание, что в конце строки, которую мы обрабатываем, нет "Z". Если вы добавите что-либо отдельно от даты и времени, вас встретит java.time.format.DateTimeParseException
. Таким образом, кажется, что этот класс бесполезен, если мы хотим проанализировать строку ISO8601.
ZonedDateTime на помощь
К счастью, существует класс, который позволяет анализировать строки ISO8601 - это java.time.ZonedDateTime.
ZonedDateTime zonedDateTime = ZonedDateTime.parse("2016-03-23T18:21+01:00");
System.out.println(zonedDateTime); // 2016-03-23T18:21+01:00
ZonedDateTime zonedDateTimeZulu = ZonedDateTime.parse("2016-03-23T18:21Z");
System.out.println(zonedDateTimeZulu); // 2016-03-23T18:21Z
Единственная проблема здесь: вам действительно нужно использовать обозначение часового пояса. Попытка разобрать необработанное время (т.е. "2016-03-23T18: 21" ) приведет к уже упомянутому RuntimeException
. В зависимости от ситуации вам придется выбирать между LocalDateTime
и ZonedDateTime
.
Конечно, вы можете легко конвертировать между этими двумя, поэтому это не должно быть проблемой:
System.out.println(zonedDateTimeZulu.toLocalDateTime()); // 2016-03-23T18:21
// Zone conversion
ZonedDateTime cetDateTime = zonedDateTimeZulu.toLocalDateTime()
.atZone(ZoneId.of("CET"));
System.out.println(cetDateTime); // 2016-03-23T18:21+01:00[CET]
Я рекомендую использовать эти классы в настоящее время. Однако, если ваше должностное задание включает в себя археологию (то есть вам не повезло работать с более чем 2-летней Java 8...), вам может потребоваться использовать что-то еще.
Радость SimpleDateFormat
Я не очень большой поклонник https://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html, но иногда у вас просто нет другого выбора. Проблема в том, что она не является потокобезопасной, и она бросает проверенный Exception
(а именно ParseException
) на ваше лицо, если ему что-то не нравится. Поэтому фрагмент кода довольно уродлив:
private Object lock = new Object();
// ...
try {
synchronized (lock) {
// Either "2016-03-23T18:21+01:00" or "2016-03-23T18:21Z"
// will be correctly parsed (mind the different meaning though)
Date date = dateFormat.parse("2016-03-23T18:21Z");
System.out.println(date); // Wed Mar 23 19:21:00 CET 2016
}
} catch (ParseException e) {
LOG.error("Date time parsing exception", e);
}
FastDateFormat
FastDateFormat
синхронизируется, поэтому вы можете по крайней мере избавиться от синхронизированного блока. Однако это внешняя зависимость. Но поскольку он Apache Commons Lang, и он полностью используется, я думаю, это приемлемо. На самом деле это очень похоже на использование SimpleDateFormat
:
FastDateFormat fastDateFormat = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mmX");
try {
Date fastDate = fastDateFormat.parse("2016-03-23T18:21+01:00");
System.out.println(fastDate);
} catch (ParseException e) {
LOG.error("Date time parsing exception", e);
}
JodaTime
С Joda-Time вы можете подумать, что следующие работы:
DateTimeFormatter parser = ISODateTimeFormat.dateTimeParser();
LocalDateTime dateTime = LocalDateTime.parse("2016-03-23T20:48+01:00", parser);
System.out.println(dateTime); // 2016-03-23T20:48:00.000
К сожалению, независимо от того, что вы положили в последнюю позицию (Z, +03: 00,...), результат будет таким же. Очевидно, что он не работает.
Ну, вы действительно должны разбирать его напрямую:
DateTimeFormatter parser = ISODateTimeFormat.dateTimeParser();
DateTime dateTime = parser.parseDateTime("2016-03-23T21:12:23+04:00");
System.out.println(dateTime); // 2016-03-23T18:12:23.000+01:00
Теперь все будет в порядке. Обратите внимание, что в отличие от одного из других ответов я использовал dateTimeParser()
и не dateTime()
. Я заметил тонкое, но важное различие в поведении между ними (Joda-Time 2.9.2). Но я оставляю это читателю, чтобы проверить его и подтвердить.