Java:将无符号8字节时间戳转换为微秒准确日期

时间:2017-11-07 14:12:44

标签: java unix

我正在编写一个读取数据文件的代码,该文件包含存储在无符号8字节int中的Unix时间戳,其精度为微秒级。我正在尝试将这个无符号的8字节int转换为精确到微秒的人类可读日期。

我的问题是,鉴于Java不支持unsigned longs,我正在努力思考如何实际实现它。不幸的是,我必须在Java中完全实现这一点,我不能牺牲时间戳的准确性。

3 个答案:

答案 0 :(得分:2)

字节序

您未提供的一条重要信息是二进制数的字节字节序。我会假设它是 little endian ,就像大多数系统一样。

提取秒和纳秒

Java 8中的

Instant支持以纪元为单位指定的时间为long(63位,不计算符号),以及纳秒数。

所以好消息是我们能够在8字节无符号整数中打印所有可以存储为纳秒的日期。

由于Java只有signed long 8字节的原始数据类型,因此我们需要注意不要处理最高有效位为1作为负2的补码数的情况。

可能的解决方案

// 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));

因此,FF FF FF FF FF FF FF FF代表的最新日期对应字符串2554-07-22 01:34:33.709551615

00 00 00 00 00 00 00 00将成为时代。

答案 1 :(得分:0)

java 9中的一些新功能,本文也可能有所帮助。

Current time in microseconds in java

答案 2 :(得分:0)

Java既不支持无符号整数也不支持8字节整数。整数具有4字节= 32位的固定长度。但是你可以在JDK 8(转到Long(或整数)javadoc页面并搜索“unsigned”)后对long,int两者应用无符号算术运算。