date到XMLGregorianCalendar

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

662160 次浏览
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);
}


}

编辑:慢:-)

我希望我的编码在这里是正确的 为了使它更快,只需使用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);
}


}

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

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

我只是想在下面加上我的解决方案,因为上面的答案并不能满足我的确切需求。我的Xml模式需要单独的Date和Time元素,而不是一个DateTime字段。上面使用的标准XMLGregorianCalendar构造函数将生成一个DateTime字段

注意这里有几个gothca,例如必须在月份中添加1(因为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);

假设您正在解码或编码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);
}
}
< p >看这里: # EYZ0 < / p >

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

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

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

他在公认的答案中的评论归功于尼古拉斯Mommaerts

看看这段代码:-

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

您可以看到完整的示例在这里

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

  • Date设计一直很糟糕,已经有20多年的历史了。这很简单:不要使用它。
  • XMLGregorianCalendar也很老了,有一个老式的设计。据我所知,它用于为XML文档生成XML格式的日期和时间。比如2009-05-07T19:05:45.678+02:002009-05-07T17:05:45.678Z。这些格式很好地符合ISO 8601, java的类。time,现代Java日期和时间API,可以生成它们,这是我们喜欢的。

不需要转换

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

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

这段代码的输出示例:

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

它与上面示例XMLGregorianCalendar strings中的后者相同。正如你们大多数人所知道的,它来自Instant.toStringSystem.out.println隐式调用。与java。在许多情况下,我们不需要在以前的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 - 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,那就用本·诺兰德的答案吧。

链接

我的解决方案

public static XMLGregorianCalendar DateToXMLGregorianCalendar(Date date) {


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