我有一个来自JSON响应的.NET INT64值(DateTime.toBinary((的结果(,为-8586018589234115。如何将该值转换为有效的java日期?
谢谢,Sandeep
二进制值为:
一个64位带符号整数,它将
Kind
属性编码在2位字段中,将Ticks
属性编码在62位字段中。
由于Kind
属性对我们来说是无用的,我们可以简单地使用value & ((1L << 62) - 1)
来屏蔽它以获得Ticks
属性。
勾号是:
一个刻度表示一百纳秒或一千万分之一秒。一毫秒内有
10,000
个刻度(请参见TicksPerMillisecond
(,一秒钟内有1000万个刻度。此属性的值表示自
12:00:00 midnight, January 1, 0001
以来经过的100纳秒间隔数。
这意味着我们可以这样转换:
private static final long NANOS_PER_TICK = 100L;
private static final long TICKS_PER_SECOND = 1000000000L / NANOS_PER_TICK;
private static final long YEAR_OFFSET = -62135596800L;
// Seconds from Epoch to 12:00:00 midnight, January 1, 0001, calculated using:
// OffsetDateTime.of(1, 1, 1, 0, 0, 0, 0, ZoneOffset.UTC).toEpochSecond()
static Instant fromDateTimeBinary(long value) {
long ticks = value & ((1L << 62) - 1);
return Instant.ofEpochSecond(ticks / TICKS_PER_SECOND + YEAR_OFFSET,
ticks % TICKS_PER_SECOND * NANOS_PER_TICK);
}
测试
long dateTimeBinary = -8586018589234214115L;
System.out.println(dateTimeBinary + " -> " + fromDateTimeBinary(dateTimeBinary));
输出
-8586018589234214115 -> 2020-09-10T14:26:02.056169300Z
警告:-8586018589234214115
值指定2=Local
的Kind
值(表示的时间为本地时间(,但我们不知道;本地";时区为,因此转换为UTC的结果可能是错误的。
我们也可以用另一种方式转换:
static long toDateTimeBinary(Instant dateTime) {
long ticks = (dateTime.getEpochSecond() - YEAR_OFFSET) * TICKS_PER_SECOND
+ dateTime.getNano() / NANOS_PER_TICK;
return (0x01L/*Kind=UTC*/ << 62) | ticks;
}
测试
Instant now = Instant.now();
System.out.println(now + " -> " + toDateTimeBinary(now));
输出
2020-12-16T01:51:17.066065200Z -> 5249122821198048556
另请参阅:Java 8时间-等效于.NET DateTime.MaxValue.Ticks
- 使用
DateTime.FromBinary(Int64)
将值(例如,-8586018589234214115
(转换为DateTime
对象(例如theDateTimeObject
( - 将
theDateTimeObject
转换为DateTimeOffset
作为DateTimeOffset dateTime = DateTime.SpecifyKind(theDateTimeObject, DateTimeKind.Utc)
- 传递
DateTimeOffset.ToUnixTimeMilliseconds
的值转换为java.time.Instant#ofEpochMilli
以获得Instant
的对象,您可以将其转换为其他日期-时间类型
演示:
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
public class Main {
public static void main(String[] args) {
long millis = 1608075095347L;
Instant instant = Instant.ofEpochMilli(millis);
System.out.println(instant);
// You can derive other date-time objects from Instant e.g.
OffsetDateTime odt = instant.atOffset(ZoneOffset.UTC);
ZonedDateTime zdt = instant.atZone(ZoneOffset.UTC);
LocalDateTime ldt = odt.toLocalDateTime();
System.out.println(odt);
System.out.println(zdt);
System.out.println(ldt);
}
}
输出:
2020-12-15T23:31:35.347Z
2020-12-15T23:31:35.347Z
2020-12-15T23:31:35.347Z
2020-12-15T23:31:35.347
请注意,java.util
的日期时间API及其格式API、SimpleDateFormat
已过时且为错误产品。建议完全停止使用它们,并切换到现代日期时间API。有关现代日期时间API的更多信息,请访问跟踪:日期时间。
注意:无论出于何种原因,如果您必须坚持使用Java 6或Java 7,您可以使用ThreeTen Backport将Java.time的大部分功能向后移植到Java 6&7.
如果您正在为Android项目工作,并且您的Android API级别仍然不符合Java-8,请检查通过desugaring和如何在Android项目中使用ThreeTenABP提供的Java 8+API。
最好转换为unix time.net DateTimeOffset.ToUnixTimeMilliseconds,然后使用java.util.Date java构造函数解析它