1

i am using a function which is taking date time over the internet from external server. here is the function which i am using to get date and time without depend on user pc date time settings.

using NodaTime;
using NodaTime.Text;
using System.IO;
using System.Globalization;

 public static DateTime GetFastestNISTDate()
        {
            var result = DateTime.MinValue;
            DateTime utcDateTime = DateTime.MinValue; 

            // Initialize the list of NIST time servers
            // http://tf.nist.gov/tf-cgi/servers.cgi
            string[] servers = new string[] {
                "nist1-ny.ustiming.org",
                "nist1-nj.ustiming.org",
                "nist1-pa.ustiming.org",
                "time-a.nist.gov",
                "time-b.nist.gov",
                "nist1.aol-va.symmetricom.com",
                "nist1.columbiacountyga.gov",
                "nist1-chi.ustiming.org",
                "nist.expertsmi.com",
                "nist.netservicesgroup.com"
            };

            // Try 5 servers in random order to spread the load
            Random rnd = new Random();
            foreach (string server in servers.OrderBy(s => rnd.NextDouble()).Take(5))
            {
                try
                {
                    // Connect to the server (at port 13) and get the response
                    string serverResponse = string.Empty;
                    using (var reader = new StreamReader(new System.Net.Sockets.TcpClient(server, 13).GetStream()))
                    {
                        serverResponse = reader.ReadToEnd();
                    }

                    // If a response was received
                    if (!string.IsNullOrEmpty(serverResponse))
                    {
                        // Split the response string ("55596 11-02-14 13:54:11 00 0 0 478.1 UTC(NIST) *")
                        string[] tokens = serverResponse.Split(' ');

                        // Check the number of tokens
                        if (tokens.Length >= 6)
                        {
                            // Check the health status
                            string health = tokens[5];
                            if (health == "0")
                            {
                                // Get date and time parts from the server response
                                string[] dateParts = tokens[1].Split('-');
                                string[] timeParts = tokens[2].Split(':');

                                // Create a DateTime instance
                                utcDateTime = new DateTime(
                                    Convert.ToInt32(dateParts[0]) + 2000,
                                    Convert.ToInt32(dateParts[1]), Convert.ToInt32(dateParts[2]),
                                    Convert.ToInt32(timeParts[0]), Convert.ToInt32(timeParts[1]),
                                    Convert.ToInt32(timeParts[2]));

                                // Convert received (UTC) DateTime value to the local timezone
                                result = utcDateTime.ToLocalTime();

                                //return result;
                                return utcDateTime;
                                // Response successfully received; exit the loop

                            }
                        }

                    }

                }
                catch
                {
                    // Ignore exception and try the next server
                }
            }
            //return result;
            return utcDateTime;
        }

this variable result has local date time but i need to use Nodatime library where i will put my local date time variable result and also specify different timezone and Noda libraray will return local date and time of that timezone.

just guide me how to achieve it. i visit this url but still not clear how to incorporate Nodatime library and local time got from external server together to get another datetime based on different timezone.

looking for help with bit of sample code thanks

EDIT

var wc = GetFastestNISTDate();

var pattern = InstantPattern.CreateWithInvariantCulture("dd/MM/yyyy HH:mm:ss");
var parseResult = pattern.Parse(wc.ToString("dd/MM/yyyy HH:mm:ss", CultureInfo.InvariantCulture));
if (!parseResult.Success)
    throw new InvalidDataException("...whatever...");
var instant = parseResult.Value;

var timeZone = DateTimeZoneProviders.Tzdb["Europe/London"];
var zonedDateTime = instant.InZone(timeZone);
var bclDateTime = zonedDateTime.ToDateTimeUnspecified();

timezone translation is not working. i got the right date from this function GetFastestNISTDate(); and next i try to get local date and time of different timezone based on my first utc time but code return wrong time for London. i guess i am making mistake the code. can anyone see & help. thanks

EDIT 2

the samething i want to achieve by Nodatime library.

    var wc = GetFastestNISTDate();

    TimeZoneInfo cstZone = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");
    DateTime cstTime = TimeZoneInfo.ConvertTimeFromUtc(wc, cstZone);

the above code is giving more or less right time. just tell me how to replace my last 2 line using nodatime library. thanks

Edit 3

var wc = GetFastestNISTDate();
Instant now = Instant.FromDateTimeUtc(wc);

var timeZone = DateTimeZoneProviders.Tzdb["Europe/London"];
var zonedDateTime = instant.InZone(timeZone);
var bclDateTime = zonedDateTime.ToDateTimeUnspecified();

@John just tell me the above code is ok because u said

Don't convert the UTC DateTime to a local version - it's pointless and confusing
Use Instant.FromDateTimeUtc to convert a UTC DateTime to an instant

GetFastestNISTDate() returning datetime instance and here we just create noda instance from utc datetime using like this code `Instant now = Instant.FromDateTimeUtc(wc);`

does it solve the issue.

EDIT 4

@Matt Johnson : thanks a lot for redirecting me to a good library. 
i would definitely like to work with that library to achieve my task. before 
use your library i have some question.
  1. Point 1

    what was wrong you notice in this routine GetFastestNISTDate(); the routine was query few NIST time servers and get the utctime.

                       utcDateTime = new DateTime(
                            Convert.ToInt32(dateParts[0]) + 2000,
                            Convert.ToInt32(dateParts[1]), Convert.ToInt32(dateParts[2]),
                            Convert.ToInt32(timeParts[0]), Convert.ToInt32(timeParts[1]),
                            Convert.ToInt32(timeParts[2]));
    

this routine GetFastestNISTDate(); was returning utcDateTime....was not a utc time ?

  1. Point 2

when i was calling GetFastestNISTDate(); routine i notice some time this routine was returning DateTime.MinValue which was not expected result. i could understand why it was happening because NIST time servers was busy or blocked or timeout occured at that time.

  1. Point 3 if i use your current code/library NodaTime.NetworkClock then i like to know which NTP server it will query by default?

if i use NodaTime.NetworkClock then is there any chance that some time i may get wrong date or null date due to NTP server is busy/block or timeout occur?

EDIT 5

    var instant = NetworkClock.Instance.Now;
    var timeZone = DateTimeZoneProviders.Tzdb["Europe/London"];
    var zonedDateTime = instant.InZone(timeZone);

    lbldate.Text = zonedDateTime.ToString("dd/MM/yyyy", CultureInfo.InvariantCulture);
    lbltime.Text = zonedDateTime.ToString("hh:mm:ss", CultureInfo.InvariantCulture);
Community
  • 1
  • 1
Mou
  • 15,673
  • 43
  • 156
  • 275
  • It's very hard to help without a concrete example of what's going wrong - sample input values, expected output values and actual output values. – Jon Skeet Dec 05 '14 at 13:06
  • @JonSkeet: GetFastestNISTDate() this function return localtime and i want to get localtime from different timezone. timezone is not fixed. user may give any timezone. basically my objective is to get local datetime based on timezoneid without depend on user pc datetime. – Mou Dec 05 '14 at 13:10
  • 1
    That still hasn't given any sample input values etc. See my answer, but please read http://tinyurl.com/stack-hints for suggestions on asking better questions. – Jon Skeet Dec 05 '14 at 13:11

2 Answers2

4

Your GetFastestNISTDate function uses the daytime protocol - which is essentially deprecated and NOT meant for machine interaction because its results are in no specific format. Even the docs from NIST strongly encourage users to use NTP instead of daytime.

You can find a simple C# implementation of an NTP client here.

To make things easier, I've implemented this client as a NodaTime.IClock. The code is on GitHub here. Simply install it from NuGet:

Install-Package NodaTime.NetworkClock

Then you can use it just like you would use the SystemClock:

var instant = NetworkClock.Instance.Now;
var timeZone = DateTimeZoneProviders.Tzdb["Europe/London"];
var zonedDateTime = instant.InZone(timeZone);
Community
  • 1
  • 1
Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575
  • thanks a lot for your answer. please see my edit 4 portion and answer few my points in details if possible. thanks – Mou Dec 08 '14 at 08:02
  • Point 1 - you were using a deprecated protocol. Point 2 - Networks aren't perfect. Always plan for outages. Point 3 - I already answered in [the project readme](https://github.com/mj1856/NodaTime.NetworkClock/blob/master/README.md). – Matt Johnson-Pint Dec 08 '14 at 17:49
  • i go to your readme file and notice explanations are very few but code is more there.NodaTime network clock is taking time from which server by default is it "pool.ntp.org" ? please answer. thanks – Mou Dec 09 '14 at 10:58
  • Yes. The default is `pool.ntp.org`, which will find a close and accurate ntp server nearest the client. You can change it if you want. – Matt Johnson-Pint Dec 09 '14 at 16:33
3

You shouldn't be converting the DateTime to a string and back - but your current problem is that you're converting the UTC value you get back from the server into a local DateTime for no obvious reason. Ideally, I'd suggest changing GetFastestNISTDate() to return an Instant, but assuming you can't do that:

  • Don't do the parsing yourself. Take the appropriate substring from the response, then use DateTime.ParseExact, specifying CultureInfo.InvariantCulture and DateTimeStyles.AssumeUniversal
  • Don't convert the UTC DateTime to a local version - it's pointless and confusing
  • Use Instant.FromDateTimeUtc to convert a UTC DateTime to an instant

The final part of your code (the last three lines) is okay, but why do you need a DateTime at all? If you can make as much of your code as possible use Noda Time, you'll get the greatest benefits in terms of code clarity.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • i never use Nodatime. can u plzz edit my last 7 line. – Mou Dec 05 '14 at 13:13
  • GetFastestNISTDate() return datetime like "01-Jan-01 12:00:00 AM" and when i try to get another timezone "Europe/London" datetime based on previous datetime then problem occur. – Mou Dec 05 '14 at 13:15
  • please see my second edit portion what i am trying to achieve will be clear. thanks – Mou Dec 05 '14 at 13:25
  • @Mou: "Then problem occur" **still** doesn't give me sample data. I'm not sure how many different ways I can say this... what is your input (i.e. the value you get back from `GetFastestNISTDate()` after making the changes I've suggested so it's UTC rather than local)? What is your expected output? What is your actual output? – Jon Skeet Dec 05 '14 at 13:35
  • anyway it seems problem has been solved after return utc datetime from this function GetFastestNISTDate(). – Mou Dec 05 '14 at 13:38
  • hi jon Mou is my friend. u said "Use Instant.FromDateTimeUtc to convert a UTC DateTime to an instant" so i just edit her code. now please see the edit 3 portion and tell us does it work fine now? looking for your suggestion. – Thomas Dec 06 '14 at 18:35
  • @Thomas: Well that's exactly what I said in my answer - see my last bullet point. But `GetFastestNISTDate` needs to return a UTC `DateTime` first. But personally I'd just try to use Noda Time *throughout* the code base, rather than converting between Noda Time and the BCL types everywhere. – Jon Skeet Dec 06 '14 at 19:28