如何在Java8 Instant中表示MS-DTYP`DATETIME`?

如何在Java8 Instant中表示MS-DTYP`DATETIME`?,java,c#,time,datetime-conversion,java.time.instant,Java,C#,Time,Datetime Conversion,Java.time.instant,在Microsoft规范中,DATETIME表示为2个32位整数:low和high 参考: FILETIME结构是一个64位的值,表示 从1601年1月1日起,间隔为100纳秒, 协调世界时(UTC)。typedef结构_FILETIME{DWORD dwLowDateTime;DWORD dwHighDateTime;}FILETIME, *最后, *LPF文件时间;dwLowDateTime:一个32位无符号整数,包含文件时间的低位。dwHighDateTime:32位无符号 包含文件时间的

在Microsoft规范中,
DATETIME
表示为2个32位整数:
low
high

参考:

FILETIME结构是一个64位的值,表示 从1601年1月1日起,间隔为100纳秒, 协调世界时(UTC)。typedef结构_FILETIME{DWORD dwLowDateTime;DWORD dwHighDateTime;}FILETIME, *最后, *LPF文件时间;dwLowDateTime:一个32位无符号整数,包含文件时间的低位。dwHighDateTime:32位无符号 包含文件时间的高阶位的整数

例如,这里是长的
130280867040000000

因此,使用

int high = (int)(fullval >> 32);
int low = (int)fullval;
如此之高=
30333378
和低=
552794112


如何将这些计算为Java8即时值

啊,当我像那样把字节一分为二时,我找错了方向

基本上就是说单位是100纳秒

这个时代也有不同的基准时间。因此,您还必须添加偏移量

因此:

    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)

对于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

让我们试着在你的原始值上再打一个勾;它应该增加100纳秒

    long fullval = 130_280_867_040_000_001L;
2013-11-05T00:58:24.000000100Z

的确如此


未来很长一段时间的警告:根据你的报价,微软的整数都是无符号的。Java
long
已签名。因此,在30828年的某个时候,我们将开始得到非常错误的结果。以防万一,如果
long
值为负值,我们应该抛出异常。

从示例值中,您的代码将打印2013-11-05T00:58:24Z。这与我的观点完全一致。看起来你没有转换任何一秒的分数;如果需要的话,我相信这是可以做到的。