java.util.Date to XMLGregorianCalendar - PullRequest
       34

java.util.Date to XMLGregorianCalendar

567 голосов
/ 07 мая 2009

Нет ли удобного способа перейти от java.util.Date к XMLGregorianCalendar?

Ответы [ 9 ]

1015 голосов
/ 07 мая 2009
GregorianCalendar c = new GregorianCalendar();
c.setTime(yourDate);
XMLGregorianCalendar date2 = DatatypeFactory.newInstance().newXMLGregorianCalendar(c);
202 голосов
/ 04 января 2011

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

XMLGregorianCalendar xcal = <assume this is initialized>;
java.util.Date dt = xcal.toGregorianCalendar().getTime();
31 голосов
/ 07 мая 2009

Вот метод для преобразования из 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: -)

22 голосов
/ 03 февраля 2014

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

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

Кредит Николя Момэртс из его комментария в принятый ответ .

12 голосов
/ 16 марта 2011

Просто подумал, что добавлю свое решение ниже, поскольку ответы выше не соответствуют моим точным потребностям. Моя 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);
10 голосов
/ 21 сентября 2010

Я надеюсь, что моя кодировка здесь правильная; 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);
   }

}
6 голосов
/ 26 мая 2019

Я хотел бы сделать шаг назад и по-современному взглянуть на этот 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: это коротко, и я не думаю, что это преподносит какие-либо сюрпризы. Против: Для меня это похоже на пустую трата времени, форматирующее мгновение в строку и анализирующее его обратно.

    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, просто воспользуйтесь ответом Бена Ноланда.

Ссылки

4 голосов
/ 22 апреля 2013

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

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

Пример для jodatime 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 тоже подойдет.

0 голосов
/ 24 марта 2017

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

/* 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);

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

...