C#: Get NIST Internet Time


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.

About these ads
Posted in Time and Date. Tags: , , . 29 Comments »

29 Responses to “C#: Get NIST Internet Time”

  1. Eli Yukelzon Says:

    Thanks for your code, it was very helpful!

  2. Nick Olsen Says:

    No problem! Glad you found it useful!

  3. Thomas Says:

    Thanks dude!
    Perfect for my girlfriends christmas calendar ;)

  4. Fernando Says:

    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

    • Nick Olsen Says:

      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.

  5. Gaurav Says:

    Hi Nick,

    Can I use your code for my application?

    Regards,
    Gaurav

    • Nick Olsen Says:

      Definitely. I have no problem with that.

  6. Vic Says:

    Thanks!

  7. Richard Robertson Says:

    Posting a thank you because this code is excellent. Only change I made was switching the IP addresses to hostnames.

  8. Tanmay Dharmaraj Says:

    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

    • Nick Olsen Says:

      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.

  9. sandy Says:

    HI THANKS NICE CODE
    HOW TO WRITE THE RESULT ON SCREEN?

    • Nick Olsen Says:

      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.

  10. george Says:

    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?

    • Nick Olsen Says:

      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.

  11. NANy Says:

    Hi
    Your Code Is Excellent
    but I Want To Set The Time To Egyption Time Becouze Their Is a 3 Hours Differance
    Thanks

  12. Rojer Says:

    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.

  13. Crucifi3r Says:

    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

  14. Crucifi3r Says:

    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

    • Nick Olsen Says:

      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());

  15. Crucifi3r Says:

    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);
    }

  16. Crucifi3r Says:

    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?)

  17. Rojer Says:

    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?

  18. soso Says:

    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!

    • Nick Olsen Says:

      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.

  19. click Says:

    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

  20. tolga Says:

    thank you from turkey :)

  21. adream Says:

    i want this to display and run dynamically
    how can i do that?

  22. rahuls Says:

    Hi, it is indeed a very useful solution…. but what get actual date if the machine is not connected to internet…


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 67 other followers

%d bloggers like this: