您如何在 Java 8 Instant 中表示 MS-DTYP `DATETIME`?
How do you represent MS-DTYP `DATETIME` in Java 8 Instant?
在 Microsoft 规范中,DATETIME
表示为 2 个 32 位整数:low
和 high
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.
例如这里是长130280867040000000
因此计算出的最高价和最低价是
int high = (int)(fullval >> 32);
int low = (int)fullval;
这么高=30333378
低 = 552794112
如何将这些计算为 Java 8 Instant?
啊,当我像那样将字节分成两半时,我找错了树。
基本上就是说单位是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)
要以 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 整数都是无符号的。 A Java long
被签名。所以在 30828 年的某个时候,我们将开始得到非常错误的结果。以防万一我们应该在 long
值为负数时抛出异常。
在 Microsoft 规范中,DATETIME
表示为 2 个 32 位整数:low
和 high
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.
例如这里是长130280867040000000
因此计算出的最高价和最低价是
int high = (int)(fullval >> 32);
int low = (int)fullval;
这么高=30333378
低 = 552794112
如何将这些计算为 Java 8 Instant?
啊,当我像那样将字节分成两半时,我找错了树。
基本上就是说单位是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)
要以 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 整数都是无符号的。 A Java long
被签名。所以在 30828 年的某个时候,我们将开始得到非常错误的结果。以防万一我们应该在 long
值为负数时抛出异常。