将 c# DateTime.Now 转换为二进制
Convert c# DateTime.Now to Binary
我问这个问题是为了学习。
看看我刚刚在wireshark上捕获的这个udp数据包:
(这就是 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;
}
所有操作系统都有两个重要的值:
1) 'epoch'
2) 区间
纪元描述了值所代表的时间间隔。引用 MS 帮助,DateTime.Ticks "represents the number of 100-nanosecond intervals that have elapsed since 12:00:00 midnight, January 1, 0001"。
但我们不是在看 Windows 时间。我们正在查看 NTP 时间。搜索 "NTP message format" 我发现 RFC958 说 "NTP timestamps are represented as a 64-bit fixed-point number, in seconds relative to 0000 UT on 1 January 1900. The integer part is in the first 32 bits and the fraction part in the last 32 bits"
你如何转换?数学。或者查看此处并进行必要的调整:
根据您链接的代码,您有:
UInt64 milliseconds = (intPart * 1000) + ((fractPart * 1000) / 0x100000000L);
DateTime networkDateTime = (new DateTime(1900, 1, 1)).AddMilliseconds((long)milliseconds);
所以你看到这 8 个字节是自 1/1/1900 以来的毫秒数。因此,要生成这样的时间戳,您可以这样做
ulong milliseconds = (ulong)((DateTime.Now() - new DateTime(1900, 1, 1)).TotalMilliseconds);
.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);
上的 MSDN 文档
我问这个问题是为了学习。
看看我刚刚在wireshark上捕获的这个udp数据包:
(这就是 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;
}
所有操作系统都有两个重要的值: 1) 'epoch' 2) 区间
纪元描述了值所代表的时间间隔。引用 MS 帮助,DateTime.Ticks "represents the number of 100-nanosecond intervals that have elapsed since 12:00:00 midnight, January 1, 0001"。
但我们不是在看 Windows 时间。我们正在查看 NTP 时间。搜索 "NTP message format" 我发现 RFC958 说 "NTP timestamps are represented as a 64-bit fixed-point number, in seconds relative to 0000 UT on 1 January 1900. The integer part is in the first 32 bits and the fraction part in the last 32 bits"
你如何转换?数学。或者查看此处并进行必要的调整:
根据您链接的代码,您有:
UInt64 milliseconds = (intPart * 1000) + ((fractPart * 1000) / 0x100000000L);
DateTime networkDateTime = (new DateTime(1900, 1, 1)).AddMilliseconds((long)milliseconds);
所以你看到这 8 个字节是自 1/1/1900 以来的毫秒数。因此,要生成这样的时间戳,您可以这样做
ulong milliseconds = (ulong)((DateTime.Now() - new DateTime(1900, 1, 1)).TotalMilliseconds);
.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);
上的 MSDN 文档