您可能不需要 7 位小数
通常,SOAP Web 服务不需要任何特定的小数位数。它需要带有 XML 格式的日期和时间的 XML。XML 的日期和时间格式的灵感来自 ISO 8601 格式(底部的链接)。日期和时间数据类型上的 W3Schools 页面甚至没有提到指定秒的任何分数的可能性:
dateTime 以以下形式指定 "YYYY-MM-DDThh:mm:ss" ...</p>
不过,引用 W3C 的XML Schema Part 2: Datatypes Second Edition时,允许“任意精度级别”的秒小数部分。因此,如果您的 Web 服务坚持精确到小数点后 7 位,这是一个特殊且不寻常的限制。你可能想挑战它。
XMLGregorianCalendar 的替代品
现在XMLGregorianCalendar
班老了。它完全用于为 SOAP 和许多其他地方使用的 XML 文档生成 ISO 8601 格式。java.time 类,现代 Java 日期和时间 API,也产生 ISO 8601 格式。我们更喜欢使用这些(除非有非常特殊的要求XMLGregorianCalendar
)。
OffsetDateTime odt = OffsetDateTime.of(2019, 12, 1, 4, 0, 0, 0, ZoneOffset.UTC);
System.out.println(odt);
此代码段输出:
2019-12-01T04:00Z
如果确实需要 7 位小数,请使用格式化程序:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSSSSSX");
System.out.println(odt.format(formatter));
2019-12-01T04:00:00.0000000Z
当然,如果您已经得到了字符串,2019-12-01T04:00:00.0000000Z
就像您的问题一样,只需将其直接放入您的 XML 文档中。如果您需要先验证它,请将其传递给Instant.parse()
并查看是否获得DateTimeFormatException
.
如果您确实无法避免在XMLGregorianCalendar
秒上需要 7 位小数,则有两种方法可以产生一种:
DatatypeFactory.newXMLGregorianCalendar(String)
如另一个答案中使用的:
XMLGregorianCalendar fecha = DatatypeFactory.newInstance()
.newXMLGregorianCalendar("2019-12-01T04:00:00.0000000Z");
System.out.println(fecha);
2019-12-01T04:00:00.0000000Z
将 a 传递BigDecimal
给DatatypeFactory
:
XMLGregorianCalendar fecha = DatatypeFactory.newInstance()
.newXMLGregorianCalendar(BigInteger.valueOf(2019), 12, 1,
4, 0, 0, new BigDecimal("0.0000000"), 0);
无论如何,在任何情况下,我都建议您不要使用SimpleDateFormat
and Date
。这些类设计不佳且早已过时,尤其是前者,尤其是出了名的麻烦。对于GregorianCalendar
. 我们有时可能会使用它,XMLGregorianCalendar
因为两者之间存在转换(如您的问题中所用)。GregorianCalendar
只有毫秒精度,所以你永远不会通过这样的转换得到 7 位小数。
代码中的错误
您的代码中有两个错误。
- 在格式模式字符串中硬编码
Z
为文字是错误的。Z
是与 UTC 的偏移量(为零),需要按此进行解析,否则您将在绝大多数 JVM 上得到错误的时间。
SimpleDateFormat
也只支持毫秒,精确到小数点后三位。当分数全为零时,您不会注意到错误,但是一旦有人在某处输入非零数字,您就会得到错误的结果。没有办法SimpleDateFormat
正确处理 2 个或 4 个或 7 个小数位。
链接