Java:将无符号8字节时间戳转换为微秒级的精确日期
我写的代码读取一个数据文件,该文件包含一个Unix时间戳,该时间戳存储在一个无符号的8字节整数中,精度为微秒。我试图把这个无符号的8字节整数转换成一个人类可读的精确到微秒的日期Java:将无符号8字节时间戳转换为微秒级的精确日期,java,unix,Java,Unix,我写的代码读取一个数据文件,该文件包含一个Unix时间戳,该时间戳存储在一个无符号的8字节整数中,精度为微秒。我试图把这个无符号的8字节整数转换成一个人类可读的精确到微秒的日期 我的问题是,鉴于Java不支持无符号long,我正努力思考如何实际实现它。不幸的是,我必须用Java完全实现这一点,我不能牺牲时间戳的准确性。Java既不支持无符号整数,也不支持8字节整数。整数的固定长度为4字节=32位。但从JDK 8开始,您可以对long和int应用无符号算术运算(转到(或整数)javadoc页面并搜
我的问题是,鉴于Java不支持无符号long,我正努力思考如何实际实现它。不幸的是,我必须用Java完全实现这一点,我不能牺牲时间戳的准确性。Java既不支持无符号整数,也不支持8字节整数。整数的固定长度为4字节=32位。但从JDK 8开始,您可以对long和int应用无符号算术运算(转到(或整数)javadoc页面并搜索“unsigned”)。Endianness 您没有提供的一条重要信息是二进制数的字节结束度。我将假设它是小端点,就像在大多数系统中一样 提取秒和纳秒 Java 8中的
Instant
除了纳秒外,还支持将时间指定为长的时间(63位,不计算符号)
所以好消息是,我们可以打印所有可以以纳秒形式存储在8字节无符号整数中的日期
由于Java只有一个有符号长的
8字节的原始数据类型,我们需要小心不要处理最高有效位为1作为负2的补码的情况
可能的解决办法
因此,我们可以显示的最新日期,由FF FF FF FF FF
表示,对应于字符串2554-07-22 01:34:33.709551615
00 00
将是历元。您能否提供一个示例记录,从该文件中提供分辨率。我知道,但二进制数据文件是用C生成的,它支持这两种格式(无符号长-长)。我只是想弄明白如何将它转换成Java中可用的东西。然后,对其应用无符号算术运算。由于您需要微秒精度,long将不再以1作为其第一位,因此您可以继续执行有符号行为(因为第一个负数在二进制表示中为1000…0,在十进制表示中等于-10^31-1)。
// constants
long nanosPerSecond = 1000_000_000L;
String pattern = "yyyy-MM-dd HH:mm:ss.n";
// assuming the bytes in the file are in little endian byte order
byte[] arr = Files.readAllBytes(path);
// transform to big endian (required by BigInteger)
ArrayUtils.reverse(arr);
// always positive
BigInteger number = new BigInteger(1, arr);
// get seconds since epoch and nano adjustment
long nanoAdjustment = number.mod(BigInteger.valueOf(nanosPerSecond))
.longValueExact();
long epochSecond = number.divide(BigInteger.valueOf(nanosPerSecond))
.longValueExact();
Instant instant = Instant.ofEpochSecond(epochSecond, nanoAdjustment);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern).withZone(ZoneId.systemDefault());
System.out.println(formatter.format(instant));