1 回答
TA贡献1793条经验 获得超6个赞
java.time
使用解释中的示例:
时间戳 - C50204EC EC42EE92 相当于 2004 年 9 月 27 日 03:18:04.922896299 UTC。
Instant epoch = OffsetDateTime.of(1900, 1, 1, 0, 0, 0, 0, ZoneOffset.UTC).toInstant();
BigInteger timeStamp = new BigInteger("C50204ECEC42EE92", 16);
// To get the whole part and the fraction right, divide by 2^32
double secondsSince1900 = timeStamp.doubleValue() / 0x1_0000_0000L;
// Convert seconds to nanos by multiplying by 1 000 000 000
Instant converted = epoch.plusNanos(Math.round(secondsSince1900 * 1_000_000_000L));
System.out.println(converted);
输出是:
2004-09-27T03:18:04.922896384Z
它关闭了 85 纳秒。可能更好的浮点运算可以做得更好。编辑:由于原始时间戳的分辨率为 2^-32 秒,因此不可避免地会损失一点精度,这是 . 的纳秒(10^-9 秒)分辨率的 4 倍多Instant。
Calendar您尝试使用的类总是设计得很差,现在已经过时了。相反,我按照评论中建议的那样做,我正在使用 java.time,现代 Java 日期和时间 API。编辑:为了比较Calendar具有毫秒分辨率,因此充其量只会给您带来精度损失。
编辑:更精确的数学
我不能让 85 纳秒成为现实。这是一个尽可能保持精度并给出预期结果的版本:
BigDecimal timeStamp = new BigDecimal(new BigInteger("C50204ECEC42EE92", 16));
// To get the whole part and the fraction right, divide by 2^32
BigDecimal bit32 = new BigDecimal(0x1_0000_0000L);
BigDecimal secondsSince1900 = timeStamp.divide(bit32);
// Convert seconds to nanos by multiplying by 1 000 000 000; round to long
long nanosSince1900 = secondsSince1900.multiply(new BigDecimal(TimeUnit.SECONDS.toNanos(1)))
.setScale(0, RoundingMode.HALF_UP)
.longValueExact();
Instant converted = epoch.plusNanos(nanosSince1900);
2004-09-27T03:18:04.922896300Z
1纳米太多了?这是因为我在调用setScale. 相反,如果我截断(使用RoundingMode.FLOOR),我会从解释中得到确切的结果。所以我的版本不会比他们的更精确。
添加回答
举报