title: Converting between NTP and C# DateTime
body: <p>I use the following code to convert between NTP and a C# DateTime. I think the forward corversion is correct, but backwards is wrong.</p>
  
  <p>See the following code to convert 8 bytes into a DatTime:</p>
  
  <h2>Convert NTP to DateTime</h2>
  
  <pre><code>public static ulong GetMilliSeconds(byte[] ntpTime)
  {
      ulong intpart = 0, fractpart = 0;
  
      for (var i = 0; i &lt;= 3; i++)
          intpart = 256 * intpart + ntpTime[i];
      for (var i = 4; i &lt;= 7; i++)
          fractpart = 256 * fractpart + ntpTime[i];
  
      var milliseconds = intpart * 1000 + ((fractpart * 1000) / 0x100000000L);
  
      Debug.WriteLine("intpart:      " + intpart);
      Debug.WriteLine("fractpart:    " + fractpart);
      Debug.WriteLine("milliseconds: " + milliseconds);
      return milliseconds;
  }
  
  public static DateTime ConvertToDateTime(byte[] ntpTime)
  {
      var span = TimeSpan.FromMilliseconds(GetMilliSeconds(ntpTime));
      var time = new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc);
      time += span;
      return time;
  }
  </code></pre>
  
  <h2>Convert from DateTime to NTP</h2>
  
  <pre><code>public static byte[] ConvertToNtp(ulong milliseconds)
  {
      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 &gt;= 0; i--)
      {
          ntpData[i] = (byte)(temp % 256);
          temp = temp / 256;
      }
  
      temp = fractpart;
      for (var i = 7; i &gt;= 4; i--)
      {
          ntpData[i] = (byte)(temp % 256);
          temp = temp / 256;
      }
      return ntpData;
  }
  </code></pre>
  
  <p>The following input produces the output:</p>
  
  <pre><code>bytes = { 131, 170, 126, 128,
             46, 197, 205, 234 }
  
  var ms = GetMilliSeconds(bytes );
  var ntp = ConvertToNtp(ms)
  
  //GetMilliSeconds output
  milliseconds: 2208988800182
  intpart:      2208988800
  fractpart:    784715242
  
  //ConvertToNtp output
  milliseconds: 2208988800182
  intpart:      2208988800
  fractpart:    781684047
  </code></pre>
  
  <p>Notice that the conversion from milliseconds to fractional part is wrong. Why?</p>
  
  <h2>Update:</h2>
  
  <p>As Jonathan S. points out - it's loss of fraction. So instead of converting back and forth, I want to manipulate with the NTP timestamp directly. More specific, add milliseconds to it. I would assume the following function would do just that, but I'm having a hard time validating it. I am very unsure about the fraction-part.</p>
  
  <pre><code>public static void AddMilliSeconds(ref byte[] ntpTime, ulong millis)
  {
      ulong intpart = 0, fractpart = 0;
  
      for (var i = 0; i &lt; 4; i++)
          intpart = 256 * intpart + ntpTime[i];
      for (var i = 4; i &lt;= 7; i++)
          fractpart = 256 * fractpart + ntpTime[i];
  
      intpart += millis / 1000;
      fractpart += millis % 1000;
  
      var newIntpart = BitConverter.GetBytes(SwapEndianness(intpart));
      var newFractpart = BitConverter.GetBytes(SwapEndianness(fractpart));
  
      for (var i = 0; i &lt; 8; i++)
      {
          if (i &lt; 4)
              ntpTime[i] = newIntpart[i];
          if (i &gt;= 4)
              ntpTime[i] = newFractpart[i - 4];
      }
  }
  </code></pre>