java.util.Date to XMLGregorianCalendar

Разве нет удобного способа получить из java.util.Date XMLGregorianCalendar?

10 ответов

Решение
GregorianCalendar c = new GregorianCalendar();
c.setTime(yourDate);
XMLGregorianCalendar date2 = DatatypeFactory.newInstance().newXMLGregorianCalendar(c);

Для тех, кто может оказаться здесь в поисках противоположного преобразования (из XMLGregorianCalendar в Date):

XMLGregorianCalendar xcal = <assume this is initialized>;
java.util.Date dt = xcal.toGregorianCalendar().getTime();

Я хотел бы сделать шаг назад и по-современному взглянуть на этот 10-летний вопрос. Упомянутые классы, Date а также XMLGregorianCalendar, стары сейчас. Я оспариваю их использование и предлагаю альтернативы.

  • Date был всегда плохо спроектирован и ему более 20 лет. Это просто: не используйте его.
  • XMLGregorianCalendar тоже стар и имеет старомодный дизайн. Насколько я понимаю, он использовался для создания даты и времени в формате XML для документов XML. подобно 2009-05-07T19:05:45.678+02:00 или же 2009-05-07T17:05:45.678Z, Эти форматы достаточно хорошо согласуются с ISO 8601, что классы java.time, современного Java-API даты и времени, могут создавать их, что мы предпочитаем.

Нет необходимости в преобразовании

Для многих (большинства?) Целей современная замена Date будет Instant, Instant это момент времени (так же, как Date является).

    Instant yourInstant = // ...
    System.out.println(yourInstant);

Пример вывода из этого фрагмента:

2009-05-07T17: 05: 45.678Z

Это так же, как последний из моего примера XMLGregorianCalendar строки выше. Как многие из вас знают, это происходит из Instant.toString будучи неявно вызванным System.out.println, С java.time во многих случаях нам не нужны преобразования, которые в старые времена мы делали между Date, Calendar, XMLGregorianCalendar и другие классы (в некоторых случаях нам нужны преобразования, хотя я покажу вам пару в следующем разделе).

Управление смещением

Ни Date ни в Instant имеет часовой пояс или смещение UTC. Ранее принятый и все еще получивший наибольшее количество голосов ответ Бен Ноланда использует текущий часовой пояс по умолчанию для JVM для выбора смещения XMLGregorianCalendar, Чтобы включить смещение в современном объекте, мы используем OffsetDateTime, Например:

    ZoneId zone = ZoneId.of("America/Asuncion");
    OffsetDateTime dateTime = yourInstant.atZone(zone).toOffsetDateTime();
    System.out.println(dateTime);

2009-05-07T13: 05: 45.678-04: 00

Опять же, это соответствует формату XML. Если вы хотите снова использовать текущий часовой пояс JVM, установите zone в ZoneId.systemDefault(),

Что если мне абсолютно необходим XMLGregorianCalendar?

Есть больше способов конвертировать Instant в XMLGregorianCalendar, Я представлю пару, каждая со своими плюсами и минусами. Во-первых, просто как XMLGregorianCalendar производит строку как 2009-05-07T17:05:45.678Z, он также может быть построен из такой строки:

    String dateTimeString = yourInstant.toString();
    XMLGregorianCalendar date2
            = DatatypeFactory.newInstance().newXMLGregorianCalendar(dateTimeString);
    System.out.println(date2);

2009-05-07T17: 05: 45.678Z

Pro: это коротко, и я не думаю, что это преподносит какие-либо сюрпризы. Con: Для меня это похоже на пустую трата времени, форматируя мгновение в строку и анализируя его обратно.

    ZonedDateTime dateTime = yourInstant.atZone(zone);
    GregorianCalendar c = GregorianCalendar.from(dateTime);
    XMLGregorianCalendar date2 = DatatypeFactory.newInstance().newXMLGregorianCalendar(c);
    System.out.println(date2);

2009-05-07T13: 05: 45.678-04: 00

Pro: Это официальное преобразование. Управление смещением происходит естественно. Против: он проходит больше шагов и, следовательно, дольше.

Что если у нас будет свидание?

Если вы получили старомодный Date объект из устаревшего API, который вы не можете себе позволить изменить сейчас, преобразуйте его в Instant:

    Instant i = yourDate.toInstant();
    System.out.println(i);

Вывод такой же, как и раньше:

2009-05-07T17: 05: 45.678Z

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

Если у вас есть старомодный Date и абсолютно нужно старомодно XMLGregorianCalendarПросто воспользуйтесь ответом Бена Ноланда.

связи

Вот метод для преобразования из GregorianCalendar в XMLGregorianCalendar; Я оставлю часть преобразования из java.util.Date в GregorianCalendar в качестве упражнения для вас:

import java.util.GregorianCalendar;

import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;

public class DateTest {

   public static void main(final String[] args) throws Exception {
      GregorianCalendar gcal = new GregorianCalendar();
      XMLGregorianCalendar xgcal = DatatypeFactory.newInstance()
            .newXMLGregorianCalendar(gcal);
      System.out.println(xgcal);
   }

}

РЕДАКТИРОВАТЬ: Slooow:-)

Пример из одной строки с использованием библиотеки Joda-Time:

XMLGregorianCalendar xgc = DatatypeFactory.newInstance().newXMLGregorianCalendar(new DateTime().toGregorianCalendar());

Nicolas Mommaerts из его комментария в принятом ответе.

Просто подумал, что я добавлю свое решение ниже, так как ответы выше не соответствуют моим точным потребностям. Моя XML-схема требует отдельных элементов Date и Time, а не отдельного поля DateTime. Стандартный конструктор XMLGregorianCalendar, использованный выше, будет генерировать поле DateTime

Обратите внимание на пару готок, например, добавление одного к месяцу (поскольку java считает месяцы с 0).

GregorianCalendar cal = new GregorianCalendar();
cal.setTime(yourDate);
XMLGregorianCalendar xmlDate = DatatypeFactory.newInstance().newXMLGregorianCalendarDate(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH)+1, cal.get(Calendar.DAY_OF_MONTH), 0);
XMLGregorianCalendar xmlTime = DatatypeFactory.newInstance().newXMLGregorianCalendarTime(cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE), cal.get(Calendar.SECOND), 0);

Я надеюсь, что моя кодировка здесь правильна;D Чтобы сделать это быстрее, просто используйте уродливый вызов GetInstance() из GregorianCalendar вместо вызова конструктора:

import java.util.GregorianCalendar;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;

public class DateTest {

   public static void main(final String[] args) throws Exception {
      // do not forget the type cast :/
      GregorianCalendar gcal = (GregorianCalendar) GregorianCalendar.getInstance();
      XMLGregorianCalendar xgcal = DatatypeFactory.newInstance()
            .newXMLGregorianCalendar(gcal);
      System.out.println(xgcal);
   }

}

Предполагая, что вы декодируете или кодируете XML и используете JAXBзатем можно полностью заменить привязку dateTime и использовать что-то другое, кроме XMLGregorianCalendar для каждой даты в схеме.

Таким образом, вы можете иметь JAXB делайте повторяющиеся вещи, пока вы можете потратить время на написание потрясающего кода, который приносит ценность.

Пример для йодатима DateTime: (Делать это с java.util.Date также будет работать - но с некоторыми ограничениями. Я предпочитаю jodatime, и он скопирован из моего кода, так что я знаю, что это работает...)

<jxb:globalBindings>
    <jxb:javaType name="org.joda.time.LocalDateTime" xmlType="xs:dateTime"
        parseMethod="test.util.JaxbConverter.parseDateTime"
        printMethod="se.seb.bis.test.util.JaxbConverter.printDateTime" />
    <jxb:javaType name="org.joda.time.LocalDate" xmlType="xs:date"
        parseMethod="test.util.JaxbConverter.parseDate"
        printMethod="test.util.JaxbConverter.printDate" />
    <jxb:javaType name="org.joda.time.LocalTime" xmlType="xs:time"
        parseMethod="test.util.JaxbConverter.parseTime"
        printMethod="test.util.JaxbConverter.printTime" />
    <jxb:serializable uid="2" />
</jxb:globalBindings>

И конвертер:

public class JaxbConverter {
static final DateTimeFormatter dtf = ISODateTimeFormat.dateTimeNoMillis();
static final DateTimeFormatter df = ISODateTimeFormat.date();
static final DateTimeFormatter tf = ISODateTimeFormat.time();

public static LocalDateTime parseDateTime(String s) {
    try {
        if (StringUtils.trimToEmpty(s).isEmpty())
            return null;
        LocalDateTime r = dtf.parseLocalDateTime(s);
        return r;
    } catch (Exception e) {
        throw new IllegalArgumentException(e);
    }
}

public static String printDateTime(LocalDateTime d) {
    try {
        if (d == null)
            return null;
        return dtf.print(d);
    } catch (Exception e) {
        throw new IllegalArgumentException(e);
    }
}

public static LocalDate parseDate(String s) {
    try {
        if (StringUtils.trimToEmpty(s).isEmpty())
            return null;
        return df.parseLocalDate(s);
    } catch (Exception e) {
        throw new IllegalArgumentException(e);
    }
}

public static String printDate(LocalDate d) {
    try {
        if (d == null)
            return null;
        return df.print(d);
    } catch (Exception e) {
        throw new IllegalArgumentException(e);
    }
}

public static String printTime(LocalTime d) {
    try {
        if (d == null)
            return null;
        return tf.print(d);
    } catch (Exception e) {
        throw new IllegalArgumentException(e);
    }
}

public static LocalTime parseTime(String s) {
    try {
        if (StringUtils.trimToEmpty(s).isEmpty())
            return null;
        return df.parseLocalTime(s);
    } catch (Exception e) {
        throw new IllegalArgumentException(e);
    }
}

Смотрите здесь: как заменить XmlGregorianCalendar на Date?

Если вы счастливы просто отобразить момент, основанный на часовом поясе + временная метка, и исходный часовой пояс на самом деле не имеет значения, то java.util.Date наверное тоже хорошо.

Проверьте этот код:-

/* Create Date Object */
Date date = new Date();
XMLGregorianCalendar xmlDate = null;
GregorianCalendar gc = new GregorianCalendar();

gc.setTime(date);

try{
    xmlDate = DatatypeFactory.newInstance().newXMLGregorianCalendar(gc);
}
catch(Exception e){
    e.printStackTrace();
}

System.out.println("XMLGregorianCalendar :- " + xmlDate);

Вы можете увидеть полный пример здесь

Мое решение

      public static XMLGregorianCalendar DateToXMLGregorianCalendar(Date date) {

    GregorianCalendar gregoriancalendar = new GregorianCalendar();
    gregoriancalendar.setTime(date);
    XMLGregorianCalendar xmlGregorianCalendar = new XMLGregorianCalendarImpl(gregoriancalendar);
    return xmlGregorianCalendar;
}
Другие вопросы по тегам