I have a .NET INT64 value(result from DateTime.toBinary()) as -8586018589234214115 from JSON response. How do I convert that value into valid java Date?
Thanks, Sandeep
I have a .NET INT64 value(result from DateTime.toBinary()) as -8586018589234214115 from JSON response. How do I convert that value into valid java Date?
Thanks, Sandeep
-8586018589234214115
) to DateTime
object (say, theDateTimeObject
) using DateTime.FromBinary(Int64)
theDateTimeObject
to DateTimeOffset
as DateTimeOffset dateTime = DateTime.SpecifyKind(theDateTimeObject, DateTimeKind.Utc)
DateTimeOffset.ToUnixTimeMilliseconds
into java.time.Instant#ofEpochMilli
to get an object of Instant
which you can convert to other date-time types.Demo:
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);
}
}
Output:
2020-12-15T23:31:35.347Z
2020-12-15T23:31:35.347Z
2020-12-15T23:31:35.347Z
2020-12-15T23:31:35.347
Note that the date-time API of java.util
and their formatting API, SimpleDateFormat
are outdated and error-prone. It is recommended to stop using them completely and switch to the modern date-time API. Learn more about the modern date-time API at Trail: Date Time.
Note: For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7.
If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.
The Binary value is:
A 64-bit signed integer that encodes the
Kind
property in a 2-bit field and theTicks
property in a 62-bit field.
Since the Kind
property is useless to us, we can simply mask it out using value & ((1L << 62) - 1)
to get the Ticks
property.
A Tick is:
A single tick represents one hundred nanoseconds or one ten-millionth of a second. There are
10,000
ticks in a millisecond (seeTicksPerMillisecond
) and 10 million ticks in a second.The value of this property represents the number of 100-nanosecond intervals that have elapsed since
12:00:00 midnight, January 1, 0001
.
Which means we can convert like this:
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);
}
Test
long dateTimeBinary = -8586018589234214115L;
System.out.println(dateTimeBinary + " -> " + fromDateTimeBinary(dateTimeBinary));
Output
-8586018589234214115 -> 2020-09-10T14:26:02.056169300Z
Warning: The -8586018589234214115
value specifies a Kind
value of 2=Local
(the time represented is local time), but we don't know what the "local" time zone was, so the result of converting to UTC may be wrong.
We can also convert the other way:
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;
}
Test
Instant now = Instant.now();
System.out.println(now + " -> " + toDateTimeBinary(now));
Output
2020-12-16T01:51:17.066065200Z -> 5249122821198048556
See also: Java 8 Time - Equivalent of .NET DateTime.MaxValue.Ticks
It would be better to convert to unix time .net DateTimeOffset.ToUnixTimeMilliseconds and then use the java.util.Date java constructor to parse it