Tono Nam
Tono Nam

Reputation: 36050

Convert c# DateTime.Now to Binary

I am asking this question for learning purposes.

Take a look at this udp packet I just captured on wireshark:

enter image description here

(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.

Edit

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?

Solution

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

Answers (3)

Pradeep Kumar
Pradeep Kumar

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

adjan
adjan

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

Ray Fischer
Ray Fischer

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

Related Questions