难道没有从java.util.Date到XMLGregorianCalendar的方便方法吗?


当前回答

我的解决方案

public static XMLGregorianCalendar DateToXMLGregorianCalendar(Date date) {

    GregorianCalendar gregoriancalendar = new GregorianCalendar();
    gregoriancalendar.setTime(date);
    XMLGregorianCalendar xmlGregorianCalendar = new XMLGregorianCalendarImpl(gregoriancalendar);
    return xmlGregorianCalendar;
}

其他回答

对于那些可能在这里结束寻找相反转换(从XMLGregorianCalendar到Date)的人:

XMLGregorianCalendar xcal = <assume this is initialized>;
java.util.Date dt = xcal.toGregorianCalendar().getTime();
GregorianCalendar c = new GregorianCalendar();
c.setTime(yourDate);
XMLGregorianCalendar date2 = DatatypeFactory.newInstance().newXMLGregorianCalendar(c);

下面是一个从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:-)

我想退一步,用现代的眼光来看待这个10年前的问题。上面提到的Date和XMLGregorianCalendar类现在已经很老了。我对它们的使用提出质疑,并提供替代方案。

日期总是设计得很糟糕,而且是20多年前的。这很简单:不要使用它。 XMLGregorianCalendar也很老了,它的设计也很过时。据我所知,它用于为XML文档生成XML格式的日期和时间。比如2009-05-07T19:05:45.678+02:00或2009-05-07T17:05:45.678Z。这些格式很好地符合ISO 8601, java的类。time,现代Java日期和时间API,可以生成它们,这是我们喜欢的。

不需要转换

在许多(大多数?)目的下,日期的现代替代品将是瞬间。一个瞬间是一个时间点(就像一个日期一样)。

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

这段代码的输出示例:

2009 - 05 - 07 - t17:05:45.678z

它与上面XMLGregorianCalendar字符串示例中的后者相同。正如你们大多数人所知道的,它来自Instant。toString被System.out.println隐式调用。与java。在许多情况下,我们不需要像过去那样在Date、Calendar、XMLGregorianCalendar和其他类之间进行转换(在某些情况下,我们确实需要转换,不过,我将在下一节向您展示两个)。

控制偏移量

Date和Instant都没有时区和UTC偏移量。Ben Noland之前给出的答案是使用jvm当前默认时区来选择XMLGregorianCalendar的偏移量。要在现代对象中包含偏移量,我们使用OffsetDateTime。例如:

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

2009 - 05 - 07 - t13:05:45.678内

这同样符合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 - 07 - t17: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 - 07 - t13:05:45.678内

教授:这是官方的转换。控制偏移量是自然而然的。缺点:它要经过更多的步骤,因此时间更长。

如果我们有个约会呢?

如果你从一个遗留API中得到了一个过时的Date对象,而你现在无法承担更改的代价,将它转换为Instant:

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

输出与之前相同:

2009 - 05 - 07 - t17:05:45.678z

如果您想控制偏移量,请按照上面的方法进一步转换为OffsetDateTime。

如果您有一个老式的Date,并且绝对需要一个老式的XMLGregorianCalendar,那么只需使用Ben Noland的答案。

链接

Oracle教程:Date Time解释如何使用java.time。 W3Schools上的XSD日期和时间数据类型。 维基百科文章:ISO 8601

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

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

这要归功于Nicolas Mommaerts在公认答案中的评论。