Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.2k views
in Technique[技术] by (71.8m points)

c# - How Convert UTC Date & time to local time using different timezone Nodatime

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);
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...