Есть ли хороший и простой способ преобразования даты Java в формат строки даты XML и наоборот?
Приветствия,
Andez
Есть ли хороший и простой способ преобразования даты Java в формат строки даты XML и наоборот?
Приветствия,
Andez
Я предполагаю, что в разделе "Формат даты XML" вы имеете в виду что-то вроде "2010-11-04T19: 14Z". Фактически это ISO 8601.
Вы можете преобразовать его с помощью SimpleDateFormat, как предложили другие, FastDateFormat или с помощью Joda Time, который, я считаю, специально создан для для этой цели.
Как заработок, указанный в комментарии, этот ответ можно улучшить с помощью примеров.
Во-первых, мы должны четко указать, что исходный ответ довольно устарел. Это потому, что Java 8 вводит классы для манипулирования датой и временем - пакет java.time
должен представлять интерес. Если вам посчастливилось использовать Java 8, вы должны использовать один из них. Однако эти вещи на удивление трудно получить.
Рассмотрим следующий пример:
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.
К счастью, существует класс, который позволяет анализировать строки 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...), вам может потребоваться использовать что-то еще.
Я не очень большой поклонник 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
синхронизируется, поэтому вы можете по крайней мере избавиться от синхронизированного блока. Однако это внешняя зависимость. Но поскольку он 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);
}
С 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). Но я оставляю это читателю, чтобы проверить его и подтвердить.
Как уже было предложено использовать SimpleDateFormat.
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
String date = sdf.format(new Date());
System.out.println(date);
Date d = sdf.parse(date);
Я предполагаю, что формат/шаблон, который вы ищете, yyyy-MM-dd'T'HH:mm:ss
Также посмотрите http://www.w3schools.com/schema/schema_dtypes_date.asp
Используя Joda Time, вы бы сделали следующее:
DateTimeFormatter fmt = ISODateTimeFormat.dateTime(); // ISO8601 (XML) Date/time
DateTime dt = fmt.parseDateTime("2000-01-01T12:00:00+100"); // +1hr time zone
System.out.println(fmt.print(dt)); // Prints in ISO8601 format
Нить безопасная, неизменная и простая.
Просто используя SimpleDateFormat в java, мы можем это сделать...
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
Date date = sdf.parse("2011-12-31T15:05:50+1000");
Метод Perfect, используйте XMLGregorianCalendar:
GregorianCalendar calendar = new GregorianCalendar();
calendar.setTime(v);
DatatypeFactory df = DatatypeFactory.newInstance();
XMLGregorianCalendar dateTime = df.newXMLGregorianCalendar(calendar);
return dateTime.toString();
Вы можете анализировать и форматировать даты в любом формате с помощью SimpleDateFormat
Я бы рекомендовал использовать java, встроенный в класс javax.xml.bind.DatatypeConverter. Он может обрабатывать преобразование в большинство простых xml-типов и из них. Немного громоздко для дат, которые вы должны пройти через объект Calendar
, но, с другой стороны, он обрабатывает все варианты информации о зоне, которые могут встречаться в поле xml datetime
.
Из xml:
Calendar c = DatatypeConverter.parseDateTime("2015-10-21T13:25");
Date d = c.getTime();
В xml:
Date yourDate = new Date()
Calendar c = Calendar.getInstance();
c.setTime(yourDate);
String xmlDateTime = DatatypeConverter.printDateTime(c);
Чтобы соответствовать ISO8601, часовой пояс должен быть в формате + HH: MM или - HH: MM
С Simpledateformat вы должны использовать XXX вместо Z (см. ответ NovelGuy)
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
Не зная точно, какой формат вам нужен, общий ответ: вам понадобится DateFormat или SimpleDateFormat. Существует хороший учебник для здесь.