简体   繁体   English

如何使用不同的时区Nodatime将UTC日期和时间转换为本地时间

[英]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. 这是我用来获取日期和时间的功能,而无需依赖用户PC日期时间设置。

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. variable result具有本地日期时间,但是我需要使用Nodatime库,在该库中我将放置本地日期时间变量result ,并指定不同的时区,Noda libraray将返回该时区的本地日期和时间。

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. 我访问此URL,但仍不清楚如何将Nodatime库和从外部服务器获得的本地时间结合在一起,以获取基于不同时区的另一个datetime。

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(); 我从此函数GetFastestNISTDate();得到了正确的日期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. 接下来,我尝试根据我的第一个utc时间获取不同时区的本地日期和时间,但是代码返回伦敦的错误时间。 i guess i am making mistake the code. 我想我把代码弄错了。 can anyone see & help. 谁能看到和帮助。 thanks 谢谢

EDIT 2 编辑2

the samething i want to achieve by Nodatime library. 我想通过Nodatime库实现的目标。

    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. 告诉我如何使用nodatime库替换我的最后2行。 thanks 谢谢

Edit 3 编辑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 @John告诉我上面的代码还可以,因为你说

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 编辑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 点1

    what was wrong you notice in this routine GetFastestNISTDate(); 您在此例程GetFastestNISTDate();注意到了什么错误GetFastestNISTDate(); the routine was query few NIST time servers and get the utctime. 该例程是查询几个NIST时间服务器并获取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(); 此例程GetFastestNISTDate(); was returning utcDateTime....was not a utc time ? 正在返回utcDateTime ....不是utc时间?

  1. Point 2 点2

when i was calling GetFastestNISTDate(); 当我调用GetFastestNISTDate(); routine i notice some time this routine was returning DateTime.MinValue which was not expected result. 例程我注意到一段时间,该例程返回DateTime.MinValue ,这不是预期的结果。 i could understand why it was happening because NIST time servers was busy or blocked or timeout occured at that time. 我可以理解为什么会发生这种情况, because NIST time servers正忙或阻塞,或者当时发生了超时。

  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? 第三点,如果我使用您当前的代码/库NodaTime.NetworkClock那么我想知道默认情况下将查询哪个NTP服务器?

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? 如果我使用NodaTime.NetworkClock那么是否有可能由于NTP server is busy/block或发生超时而导致我得到错误的日期或空日期的时间?

EDIT 5 编辑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);

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. 您的GetFastestNISTDate函数使用白天协议 -本质上已弃用,并且不打算用于机器交互,因为其结果没有特定的格式。 Even the docs from NIST strongly encourage users to use NTP instead of daytime. 甚至NIST文档都强烈建议用户使用NTP而不是白天。

You can find a simple C# implementation of an NTP client here . 您可以在此处找到NTP客户端的简单C#实现。

To make things easier, I've implemented this client as a NodaTime.IClock . 为了使事情变得简单,我已经将此客户端实现为NodaTime.IClock The code is on GitHub here . 该代码是在GitHub 这里 Simply install it from NuGet : 只需从NuGet安装它:

Install-Package NodaTime.NetworkClock

Then you can use it just like you would use the SystemClock : 然后,您可以像使用SystemClock一样使用它:

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

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. 您不应该将DateTime转换为字符串并返回-但是当前的问题是,您将从服务器获取的UTC值转换为本地DateTime的原因不明显。 Ideally, I'd suggest changing GetFastestNISTDate() to return an Instant , but assuming you can't do that: 理想情况下,我建议更改GetFastestNISTDate()以返回Instant ,但是假设您不能这样做:

  • Don't do the parsing yourself. 不要自己解析。 Take the appropriate substring from the response, then use DateTime.ParseExact , specifying CultureInfo.InvariantCulture and DateTimeStyles.AssumeUniversal 从响应中获取适当的子字符串,然后使用DateTime.ParseExact ,指定CultureInfo.InvariantCultureDateTimeStyles.AssumeUniversal
  • Don't convert the UTC DateTime to a local version - it's pointless and confusing 不要将UTC DateTime转换为本地版本-这毫无意义且令人困惑
  • Use Instant.FromDateTimeUtc to convert a UTC DateTime to an instant 使用Instant.FromDateTimeUtc将UTC DateTime时间转换为即时

The final part of your code (the last three lines) is okay, but why do you need a DateTime at all? 代码的最后部分(最后三行)可以,但是为什么您完全需要DateTime 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. 如果您可以使用Noda Time尽可能多地使用代码,则在代码清晰性方面将获得最大的好处。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM