In one of the applications I have written I needed to get the current date to ensure that the user wasn’t using the software after their license expired. Given that using DateTime.Today could not be trusted as the user could just change their system date, I need ot retrieve the time from the internet somehow. Below is the code that I used to get the current date and time from various NIST Internet Time Services.
public static DateTime GetNISTDate(bool convertToLocalTime) { Random ran = new Random(DateTime.Now.Millisecond); DateTime date = DateTime.Today; string serverResponse = string.Empty; // Represents the list of NIST servers string[] servers = new string[] { "64.90.182.55", "206.246.118.250", "207.200.81.113", "128.138.188.172", "64.113.32.5", "64.147.116.229", "64.125.78.85", "128.138.188.172" }; // Try each server in random order to avoid blocked requests due to too frequent request for (int i = 0; i < 5; i++) { try { // Open a StreamReader to a random time server StreamReader reader = new StreamReader(new System.Net.Sockets.TcpClient(servers[ran.Next(0, servers.Length)], 13).GetStream()); serverResponse = reader.ReadToEnd(); reader.Close(); // Check to see that the signiture is there if (serverResponse.Length > 47 && serverResponse.Substring(38, 9).Equals("UTC(NIST)")) { // Parse the date int jd = int.Parse(serverResponse.Substring(1, 5)); int yr = int.Parse(serverResponse.Substring(7, 2)); int mo = int.Parse(serverResponse.Substring(10, 2)); int dy = int.Parse(serverResponse.Substring(13, 2)); int hr = int.Parse(serverResponse.Substring(16, 2)); int mm = int.Parse(serverResponse.Substring(19, 2)); int sc = int.Parse(serverResponse.Substring(22, 2)); if (jd > 51544) yr += 2000; else yr += 1999; date = new DateTime(yr, mo, dy, hr, mm, sc); // Convert it to the current timezone if desired if (convertToLocalTime) date = date.ToLocalTime(); // Exit the loop break; } } catch (Exception ex) { /* Do Nothing...try the next server */ } } return date; }
There are quite a number of different NIST servers available but I have chosen eight here that have proved to give the quickest results (for me that is). A list of NIST Internet Time Servers can be found here along with their current status.
July 16, 2010 at 7:24 am
Thanks for your code, it was very helpful!
July 17, 2010 at 1:11 am
No problem! Glad you found it useful!
November 2, 2010 at 3:57 pm
Thanks dude!
Perfect for my girlfriends christmas calendar 😉
December 7, 2010 at 12:26 pm
Hi Nick, I’m using the code that you post and, for all available servers, always that I try to connect, it is returned the following message: “No connection could be made because the target machine actively refused it 128.138.140.44:13”. I’m using Windows Vista and I would like your help to know if there is some necessary additional configuration so that I can get the current time at server. Thanks, Fernando
December 7, 2010 at 12:37 pm
Are you using the exact code or have you made some modifications? If you have made modifications, please post to see if something you changed caused it to fail. That being said, I just ran the code again a few times using the 128.138.140.44 server and got a response. Are you requesting the time more frequently than every 4 seconds? The NIST website states that if you do such, you will be refused service. Are you behind a firewall that blocks port 13? Can you use WireShark or some other packet sniffer to see if the request is hitting the network and if you are getting a response?
One modification that I have made to the code is to use the name instead of the IP address of the server. Simply replace the servers array with the following:
string[] servers = new string[] { “time-a.nist.gov”, “time-b.nist.gov” };
Over the years some of the IP addresses change or some of the servers are taken offline. This change will prevent problems if this occurs to you.
April 7, 2011 at 2:12 am
Hi Nick,
Can I use your code for my application?
Regards,
Gaurav
April 7, 2011 at 6:38 am
Definitely. I have no problem with that.
August 1, 2011 at 10:44 am
Thanks!
August 2, 2011 at 11:04 am
Posting a thank you because this code is excellent. Only change I made was switching the IP addresses to hostnames.
August 10, 2011 at 11:55 pm
Could you tell me if the format for the date that is returned will remain the same irrespective of the server used? the current return format is YYYY-MM-DD
August 11, 2011 at 7:51 am
I have been using this for over two years and have never run into an issue where the date format has changed on me. I highly doubt it would ever change among any of the listed servers as so many people depend on it. Windows itself actually allows you to sync to various NIST servers and if they randomly went and changed the format of the data returned, everyone running a Windows machine would be in big trouble. I think you can bet on it staying the same.
September 9, 2011 at 7:07 am
HI THANKS NICE CODE
HOW TO WRITE THE RESULT ON SCREEN?
September 9, 2011 at 7:32 am
The method just returns a DateTime so all you need to do is call ToString on it to be able to display it to the screen.
this.label1.Text = GetNISTTime(true).ToString();
You can use the other overloaded ToString methods to format it as desired.
September 11, 2011 at 11:50 am
I am using the same code given in the example. The method causes the app freeze every now and then. DO you know the possible reason for that?
September 11, 2011 at 1:47 pm
I would be willing to bet that you are getting a network timeout on one of the NIST servers. You are at the mercy of the internet which is a very unreliable thing and as well the load on the specific NIST server you are using. If you are selecting a random server to get the time, do some tests on your server pool and if you see one that consistently times out, pull it out of the pool of possible servers.
Whenever I am making a request from a NIST server I do it on a separate thread and show the user some sort of progress bar in case the behavior you are seeing is incurred. That way the application doesn’t just hang.
Hope that helps.
September 21, 2011 at 5:38 am
Hi
Your Code Is Excellent
but I Want To Set The Time To Egyption Time Becouze Their Is a 3 Hours Differance
Thanks
February 27, 2012 at 10:22 pm
Hi. thaks for the code. can yoг help me how to get time from time.windows.com or time-a.timefreq.bldrdoc.gov using this code? thanks.
February 28, 2012 at 9:50 am
string AppBaseUtcOffset = Convert.ToString(TimeZoneInfo.FindSystemTimeZoneById(“Egypt Standard Time”).BaseUtcOffset);
datetime CurrentTimeZone = TimeZoneInfo.FindSystemTimeZoneById(ZoneId);
datetime CurrentDate = TimeZoneInfo.ConvertTimeFromUtc(GetUtcDate, CurrentTimeZone);
That Should Help you out Nany
February 28, 2012 at 9:55 am
Nick how do i set a timeout option for this one?
Example. If the connection is not made in a few seconds, exit the loop.
I dont want to catch the exception. Rather i would like to set a timeout say 5000.If the connection is not made, return dummy date(date.today);
Thanx
Crucifi3r
February 28, 2012 at 10:27 am
Replace the StreamReader declaration with the following:
TCPClient client = new TcpClient(servers[ran.Next(0, servers.Length)], 13);
client.ReadTimeout = timeOutInMilliseconds;
StreamReader reader = new StreamReader(clinet.GetStream());
February 28, 2012 at 10:43 pm
i’ll try this one.//thanks
I find myself stuck in another loop.
i have a 10 second timer to refresh the date. after a few minutes the thread doesnt respond.
I suspect it is the stream reader..
private void Nist()
{
SystemMessage = null;
GetUtcDate = TZ.NistTime.GetNISTDate(); (Same as the above class)
ValidDate = GetUtcDate.ToString();
if (ValidDate.Contains(DateTime.Today.ToString()))
{
SystemMessage = “Could Not Synchronise With Time Server”;
}
else
{
CurrentTimeZone = TimeZoneInfo.FindSystemTimeZoneById(ZoneId);
CurrentDate = TimeZoneInfo.ConvertTimeFromUtc(GetUtcDate, CurrentTimeZone);
label4.SafeInvoke(d => d.Text = CurrentDate.ToString());
SystemDate = DateTime.Now;
DateDiff = (SystemDate – CurrentDate);
label6.SafeInvoke(d => d.Text = (Convert.ToString(DateDiff)));
}
if (SystemMessage.Contains(“Could Not Synchronise”))
{
label4.SafeInvoke(d => d.Text = “”);
label5.SafeInvoke(d => d.Text = “”);
label6.SafeInvoke(d => d.Text = “”);
label13.SafeInvoke(d => d.Text = “”);
label16.SafeInvoke(d => d.Text = “”);
timer.Change(Timeout.Infinite, Timeout.Infinite);
}
else
{
SystemMessage = “Clock Synchronised”;
timer.Change(0, 1000);
checktimewindow();
}
button1.SafeInvoke(d => d.Enabled = true);
}
February 28, 2012 at 10:55 pm
client.ReadTimeout = timeOutInMilliseconds;
Problem with this line.
‘System.Net.Sockets.TcpClient’ does not contain a definition for ‘ReadTimeout’ and no extension method ‘ReadTimeout’ accepting a first argument of type ‘System.Net.Sockets.TcpClient’ could be found (are you missing a using directive or an assembly reference?)
February 29, 2012 at 1:26 am
Hi. Thank you for the code.
C# gives an error, because StreamReader object doesn’t exist in the context:
StreamReader reader = new StreamReader(new System.Net.Sockets.TcpClient(servers[ran.Next(0, servers.Length)], 13).GetStream());
Can yoг help me?
June 9, 2014 at 11:59 pm
Hi,
I know it’s too late for a reply, but this problem happened to me, too.
I just added System.IO Namespace to my code and it worked. 🙂
April 2, 2012 at 3:34 pm
Hi! Thank you for posting this class.
I’d like to ask you a question: Is it normal that the request often needs up to more than one minute? Do you know of anybody else with the same problem? Or is it just me?
Thank you!
April 3, 2012 at 7:08 am
I have seem some of the servers take a while to respond. When that happens I usually drop that server out of the possible server list and try another that has a quicker response time.
June 6, 2012 at 12:42 am
If you dont mind, where do you host your web page? I am hunting for a great host and your web site appears to be quick and up just about all the time
April 3, 2013 at 1:17 am
thank you from turkey 🙂
December 1, 2013 at 11:44 pm
i want this to display and run dynamically
how can i do that?
February 19, 2014 at 9:55 pm
Hi, it is indeed a very useful solution…. but what get actual date if the machine is not connected to internet…
December 24, 2015 at 5:26 am
hi , nick I run your code but it doesn’t return the current date and time , it return 1\1\0001 12:0:0 AM
June 21, 2016 at 9:58 am
You just helped me so much! We all apreciate it 🙂
December 9, 2016 at 9:57 am
Thank you for sharing your code! I used this in a Unity project [credited you in the c#script of course], updated to use server names and with the timeout feature — as you suggested in the comments.
June 2, 2019 at 8:56 am
thanks dude.