Wrong DateTime on .NET Micro Framework Devices

Michael Schwarz on Sunday, March 9, 2008

Since embeddedworld2008 in Nuremberg I'm playing in my free time with the .NET Micro Framework [1] and the Digi Connect ME network device [2]. I've created a small Web server and ported the Ajax.NET Professional library to the really cool and small .NET framework.

When I reset such a device the current date and time gets wrong, too. This is very bad as I would like to have always the correct time, of course. Especially when you are working with Web servers it is very important to have the correct time because http headers contain date info when files should expire or how long they are allowed to be cached locally in Web browsers cache.

I have created a simple method to query a NTP server [3] and set the device date to the returned value. Here is the code:

<pre style="background-color:White;;overflow: auto;"><div><!--

Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/

--><span style="color: #0000FF;">public</span><span style="color: #000000;"> </span><span style="color: #0000FF;">static</span><span style="color: #000000;"> DateTime GetNetworkTime() { IPEndPoint ep </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">new</span><span style="color: #000000;"> IPEndPoint(Dns.GetHostEntry(</span><span style="color: #800000;">&quot;</span><span style="color: #800000;">time-a.nist.gov</span><span style="color: #800000;">&quot;</span><span style="color: #000000;">).AddressList[</span><span style="color: #800080;">0</span><span style="color: #000000;">], </span><span style="color: #800080;">123</span><span style="color: #000000;">);

Socket s </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">new</span><span style="color: #000000;"> Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); s.Connect(ep);

</span><span style="color: #0000FF;">byte</span><span style="color: #000000;">[] ntpData </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">new</span><span style="color: #000000;"> </span><span style="color: #0000FF;">byte</span><span style="color: #000000;">[</span><span style="color: #800080;">48</span><span style="color: #000000;">]; </span><span style="color: #008000;">//</span><span style="color: #008000;"> RFC 2030</span><span style="color: #008000;"> </span><span style="color: #000000;"> ntpData[</span><span style="color: #800080;">0</span><span style="color: #000000;">] </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #800080;">0x1B</span><span style="color: #000000;">; </span><span style="color: #0000FF;">for</span><span style="color: #000000;"> (</span><span style="color: #0000FF;">int</span><span style="color: #000000;"> i </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #800080;">1</span><span style="color: #000000;">; i </span><span style="color: #000000;">&lt;</span><span style="color: #000000;"> </span><span style="color: #800080;">48</span><span style="color: #000000;">; i</span><span style="color: #000000;">++</span><span style="color: #000000;">) ntpData[i] </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #800080;">0</span><span style="color: #000000;">;

s.Send(ntpData); s.Receive(ntpData);

</span><span style="color: #0000FF;">byte</span><span style="color: #000000;"> offsetTransmitTime </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #800080;">40</span><span style="color: #000000;">; </span><span style="color: #0000FF;">ulong</span><span style="color: #000000;"> intpart </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #800080;">0</span><span style="color: #000000;">; </span><span style="color: #0000FF;">ulong</span><span style="color: #000000;"> fractpart </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #800080;">0</span><span style="color: #000000;">; </span><span style="color: #0000FF;">for</span><span style="color: #000000;"> (</span><span style="color: #0000FF;">int</span><span style="color: #000000;"> i </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #800080;">0</span><span style="color: #000000;">; i </span><span style="color: #000000;">&lt;=</span><span style="color: #000000;"> </span><span style="color: #800080;">3</span><span style="color: #000000;">; i</span><span style="color: #000000;">++</span><span style="color: #000000;">) intpart </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #800080;">256</span><span style="color: #000000;"> </span><span style="color: #000000;">*</span><span style="color: #000000;"> intpart </span><span style="color: #000000;">+</span><span style="color: #000000;"> ntpData[offsetTransmitTime </span><span style="color: #000000;">+</span><span style="color: #000000;"> i];

</span><span style="color: #0000FF;">for</span><span style="color: #000000;"> (</span><span style="color: #0000FF;">int</span><span style="color: #000000;"> i </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #800080;">4</span><span style="color: #000000;">; i </span><span style="color: #000000;">&lt;=</span><span style="color: #000000;"> </span><span style="color: #800080;">7</span><span style="color: #000000;">; i</span><span style="color: #000000;">++</span><span style="color: #000000;">) fractpart </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #800080;">256</span><span style="color: #000000;"> </span><span style="color: #000000;">*</span><span style="color: #000000;"> fractpart </span><span style="color: #000000;">+</span><span style="color: #000000;"> ntpData[offsetTransmitTime </span><span style="color: #000000;">+</span><span style="color: #000000;"> i];

</span><span style="color: #0000FF;">ulong</span><span style="color: #000000;"> milliseconds </span><span style="color: #000000;">=</span><span style="color: #000000;"> (intpart </span><span style="color: #000000;"></span><span style="color: #000000;"> </span><span style="color: #800080;">1000</span><span style="color: #000000;"> </span><span style="color: #000000;">+</span><span style="color: #000000;"> (fractpart </span><span style="color: #000000;"></span><span style="color: #000000;"> </span><span style="color: #800080;">1000</span><span style="color: #000000;">) </span><span style="color: #000000;">/</span><span style="color: #000000;"> </span><span style="color: #800080;">0x100000000L</span><span style="color: #000000;">);

s.Close();

TimeSpan timeSpan </span><span style="color: #000000;">=</span><span style="color: #000000;"> TimeSpan.FromTicks((</span><span style="color: #0000FF;">long</span><span style="color: #000000;">)milliseconds </span><span style="color: #000000;">*</span><span style="color: #000000;"> TimeSpan.TicksPerMillisecond); DateTime dateTime </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">new</span><span style="color: #000000;"> DateTime(</span><span style="color: #800080;">1900</span><span style="color: #000000;">, </span><span style="color: #800080;">1</span><span style="color: #000000;">, </span><span style="color: #800080;">1</span><span style="color: #000000;">); dateTime </span><span style="color: #000000;">+=</span><span style="color: #000000;"> timeSpan;

TimeSpan offsetAmount </span><span style="color: #000000;">=</span><span style="color: #000000;"> TimeZone.CurrentTimeZone.GetUtcOffset(dateTime); DateTime networkDateTime </span><span style="color: #000000;">=</span><span style="color: #000000;"> (dateTime </span><span style="color: #000000;">+</span><span style="color: #000000;"> offsetAmount);

Debug.Print(networkDateTime.ToString());

</span><span style="color: #0000FF;">return</span><span style="color: #000000;"> networkDateTime; }</span></div></pre><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin. http://dunnhq.com -->

To set the returned DateTime as new time on the device use following utility method:

<pre style="background-color:White;;overflow: auto;"><div><!--

Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/

--><span style="color: #000000;">Utility.SetLocalTime(GetNetworkTime());</span></div></pre><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin. http://dunnhq.com -->

Note, that the current time zone is often wrong, too. Use following method to set the time zone to the correct value, in my example I use the time zone here in Germany:

<pre style="background-color:White;;overflow: auto;"><div><!--

Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/

--><span style="color: #000000;">Microsoft.SPOT.ExtendedTimeZone.SetTimeZone(TimeZoneId.Berlin);</span></div></pre><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin. http://dunnhq.com -->

I put this code in the Main() method of my applications to get always the correct date when I start my device.