从C#日期到Java日期将Long转换为DateTime [英] Convert Long to DateTime from C# Date to Java Date

查看:82
本文介绍了从C#日期到Java日期将Long转换为DateTime的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直试图用Java读取二进制文件,并且该二进制文件是用C#编写的.其中一些数据包含DateTime数据.

I've been trying to read the binary file with Java, and the binary file is written in C#. And some of those data is contain a DateTime data.

将DateTime数据写入文件(二进制)时,将使用C#上的 DateTime.ToBinary(); .

When DateTime data will be written into the file (in binary), it using DateTime.ToBinary(); on C#.

要读取DateTime数据,它将首先使用 BitConverter.ToInt64(byte [],0)从字节转换为长数据,然后使用 DateTime.FromBinary(long).(所有这些都是用C#编写的.)

For reading the DateTime data, it will convert first from bytes into long data, using BitConverter.ToInt64(byte[], 0), and then convert it again from long into DateTime data using DateTime.FromBinary(long). (All of those are written in C#).

假设从字节转换后的长数据为= -8586803256090942249 ,当将其转换为DateTime时,它将返回= 3/17/2018 5:07:56 PM

Let's say the long data after converting from bytes is = -8586803256090942249, and when convert it into DateTime, it will return = 3/17/2018 5:07:56 PM

现在,我正在尝试使用Java读取该二进制文件.为了将字节数据转换为长数据,我使用以下代码: ByteBuffer.wrap(byte []).order(ByteOrder.LITTLE_ENDIAN).getLong().

Now, I'm trying to read that binary file with Java. And for converting the bytes data into long data, I'm using this code : ByteBuffer.wrap(byte[]).order(ByteOrder.LITTLE_ENDIAN).getLong().

它将像C#一样返回确切的长数据值.但是当我尝试使用 Date date = new Date(long)将长数据从Java中的长数据转换为DateTime时,它将返回= Sun May 06 19:04:17 WIB 272097407 .

It will return the exact long data value as C# did. But when I try to convert it from long data into DateTime in Java, using Date date = new Date(long), it will return = Sun May 06 19:04:17 WIB 272097407 instead.

您能帮我解决这个问题的正确方法是什么?Java中C#中的 DateTime.FromBinary()是否有等效项?还是我的代码错了?您的所有答案都很感激.

Can you help me what is the correct solution for this ? Is there any equivalent for DateTime.FromBinary() from C# in Java ? Or is my code wrong ? All of yours answers is really appreciated.

推荐答案

在Java中:

    long fromBytes = -8586803256090942249L;

    // Mask out kind and ticks
    int kind = Math.toIntExact((fromBytes >> 62) & 0x3);
    long ticks = fromBytes & 0x3FFF_FFFF_FFFF_FFFFL;
    LocalDateTime cSharpEpoch = LocalDate.of(1, Month.JANUARY, 1).atStartOfDay();
    // 100 nanosecond units or 10^-7 seconds
    final int unitsPerSecond = 10_000_000;
    long seconds = ticks / unitsPerSecond;
    long nanos = (ticks % unitsPerSecond) * 100;
    LocalDateTime ldt = cSharpEpoch.plusSeconds(seconds).plusNanos(nanos);

    switch (kind) {
    case 0: // Unspecified
    case 2: // Local time
        System.out.println("Result LocalDateTime: " + ldt);
        break;

    case 1: // UTC
        OffsetDateTime utcDateTime = ldt.atOffset(ZoneOffset.UTC);
        System.out.println("Result OffsetDateTime in UTC: " + utcDateTime);
        break;

    default:
        System.out.println("Not a valid DateTimeKind: " + kind);
        break;
    }

输出:

结果LocalDateTime:2018-03-17T10:07:56.383355900

Result LocalDateTime: 2018-03-17T10:07:56.383355900

数字为

64位带符号整数,将2类的Kind属性编码字段和Ticks属性(位于62位字段中).

A 64-bit signed integer that encodes the Kind property in a 2-bit field and the Ticks property in a 62-bit field.

山本哲也是正确的,因为ticks属性表示从一天开始(午夜)0001/01/01开始经过的时间间隔为100纳秒.该类型为0(对于未指定),1(对于UTC)或2(本地时间).所以我要分别掩盖种类和滴答声.

Tetsuya Yamamoto was correct so far as the ticks property denotes number of 100-nanosecond intervals elapsed since 0001/01/01 at start of day (midnight). The kind is either 0 for unspecified, 1 for UTC or 2 for local time. So I am masking the kind and the ticks out separately.

即使您的情况是2(应该是当地时间),似乎时间也确实是UTC.这是印制时间与您期望的印尼西部时间下午5:07:56相符的唯一方法.也许该数字是在时区设置为UTC的计算机上生成的.

Even though the kind is 2 in your case, which should be for local time, it seems that the time is indeed in UTC. It’s the only way that the time printed could agree with your expected 5:07:56 PM Western Indonesian Time. Maybe the number was generated on a computer with its time zone set to UTC.

要获取您所在时区的时间:

To get the time in your time zone:

    ZoneId targetZone = ZoneId.of("Asia/Jakarta");
    ZonedDateTime zdt = ldt.atZone(ZoneOffset.UTC).withZoneSameInstant(targetZone);
    System.out.println("Converted to target time zone: " + zdt);

已转换为目标时区:2018-03-17T17:07:56.383355900 + 07:00 [亚洲/雅加达]

Converted to target time zone: 2018-03-17T17:07:56.383355900+07:00[Asia/Jakarta]

这与您所说的C#方面的观点一致.

This agrees with what you said you got on the C# side.

PS如果可能的话,请避免使用Java中的 Date 类,该类已过时且设计欠佳,许多年前已被

PS Avoid the Date class in Java if you can, it is long outdated and poorly designed and was replaced many years ago now by java.time, the modern Java date and time API (which I am of course using in the above). If you do need a Date for a legacy API that you cannot change or don’t want to change just now, as you already noted in a comment, the conversion is like this:

    Instant inst = ldt.atOffset(ZoneOffset.UTC).toInstant();
    Date date = Date.from(inst);
    System.out.println(date);

在默认时区为Asia/Jakarta的JVM上的输出:

Output on a JVM with default time zone Asia/Jakarta:

2018年3月17日星期六17:07:56 WIB

Sat Mar 17 17:07:56 WIB 2018

致谢:Andreas在一个答案(下面的链接)中解释了64位数字的结构,并提供了指向文档的链接.我从那里带走了他们.

Acknowledgement: Andreas in an answer (link below) explained the structure of the 64 bits number and gave the link to the documentation. I have taken them from there.

链接

  • DateTime.FromBinary(Int64) Method from the .NET documentation
  • Andreas’ answer to a duplicate question

这篇关于从C#日期到Java日期将Long转换为DateTime的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆