Reputation: 36050
I am asking this question for learning purposes.
Take a look at this udp packet I just captured on wireshark:
(That is what time.windows.com replies in order to give the time to my computer)
Anyways my question is regarding the last 8 bytes that are highlighted. Note how Wireshark parses the date correctly. How did time.windows.com generated those 8 bytes? How can I go from DateTime.NowUtc
to something wireshark will parse as the correct date?
I have tried:
long dateTime = DateTime.Now.ToFileTimeUtc();
var bytes = BitConverter.GetBytes(dateTime);
but when I send those 8 bytes wireshark parses that date as "4/15/1998 11:27:52 AM" which is way off.
I have also tried adding milliseconds since 1970 but that still shows an incorrect date.
Here is example on how to parse the response: http://davidnakoko.com/2013/07/c-get-network-time-from-ntp-server/
But where can I find an example on how to create it?
Thanks to @adjan and @RayFischer answer I came up with a solution. Here it is:
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;
}
Upvotes: 2
Views: 5956
Reputation: 1349
.Net provides methods to convert DateTime to 64 bit binary representation and back to DateTime.
DateTime localDate = new DateTime(2010, 3, 14, 2, 30, 0, DateTimeKind.Local);
long binLocal = localDate.ToBinary();
DateTime localDate2 = DateTime.FromBinary(binLocal);
Refer to the MSDN documentation on DateTime.ToBinary
Upvotes: 3
Reputation: 13684
From the code you have linked you have:
UInt64 milliseconds = (intPart * 1000) + ((fractPart * 1000) / 0x100000000L);
DateTime networkDateTime = (new DateTime(1900, 1, 1)).AddMilliseconds((long)milliseconds);
So you see the 8 bytes are the milliseconds since 1/1/1900. Thus, to generate such a timestamp, you can do
ulong milliseconds = (ulong)((DateTime.Now() - new DateTime(1900, 1, 1)).TotalMilliseconds);
Upvotes: 1
Reputation: 996
With all operating systems there are two important values: 1) The 'epoch' 2) The interval
The epoch describes the interval in time that the value represents. To quote from the MS Help, DateTime.Ticks "represents the number of 100-nanosecond intervals that have elapsed since 12:00:00 midnight, January 1, 0001".
But we're not looking at a Windows time. We're looking at an NTP time. Searching for "NTP message format" I find RFC958 which says that "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"
How do you convert? Math. Or look here and make the needed adjustments: How to convert NTP time to Unix Epoch time in C language (Linux)
Upvotes: 2