难道没有从java.util.Date到XMLGregorianCalendar的方便方法吗?
当前回答
我的解决方案
public static XMLGregorianCalendar DateToXMLGregorianCalendar(Date date) {
GregorianCalendar gregoriancalendar = new GregorianCalendar();
gregoriancalendar.setTime(date);
XMLGregorianCalendar xmlGregorianCalendar = new XMLGregorianCalendarImpl(gregoriancalendar);
return xmlGregorianCalendar;
}
其他回答
我想退一步,用现代的眼光来看待这个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
我的解决方案
public static XMLGregorianCalendar DateToXMLGregorianCalendar(Date date) {
GregorianCalendar gregoriancalendar = new GregorianCalendar();
gregoriancalendar.setTime(date);
XMLGregorianCalendar xmlGregorianCalendar = new XMLGregorianCalendarImpl(gregoriancalendar);
return xmlGregorianCalendar;
}
假设您正在解码或编码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 ?
如果您愿意只根据时区+时间戳映射到某个时刻,而原始时区并不真正相关,那么java.util.Date可能也可以。
GregorianCalendar c = new GregorianCalendar();
c.setTime(yourDate);
XMLGregorianCalendar date2 = DatatypeFactory.newInstance().newXMLGregorianCalendar(c);
使用Joda-Time库的一行示例:
XMLGregorianCalendar xgc = DatatypeFactory.newInstance().newXMLGregorianCalendar(new DateTime().toGregorianCalendar());
这要归功于Nicolas Mommaerts在公认答案中的评论。
推荐文章
- 到底是什么导致了堆栈溢出错误?
- 为什么Android工作室说“等待调试器”如果我不调试?
- Java:路径vs文件
- ExecutorService,如何等待所有任务完成
- 为什么在JavaScript的Date构造函数中month参数的范围从0到11 ?
- Maven依赖Servlet 3.0 API?
- 如何在IntelliJ IDEA中添加目录到应用程序运行概要文件中的类路径?
- getter和setter是糟糕的设计吗?相互矛盾的建议
- Android room persistent: AppDatabase_Impl不存在
- Java的String[]在Kotlin中等价于什么?
- Intellij IDEA上的System.out.println()快捷方式
- 使用Spring RestTemplate获取JSON对象列表
- Spring JPA选择特定的列
- URLEncoder不能翻译空格字符
- Java中的super()