Преобразование даты Java в формат даты XML (и наоборот) - PullRequest
21 голосов
/ 04 ноября 2010

Есть ли хороший и простой способ конвертировать Java Date в формат строки даты XML и наоборот?

Cheers,

Andez

Ответы [ 9 ]

22 голосов
/ 04 ноября 2010

Оригинальный ответ

Я предполагаю, что под «форматом даты XML» вы подразумеваете что-то вроде «2010-11-04T19: 14Z».Это на самом деле ISO 8601 формат.

. Вы можете конвертировать его, используя SimpleDateFormat, как другие предлагали, FastDateFormat или Joda Time , который, я считаю, был специально создан для * 1009.* с этой целью .

Редактировать: примеры кода и многое другое

Поскольку earnshae указано в комментарии, этот ответ можно улучшить с помощью примеров.

Во-первых, мы должны дать понять, что первоначальный ответ довольно устарел.Это потому, что в Java 8 введены классы для манипулирования датой и временем - пакет java.time должен представлять интерес.Если вам повезло использовать Java 8, вам следует использовать один из них.Тем не менее, эти вещи на удивление трудно понять правильно.

LocalDate (Time), который не

Рассмотрим этот пример:

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]

Iрекомендую использовать этот класс в настоящее время.Однако, если ваше описание работы включает в себя археологию (то есть вам не повезло работать с более чем 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).Но я предоставляю читателю возможность проверить и подтвердить.

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

Как уже предлагалось, используйте 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

9 голосов
/ 04 ноября 2010

Используя 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

Потокобезопасный, неизменный и простой.

8 голосов
/ 15 сентября 2014

Идеальный метод, используйте XMLGregorianCalendar:

GregorianCalendar calendar = new GregorianCalendar();
calendar.setTime(v);
DatatypeFactory df = DatatypeFactory.newInstance();
XMLGregorianCalendar dateTime = df.newXMLGregorianCalendar(calendar);
return dateTime.toString();
7 голосов
/ 31 декабря 2011

Просто используя SimpleDateFormat в Java, мы можем сделать это ...

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
Date date = sdf.parse("2011-12-31T15:05:50+1000");
4 голосов
/ 21 октября 2015

Я бы порекомендовал использовать встроенный в Java класс javax.xml.bind.DatatypeConverter .Он может обрабатывать преобразование в большинство простых типов XML.Для дат немного трудновато, что вам нужно пройти через объект Calendar, но, с другой стороны, он обрабатывает все варианты информации о зоне, которые могут присутствовать в поле xml datetime.

From 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);

EDIT

Класс DatatypeConverter больше не является публично видимым в Java 9выше, поскольку он принадлежит пакету javax.xml.bind.См. этот вопрос для получения дополнительной информации и возможных решений.Решение, предложенное loic vaugeois для использования XmlGregorianCalendar, в этом случае намного лучше.

3 голосов
/ 04 ноября 2010

Вы можете анализировать и форматировать даты в любом формате, используя SimpleDateFormat

2 голосов
/ 18 сентября 2015

Чтобы соответствовать ISO8601, часовой пояс должен быть в формате + ЧЧ: ММ или - ЧЧ: ММ

В Simpledateformat вы должны использовать XXX вместо Z (см. Ответ NovelGuy)

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
1 голос
/ 04 ноября 2010

Не зная точно, какой формат вам нужен, вы получите общий ответ: вам понадобится DateFormat или SimpleDateFormat. На обоих есть .

хороший учебник
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...