How to convert .NET DateTime.toBinary() to java date [duplicate]

北城余情 提交于 2021-01-07 06:31:11

问题


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


回答1:


  1. Convert the value (e.g. -8586018589234214115) to DateTime object (say, theDateTimeObject) using DateTime.FromBinary(Int64)
  2. Convert theDateTimeObject to DateTimeOffset as DateTimeOffset dateTime = DateTime.SpecifyKind(theDateTimeObject, DateTimeKind.Utc)
  3. Pass the value of 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.




回答2:


The Binary value is:

A 64-bit signed integer that encodes the Kind property in a 2-bit field and the Ticks 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 (see TicksPerMillisecond) 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




回答3:


It would be better to convert to unix time .net DateTimeOffset.ToUnixTimeMilliseconds and then use the java.util.Date java constructor to parse it



来源:https://stackoverflow.com/questions/65315060/how-to-convert-net-datetime-tobinary-to-java-date

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