0

我有一个带有以下格式的日期标签的肥皂网络服务

2019-12-01T04:00:00。0000000 Z(七个零)

现在我正在实现客户端,我无法创建一个带有七个零的 XMLGregorianCalendar,我只剩下三个零了

我的代码

    DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSSS'Z'");
    Date date = df.parse("2019-12-01T04:00:00.0000000Z");       
    GregorianCalendar gcal = new GregorianCalendar();
    gcal.setTime(date);
    gcal.setTimeZone(TimeZone.getTimeZone("UTC"));

    XMLGregorianCalendar fecha = DatatypeFactory.newInstance().newXMLGregorianCalendar(gcal);

    System.out.println("fecha ->"+fecha.toString());

输出

    fecha ->2019-12-01T07:00:00.000Z

我怎样才能让 XMLGregorianCalendar 在格式中保留七个零?

4

2 回答 2

1

您可能不需要 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 位小数,则有两种方法可以产生一种:

  1. DatatypeFactory.newXMLGregorianCalendar​(String)如另一个答案中使用的:

        XMLGregorianCalendar fecha = DatatypeFactory.newInstance()
                .newXMLGregorianCalendar("2019-12-01T04:00:00.0000000Z");
        System.out.println(fecha);
    

    2019-12-01T04:00:00.0000000Z

  2. 将 a 传递BigDecimalDatatypeFactory

        XMLGregorianCalendar fecha = DatatypeFactory.newInstance()
                .newXMLGregorianCalendar(BigInteger.valueOf(2019), 12, 1, 
                        4, 0, 0, new BigDecimal("0.0000000"), 0);
    

无论如何,在任何情况下,我都建议您不要使用SimpleDateFormatand Date。这些类设计不佳且早已过时,尤其是前者,尤其是出了名的麻烦。对于GregorianCalendar. 我们有时可能会使用它,XMLGregorianCalendar因为两者之间存在转换(如您的问题中所用)。GregorianCalendar只有毫秒精度,所以你永远不会通过这样的转换得到 7 位小数。

代码中的错误

您的代码中有两个错误。

  1. 在格式模式字符串中硬编码Z为文字是错误的。Z是与 UTC 的偏移量(为零),需要按此进行解析,否则您将在绝大多数 JVM 上得到错误的时间。
  2. SimpleDateFormat也只支持毫秒,精确到小数点后三位。当分数全为零时,您不会注意到错误,但是一旦有人在某处输入非零数字,您就会得到错误的结果。没有办法SimpleDateFormat正确处理 2 个或 4 个或 7 个小数位。

链接

于 2019-12-03T02:15:17.437 回答
0

您可以使用接受数据类型的词法表示的工厂方法:

XMLGregorianCalendar fecha = DatatypeFactory.newInstance().newXMLGregorianCalendar(df.format(date));
于 2019-12-03T00:12:45.493 回答