【问题标题】:How do you represent MS-DTYP `DATETIME` in Java 8 Instant?你如何在 Java 8 Instant 中表示 MS-DTYP `DATETIME`?
【发布时间】:2019-12-11 17:37:53
【问题描述】:
在 Microsoft 规范中,DATETIME 表示为 2 个 32 位整数:low 和 high
参考:https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/cca27429-5689-4a16-b2b4-9325d93e4ba2
FILETIME 结构是一个 64 位值,表示
自 1601 年 1 月 1 日以来经过的 100 纳秒间隔,
协调世界时 (UTC)。 typedef 结构 _FILETIME { DWORD
dwLowDateTime; DWORD dwHighDateTime;文件时间,
*P文件时间,
*LP文件时间; dwLowDateTime:一个 32 位无符号整数,包含文件时间的低位。 dwHighDateTime:32 位无符号
包含文件时间高位的整数。
例如,这里是长130280867040000000
所以高低是用计算的
int high = (int)(fullval >> 32);
int low = (int)fullval;
这么高 = 30333378
和低 = 552794112
如何将这些计算为 Java 8 Instant?
【问题讨论】:
标签:
java
c#
time
datetime-conversion
java.time.instant
【解决方案1】:
啊,当我像这样将字节分成两半时,我叫错了树。
基本上它只是说单位是 100ns。
Epoch 也有不同的基准时间。因此,您还必须添加偏移量。
原来如此:
private static final long DATETIME_EPOCH_DIFF_1601;
static {
LocalDateTime time32Epoch1601 = LocalDateTime.of(1601, Month.JANUARY, 1, 0, 0);
Instant instant = time32Epoch1601.atZone(ZoneOffset.UTC).toInstant();
DATETIME_EPOCH_DIFF_1601 = (instant.toEpochMilli() - Instant.EPOCH.toEpochMilli()) / 1000;
}
Instant answer = Instant.ofEpochSecond(fullval / 10000000 + DATETIME_EPOCH_DIFF_1601)
【解决方案2】:
要以 1 秒的精度进行转换,您自己的答案就可以了。如果您还需要转换秒的分数,这是一种方法。
Instant msFiletimeEpoch = Instant.parse("1601-01-01T00:00:00Z");
// a tick is 100 nanoseconds
int nanosPerTick = 100;
long ticksPerSecond = TimeUnit.SECONDS.toNanos(1) / nanosPerTick;
long fullval = 130_280_867_040_000_000L;
long seconds = fullval / ticksPerSecond;
long nanos = fullval % ticksPerSecond * nanosPerTick;
Instant answer = msFiletimeEpoch.plusSeconds(seconds).plusNanos(nanos);
System.out.println(answer);
输出是:
2013-11-05T00:58:24Z
让我们尝试在您的原始值上再增加 1 个刻度;它应该增加 100 纳秒。
long fullval = 130_280_867_040_000_001L;
2013-11-05T00:58:24.000000100Z
原来如此。
对于非常遥远的未来日期的警告:根据您的报价,Microsoft 整数都是无符号的。 Java long 已签名。所以在 30828 年的某个时候,我们将开始得到非常错误的结果。以防万一我们应该在long 值为负时抛出异常。