【问题标题】: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)
    

    【讨论】:

    • 根据您的示例值,您的代码将打印 2013-11-05T00:58:24Z。这与SiliSoftware Date format converter 完全一致。看来您没有转换任何秒数;如果需要,我相信可以做到。
    【解决方案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 值为负时抛出异常。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-12-16
      • 2014-05-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多