How do you represent MS-DTYP `DATETIME` in Java 8 Instant?

匆匆过客 提交于 2020-06-23 08:32:27

问题


In the Microsoft Spec, DATETIME is represented as 2 32-bit integers: low and high

Reference: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/cca27429-5689-4a16-b2b4-9325d93e4ba2

The FILETIME structure is a 64-bit value that represents the number of 100-nanosecond intervals that have elapsed since January 1, 1601, Coordinated Universal Time (UTC). typedef struct _FILETIME { DWORD dwLowDateTime; DWORD dwHighDateTime; } FILETIME, *PFILETIME, *LPFILETIME; dwLowDateTime: A 32-bit unsigned integer that contains the low-order bits of the file time. dwHighDateTime: A 32-bit unsigned integer that contains the high-order bits of the file time.

For example, here is the long 130280867040000000

So the the high and low computed with

int high = (int)(fullval >> 32);
int low = (int)fullval;

so high = 30333378 and low = 552794112

How do I compute these to a Java 8 Instant?


回答1:


For converting with 1 second precision your own answer is just fine. In case you also need to convert the fraction of second, here’s one way to do that.

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

Output is:

2013-11-05T00:58:24Z

Let’s try to put 1 more tick on your oroginal value; it should add 100 nanoseconds.

    long fullval = 130_280_867_040_000_001L;

2013-11-05T00:58:24.000000100Z

So so it does.

Caveat for very far future dates: According to your quote the Microsoft integers are both unsigned. A Java long is signed. So some time in year 30828 we will start getting results that are very wrong. Just in case we ought to throw an exception if the long value is negative.




回答2:


Ah I was barking up the wrong tree when I split the bytes in half like that.

Basically it's just saying that the units are in 100ns.

And the Epoch has a different base time too. So you have to add the offset as well.

So it is:

    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)


来源:https://stackoverflow.com/questions/59291268/how-do-you-represent-ms-dtyp-datetime-in-java-8-instant

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!