C# 如何使用不同的时区节点时间将UTC日期和时间转换为本地时间
我使用的功能是从外部服务器通过internet获取日期时间。 这是我用来获取日期和时间的函数,不依赖于用户pc的日期时间设置C# 如何使用不同的时区节点时间将UTC日期和时间转换为本地时间,c#,datetime,timezone,nodatime,C#,Datetime,Timezone,Nodatime,我使用的功能是从外部服务器通过internet获取日期时间。 这是我用来获取日期和时间的函数,不依赖于用户pc的日期时间设置 using NodaTime; using NodaTime.Text; using System.IO; using System.Globalization; public static DateTime GetFastestNISTDate() { var result = DateTime.MinValue;
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;
}
这个变量结果有本地日期时间,但我需要使用Nodatime库,在这里我将放置本地日期时间变量结果,并指定不同的时区,Noda libraray将返回该时区的本地日期和时间
只要指导我如何实现它。我对此进行了访问,但仍然不清楚如何将节点时间库和从外部服务器获取的本地时间合并在一起,以获得基于不同时区的另一个日期时间
正在寻找有关示例代码的帮助信息
谢谢
编辑
时区转换不起作用。我从这个函数getFastTestNistDate获得了正确的日期;接下来,我尝试根据我的第一个utc时间获取不同时区的本地日期和时间,但代码返回了错误的伦敦时间。我想我把密码弄错了。有人能看到并帮助我吗。谢谢
编辑2
我想通过Nodatime库实现的相同功能
var wc = GetFastestNISTDate();
TimeZoneInfo cstZone = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");
DateTime cstTime = TimeZoneInfo.ConvertTimeFromUtc(wc, cstZone);
上面的代码给出了或多或少正确的时间。请告诉我如何使用nodatime库替换我的最后2行。谢谢
编辑3
@约翰告诉我上面的代码是可以的,因为你说
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);`
它解决了问题吗
编辑4
第1点
在这个例行的GetFastTestDate中,您注意到了什么错误;例行程序是查询几个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]));
此例程获取最快的日期;正在返回utcDateTime…不是utc时间吗
第2点
当我打电话给GetFastTestDate时;例程我注意到这个例程有一段时间返回了DateTime.MinValue,这不是预期的结果。我可以理解为什么会发生这种情况,因为NIST时间服务器当时很忙或被阻塞,或者超时
第3点
如果我使用您当前的代码/库NodaTime.NetworkClock,那么我想知道默认情况下它将查询哪个NTP服务器?
如果我使用NodaTime.NetworkClock,是否有可能因为NTP服务器忙/阻塞或超时而在某个时间获得错误的日期或空日期
编辑5
您不应该将日期时间转换为字符串并返回-但您当前的问题是,您正在将从服务器返回的UTC值转换为本地日期时间,而没有明显的原因。理想情况下,我建议更改GetFastTestNistDate以返回瞬间,但假设您不能这样做: 不要自己解析。从响应中获取适当的子字符串,然后使用DateTime.ParseExact,指定CultureInfo.InvariantCulture和DateTimeStyles.AssumeUniversal 不要将UTC日期时间转换为本地版本-这是毫无意义和令人困惑的 使用Instant.FromDateTimeUtc将UTC日期时间转换为即时时间
代码的最后一部分(最后三行)是可以的,但是为什么需要DateTime呢?如果您可以使用Noda Time尽可能多地使用代码,您将在代码清晰性方面获得最大的好处。您不应该将DateTime转换为字符串并返回-但您当前的问题是,您将从服务器返回的UTC值转换为本地DateTime,没有明显的原因。理想情况下,我建议更改GetFastTestNistDate以返回瞬间,但假设您不能这样做: 不要自己解析。从响应中获取适当的子字符串,然后使用DateTime.ParseExact,指定CultureInfo.InvariantCulture和DateTimeStyles.AssumeUniversal 不要将UTC日期时间转换为本地版本-这是毫无意义和令人困惑的 使用Instant.FromDateTimeUtc将UTC日期时间转换为即时时间 代码的最后一部分(最后三行)是可以的,但是为什么需要DateTime呢?如果您可以使用Noda Time尽可能多地使用代码,您将在代码清晰性方面获得最大的好处。您的GetFastTestDate函数使用-这基本上是不推荐的,不适用于机器交互,因为它的结果没有特定的格式。即使是最新版本也强烈鼓励用户不要在白天使用 您可以找到NTP客户端的简单C实现 为了使事情更简单,我将这个客户端实现为NodaTime.IClock。代码在GitHub上。只需安装: 安装包NodaTime.NetworkClock 然后,您可以像使用系统时钟一样使用它: GetFastTestNistDate函数使用-这基本上是不推荐使用的,并不用于机器交互,因为它的结果没有特定的格式。即使是最新版本也强烈鼓励用户不要在白天使用 您可以找到NTP客户端的简单C实现 为了使事情更简单,我将这个客户端实现为NodaTime.IClock。代码在GitHub上。只需安装: 安装包NodaTime.NetworkClock 然后你就可以像使用 系统时钟:
如果没有一个具体的例子来说明问题所在,那么很难提供帮助—示例输入值、预期输出值和实际输出值。@Jonsket:GetFastTestNistDate此函数返回localtime,我想从不同的时区获取localtime。时区不是固定的。用户可以给出任何时区。基本上,我的目标是在不依赖用户pc datetime的情况下,根据timezoneid获取本地datetime。这仍然没有给出任何示例输入值等。请参阅我的答案,但请阅读以获得关于提出更好问题的建议。如果没有一个具体的错误示例-示例输入值,很难提供帮助,预期的输出值和实际的输出值。@Jonsket:GetFastTestNistDate此函数返回localtime,我想从不同的时区获取localtime。时区不是固定的。用户可以给出任何时区。基本上,我的目标是在不依赖用户pc datetime的情况下,根据timezoneid获取本地datetime。这仍然没有给出任何示例输入值等。请参阅我的答案,但请阅读以获得关于提出更好问题的建议。我从不使用Nodatime。你能不能编辑我的最后7行。GetFastTestNistDate返回日期时间如01-Jan-01 12:00:00 AM,当我尝试根据以前的日期时间获取另一个时区欧洲/伦敦日期时间时,问题就出现了。请参阅我的第二个编辑部分,我试图实现的目标将是明确的。thanks@Mou:那么出现的问题仍然没有给我样本数据。我不知道我可以用多少种不同的方式来表达。。。您的输入是什么,即在进行我建议的更改后从GetFastTestNistDate返回的值,因此是UTC而不是本地?你的预期产出是多少?您的实际输出是什么?无论如何,从这个函数GetFastTestNistDate返回utc日期时间后,问题似乎已经解决了。我从来没有使用过Nodatime。你能不能编辑我的最后7行。GetFastTestNistDate返回日期时间如01-Jan-01 12:00:00 AM,当我尝试根据以前的日期时间获取另一个时区欧洲/伦敦日期时间时,问题就出现了。请参阅我的第二个编辑部分,我试图实现的目标将是明确的。thanks@Mou:那么出现的问题仍然没有给我样本数据。我不知道我可以用多少种不同的方式来表达。。。您的输入是什么,即在进行我建议的更改后从GetFastTestNistDate返回的值,因此是UTC而不是本地?你的预期产出是多少?您的实际输出是什么?无论如何,从这个函数GetFastTestNistDate返回utc datetime后,问题似乎已经解决了。非常感谢您的回答。请看我的编辑4部分,如果可能的话,详细回答我的几点。thanksPoint 1-您使用的是不推荐使用的协议。第二点——网络并不完美。总是计划停机。第3点-我已经回答了。我转到你的自述文件,注意解释很少,但代码更多。NodaTime网络时钟需要时间,默认情况下是哪个服务器pool.ntp.org?请回答。谢谢。默认值为pool.ntp.org,它将查找距离客户端最近的一个接近且准确的ntp服务器。如果你愿意的话,你可以改变它。非常感谢你的回答。请看我的编辑4部分,如果可能的话,详细回答我的几点。thanksPoint 1-您使用的是不推荐使用的协议。第二点——网络并不完美。总是计划停机。第3点-我已经回答了。我转到你的自述文件,注意解释很少,但代码更多。NodaTime网络时钟需要时间,默认情况下是哪个服务器pool.ntp.org?请回答。谢谢。默认值为pool.ntp.org,它将查找距离客户端最近的一个接近且准确的ntp服务器。如果你愿意,你可以改变它。
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);`
@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.
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]));
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);
var instant = NetworkClock.Instance.Now;
var timeZone = DateTimeZoneProviders.Tzdb["Europe/London"];
var zonedDateTime = instant.InZone(timeZone);