难道没有从java.util.Date到XMLGregorianCalendar的方便方法吗?
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); } }
对于那些可能在这里结束寻找相反的转换(从XMLGregorianCalendar到Date):
XMLGregorianCalendar
Date
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
这样,你可以让JAXB做重复的事情,而你可以花时间写出色的代码,提供价值。
jodatime DateTime的例子:(使用java.util.Date也可以工作-但有某些限制。我更喜欢jodatime,它是从我的代码中复制的,所以我知道它可以工作…)
DateTime
<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); } }
如果您愿意只根据时区+时间戳映射到一个瞬间,而原始时区并不真正相关,那么java.util.Date可能也很好。
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年前的问题。上面提到的类Date和XMLGregorianCalendar现在已经过时了。我对它们的使用提出质疑,并提供替代方案。
2009-05-07T19:05:45.678+02:00
2009-05-07T17:05:45.678Z
对于许多(大多数?)目的,Date的现代替代品将是Instant。Instant是一个时间点(就像Date一样)。
Instant
Instant yourInstant = // ... System.out.println(yourInstant);
这段代码的输出示例:
2009 - 05 - 07 - t17:05:45.678z
它与上面示例XMLGregorianCalendar strings中的后者相同。正如你们大多数人所知道的,它来自Instant.toString被System.out.println隐式调用。与java。在许多情况下,我们不需要在以前的Date, Calendar, XMLGregorianCalendar和其他类之间进行转换(在某些情况下,我们确实需要转换,不过,我将在下一节向您展示一对)。
Instant.toString
System.out.println
Calendar
Date和Instant中都没有时区或UTC偏移量。Ben Noland给出的先前被接受且投票最多的答案使用jvm当前默认时区来选择XMLGregorianCalendar的偏移量。要在现代对象中包含偏移量,我们使用OffsetDateTime。例如:
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()。
zone
ZoneId.systemDefault()
有很多方法可以将Instant转换为XMLGregorianCalendar。我将介绍两个,每个都有其优缺点。首先,正如XMLGregorianCalendar产生了一个像2009-05-07T17:05:45.678Z这样的字符串,它也可以从这样的字符串构建:
String dateTimeString = yourInstant.toString(); XMLGregorianCalendar date2 = DatatypeFactory.newInstance().newXMLGregorianCalendar(dateTimeString); System.out.println(date2);
教授:它很短,我不认为它会给人任何惊喜。缺点:对我来说,将瞬间格式化为字符串并解析回来是一种浪费。
ZonedDateTime dateTime = yourInstant.atZone(zone); GregorianCalendar c = GregorianCalendar.from(dateTime); XMLGregorianCalendar date2 = DatatypeFactory.newInstance().newXMLGregorianCalendar(c); System.out.println(date2);
教授:这是官方的转换。控制偏移量是自然而然的。缺点:它要经过更多的步骤,因此时间更长。
如果你从一个遗留API中得到了一个老式的Date对象,而你现在无法承担更改的代价,将它转换为Instant:
Instant i = yourDate.toInstant(); System.out.println(i);
输出与之前相同:
如果你想控制偏移量,可以按照上面的方法进一步转换为OffsetDateTime。
如果你有一个老式的Date,并且绝对需要一个老式的XMLGregorianCalendar,那就用本·诺兰德的答案吧。
我的解决方案
public static XMLGregorianCalendar DateToXMLGregorianCalendar(Date date) { GregorianCalendar gregoriancalendar = new GregorianCalendar(); gregoriancalendar.setTime(date); XMLGregorianCalendar xmlGregorianCalendar = new XMLGregorianCalendarImpl(gregoriancalendar); return xmlGregorianCalendar; }