我觉得这个问题已经被问到了这个问题,但我对结果仍然没有信心。
我有一个xsd:duration会给我一个以年,月,日和秒描述的期望到期时间。我可以使用duration.getYears()
或duration.getMonths()
收集这些部分的整数值。
因为我选择的数据库是Cassandra,所以我想利用TTL选项,它会在指定的秒数后自动使插入的行到期。
关键部分是从xsd:duration到一个整数/长秒值,它尊重格里高利历(从现在开始的1个月不仅仅是30.41天,而是31)。
目前,我正在使用以下代码:
LocalDateTime then = LocalDateTime.now().plusYears(duration.getYears()).plusMonths(duration.getMonths()).plusDays(duration.getDays()).plusHours(duration.getHours()).plusMinutes(duration.getMinutes()).plusSeconds(duration.getSeconds());
long ttlMillis = then.toInstant(ZoneOffset.UTC).toEpochMilli() - Instant.now().toEpochMilli();
有更快/更清洁的方法吗?
我也不确定是否应该担心持续时间过长...我的特定用例不会要求任何大于2年的任何用途。
答案 0 :(得分:3)
所有人的信息说明:
您所说的是javax.xml.datatype.Duration
,而不是java.time.Duration
。
a)有没有更快的方法(使用Java-8)?很难。负责Java-8中新的日期和时间库的JSR-310团队的设计人员并不关心JDK中现有XML类的桥梁。因此,没有直接的方法可以将xml-duration转换为任何类型的JSR-310持续时间。
请记住,JSR-310类Period
(状态由年,月和日组成)和Duration
(状态由秒和纳秒组成)并非真正设计用于表示xml持续时间(在代码中有更多单位)。所以我怀疑未来是否可能在JSR-310和XML之间看到一个定义良好的桥梁(可能仅在毫秒基础上?)。 JSR-310和XML中的符号处理也完全不同。因此,如果您在xml-duration中有负号,请务必谨慎。
b)是否有更简洁的方法(使用Java-8)?是的,有点。 要考虑的一件事是:我会将时钟作为实际时刻的时间源仅使用一次,而不是使用时间源的两倍。这个(非常)小改进的例子:
Instant now = Instant.now();
LocalDateTime start = now.atOffset(ZoneOffset.UTC).toLocalDateTime();
LocalDateTime end =
start.plusYears(duration.getYears())
.plusMonths(duration.getMonths())
.plusDays(duration.getDays())
.plusHours(duration.getHours())
.plusMinutes(duration.getMinutes())
.plusSeconds(duration.getSeconds());
long deltaInMillis = end.toInstant(ZoneOffset.UTC).toEpochMilli() - now.toEpochMilli();
要考虑的第二件事: xml-duration类旨在与java.util.Date
进行互操作。所以你也有这个简短的选择:
Date start = new Date();
long deltaInMillis = duration.getTimeInMillis(start);
这种替代方案不仅要短得多,而且可能更精确,因为它考虑了毫秒部分。根据{{3}},如果你有长期的持续时间项目(超出int的范围),你应该只担心正确性。另一个主题是与任何隐藏时区计算的关系。我没有在文档中看到任何提示,所以这可能是唯一让你担心的项目(当地时区?或UTC? - 未经测试)。
c)为什么要担心持续时间过长?即使你的持续时间比我们说的某些世纪可能超过历史格里高利历的有效期限还要大,你应该记住xml -duration只使用proleptic格里高利历,而不是历史日历。并且LocalDateTime
也使用相同的预感格里高利历。如果如此大的持续时间与任何真实数据相关,则是另一个好问题。