将c#DateTime.Now转换为二进制

时间:2017-02-16 01:36:03

标签: c# datetime binary utc ntp

我问这个问题是为了学习目的。

看看我刚刚在wireshark上捕获的这个udp数据包:

enter image description here

(这就是time.windows.com回复以便给我的电脑留出时间)

无论如何,我的问题是关于突出显示的最后8个字节。请注意Wireshark如何正确解析日期。 time.windows.com是如何生成这8个字节的?如何从DateTime.NowUtc转到wireshark将解析为正确日期的内容?

我试过了:

long dateTime = DateTime.Now.ToFileTimeUtc();
var bytes = BitConverter.GetBytes(dateTime);

但是当我发送那8个字节时,wireshark会将其解析为" 4/15/1998 11:27:52 AM"离开了。

我自1970年以来也尝试过添加毫秒,但仍然显示错误的日期。

修改

以下是有关如何解析响应的示例: http://davidnakoko.com/2013/07/c-get-network-time-from-ntp-server/

但我在哪里可以找到有关如何创建它的示例?

解决方案

感谢@adjan和@RayFischer回答我提出了一个解决方案。这是:

    public static byte[] ConvertToNtp(DateTime datetime)
    {
        ulong milliseconds = (ulong)((datetime - new DateTime(1900, 1, 1)).TotalMilliseconds);

        ulong intpart = 0, fractpart = 0;
        var ntpData = new byte[8];

        intpart = milliseconds / 1000;
        fractpart = ((milliseconds % 1000) * 0x100000000L) / 1000;

        //Debug.WriteLine("intpart:      " + intpart);
        //Debug.WriteLine("fractpart:    " + fractpart);
        //Debug.WriteLine("milliseconds: " + milliseconds);

        var temp = intpart;
        for (var i = 3; i >= 0; i--)
        {
            ntpData[i] = (byte)(temp % 256);
            temp = temp / 256;
        }

        temp = fractpart;
        for (var i = 7; i >= 4; i--)
        {
            ntpData[i] = (byte)(temp % 256);
            temp = temp / 256;
        }
        return ntpData;
    }

3 个答案:

答案 0 :(得分:1)

对于所有操作系统,有两个重要的值: 1)'时代' 2)间隔

该纪元描述了该值所代表的时间间隔。要引用MS帮助,DateTime.Ticks"表示自0001年1月1日午夜12:00:00起经过的100纳秒间隔的数量。

但我们并没有关注Windows时间。我们正在查看NTP时间。搜索" NTP消息格式"我发现RFC958表示" NTP时间戳表示为64位定点数,相对于1900年1月1日的0000 UT,以秒为单位。整数部分位于前32位,小数部分位于最后32位"

你如何转换?数学。或者查看此处并进行必要的调整: How to convert NTP time to Unix Epoch time in C language (Linux)

答案 1 :(得分:1)

根据您链接的代码,您有:

UInt64 milliseconds = (intPart * 1000) + ((fractPart * 1000) / 0x100000000L);

DateTime networkDateTime = (new DateTime(1900, 1, 1)).AddMilliseconds((long)milliseconds);

所以你看到8字节是自19/1年1月1日以来的毫秒数。因此,要生成这样的时间戳,您可以执行

ulong milliseconds = (ulong)((DateTime.Now() - new DateTime(1900, 1, 1)).TotalMilliseconds);

答案 2 :(得分:0)

.Net提供了将DateTime转换为64位二进制表示并返回DateTime的方法。

DateTime localDate = new DateTime(2010, 3, 14, 2, 30, 0, DateTimeKind.Local);
long binLocal = localDate.ToBinary();
DateTime localDate2 = DateTime.FromBinary(binLocal);

请参阅DateTime.ToBinary

上的MSDN文档