在不损失精度的情况下从 Instant 转换为 XMLGregorianCalendar,反之亦然
Converting from Instant to XMLGregorianCalendar and vice-versa without losing precision
使用 java.time.Instant
和 javax.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
为什么这个测试没有通过?
您的 XMLGregorianCalendar
已获得 Instant
的全部精度。有损的是您转换回 Instant
。您正在通过调用 .toGregorianCalendar()
转换为 GregorianCalendar
。 GreogrianCalendar
只有毫秒精度,所以这就是你失去精度的地方。
如何解决?
正如您对第一次转化进行 String
一样,您可以对相反的转化进行同样的操作:
Instant convertedInstant = Instant.parse(xmlGregorianCalendar.toString());
现在你的测试通过了(它在我的 Java 9 上通过了)。
结束语
Instant
在秒(即纳秒)上的精度高达 9 位小数。 XMLGregorianCalendar
的精度几乎是无限的。因此,如果您已将 Instant
转换为 XMLGregorianCalendar
,您就会知道它的精度不超过 9 位小数,因此您可以安全地将其转换回来。另一方面,如果您应该从某个地方获得精度更高(10 位小数或更多)的 XMLGregorianCalendar
,则我向您展示的转换将失败并显示 DateTimeParseException
.
使用 java.time.Instant
和 javax.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
为什么这个测试没有通过?
您的 XMLGregorianCalendar
已获得 Instant
的全部精度。有损的是您转换回 Instant
。您正在通过调用 .toGregorianCalendar()
转换为 GregorianCalendar
。 GreogrianCalendar
只有毫秒精度,所以这就是你失去精度的地方。
如何解决?
正如您对第一次转化进行 String
一样,您可以对相反的转化进行同样的操作:
Instant convertedInstant = Instant.parse(xmlGregorianCalendar.toString());
现在你的测试通过了(它在我的 Java 9 上通过了)。
结束语
Instant
在秒(即纳秒)上的精度高达 9 位小数。 XMLGregorianCalendar
的精度几乎是无限的。因此,如果您已将 Instant
转换为 XMLGregorianCalendar
,您就会知道它的精度不超过 9 位小数,因此您可以安全地将其转换回来。另一方面,如果您应该从某个地方获得精度更高(10 位小数或更多)的 XMLGregorianCalendar
,则我向您展示的转换将失败并显示 DateTimeParseException
.