java.util.Date到XMLGregorianCalendar

时间:2009-05-07 17:05:03

标签: java xml date xmlgregoriancalendar

是否有从java.util.Date到XMLGregorianCalendar的便捷方式?

9 个答案:

答案 0 :(得分:1013)

GregorianCalendar c = new GregorianCalendar();
c.setTime(yourDate);
XMLGregorianCalendar date2 = DatatypeFactory.newInstance().newXMLGregorianCalendar(c);

答案 1 :(得分:202)

对于那些可能会在此处寻找相反转化的人(从XMLGregorianCalendarDate):

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

答案 2 :(得分:31)

这是一种从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: - )

答案 3 :(得分:22)

使用Joda-Time库的一行示例:

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

Nicolas Mommaerts的评论中感谢the accepted answer

答案 4 :(得分:12)

以为我会在下面添加我的解决方案,因为上面的答案不符合我的确切需求。我的Xml架构需要单独的Date和Time元素,而不是单独的DateTime字段。上面使用的标准XMLGregorianCalendar构造函数将生成DateTime字段

请注意有几个gothca,例如必须在一个月内添加一个(因为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);

答案 5 :(得分:10)

我希望我的编码是正确的; D 为了加快速度,只需使用GregorianCalendar的丑陋getInstance()调用而不是构造函数调用:

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 :(得分:4)

假设您正在解码或编码xml并使用JAXB,那么可以完全替换dateTime绑定,并为模式中的每个日期使用除“XMLGregorianCalendar”之外的其他内容。

通过这种方式,你可以让JAXB做重复的事情,同时你可以花时间编写可以提供价值的优秀代码。

jodatime DateTime的示例:(使用java.util.Date执行此操作也会有效 - 但有一些限制。我更喜欢jodatime,它是从我的代码中复制的,所以我知道它有效......)< / p>

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

见这里: how replace XmlGregorianCalendar by Date?

如果您很乐意根据时区+时间戳映射到一个瞬间,并且原始时区不是真正相关的,那么java.util.Date也可能很好。

答案 7 :(得分:3)

我想退后一步,以现代的眼光看待这个已有10年历史的问题。提到的类DateXMLGregorianCalendar现在已经很老了。我挑战使用它们并提供替代方法。

  • Date的设计总是很差,已经有20多年的历史了。这很简单:请勿使用。
  • XMLGregorianCalendar也很旧,并且具有老式的设计。据我了解,它用于以XML格式为XML文档生成日期和时间。像2009-05-07T19:05:45.678+02:002009-05-07T17:05:45.678Z。这些格式与ISO 8601足够吻合,因此可以使用我们喜欢的现代Java日期和时间API类java.time来生成它们。

无需转换

出于许多(大多数?)目的,Date的现代替代品将是InstantInstant是一个时间点(就像Date一样)。

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

此代码段的示例输出:

  

2009-05-07T17:05:45.678Z

与上面的示例XMLGregorianCalendar字符串的后者相同。众所周知,它来自Instant.toString隐式调用System.out.println。使用java.time,在许多情况下,我们不需要过去在DateCalendarXMLGregorianCalendar和其他类之间进行的转换(在某些情况下,我们确实需要不过,在下一部分中,我将向您展示一些转换。

控制偏移量

DateInstant中都没有时区或UTC偏移量。 Ben Noland先前接受并投票仍然最高的答案是使用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

专业人士:简短,我认为这不会给您带来任何惊喜。缺点:对我来说,将即时信息格式化为字符串并解析回字符串是一种浪费。

    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

专业版:这是官方转换。控制偏移量自然而然。缺点:它要经过更多的步骤,因此会更长。

如果我们有个约会怎么办?

如果您从无法立即更改的旧版API中获得了老式的Date对象,请将其转换为Instant

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

输出与以前相同:

  

2009-05-07T17:05:45.678Z

如果要控制偏移量,请按照上述相同方法进一步转换为OffsetDateTime

如果您拥有老式Date,并且绝对需要老式XMLGregorianCalendar,请使用Ben Noland的答案。

链接

答案 8 :(得分:0)

查看此代码: -

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

您可以看到完整的示例here