0

使用java.time.Instantjavax.xml.datatype.XMLGregorianCalendar,我试图在不丢失精度的情况下从一个转换为另一个。

为什么此测试未通过以及如何解决?

class FooTest {
    @Test
    void shouldConvertBackToSameInstant() throws DatatypeConfigurationException {
        Instant initialInstant = Instant.now();
        XMLGregorianCalendar xmlGregorianCalendar = DatatypeFactory.newInstance().newXMLGregorianCalendar(String.valueOf(initialInstant));
        Instant convertedInstant = xmlGregorianCalendar.toGregorianCalendar().toInstant();
        assertEquals(initialInstant, convertedInstant);
    }
}
org.opentest4j.AssertionFailedError: 
Expected :2021-03-10T08:34:30.700715078Z
Actual   :2021-03-10T08:34:30.700Z
4

1 回答 1

1

为什么这个测试没有通过?

XMLGregorianCalendar已获得Instant. 是你的转换回来Instant是有损的。您正在GregorianCalendar通过对 的调用转换为.toGregorianCalendar()。AGreogrianCalendar只有毫秒精度,所以这是你失去精度的地方。

如何解决?

就像您String进行第一次转换一样,您可以对相反的转换执行相同的操作:

    Instant convertedInstant = Instant.parse(xmlGregorianCalendar.toString());

现在您的测试通过了(它在我的 Java 9 上通过了)。

结束语

Instant秒精度高达小数点后 9 位(所以纳秒)。XMLGregorianCalendar具有几乎无限的精度。因此,如果您已将 an 转换InstantXMLGregorianCalendar,则您知道它的精度不超过 9 位小数,因此您可以安全地将其转换回来。另一方面,如果您应该从某个地方获得XMLGregorianCalendar更高的精度(十位小数或更多),那么我向您展示的转换将失败并显示DateTimeParseException.

于 2021-03-10T15:53:35.273 回答