【问题标题】:Incorrect result when using TimeZoneInfo.ConvertTime() to get a localised datetime使用 TimeZoneInfo.ConvertTime() 获取本地化日期时间时结果不正确
【发布时间】:2018-10-24 09:21:16
【问题描述】:

我有一个非常简单的任务,TimeZoneInfo.ConvertTime() 给出的结果不正确。我只是想在“Cen.Australia Standard Time”区域中找到当前的日期时间:

string timeZone = "Cen. Australia Standard Time";
TimeZoneInfo zoneID = TimeZoneInfo.FindSystemTimeZoneById(timeZone);
DateTime nowAtTimeZone = TimeZoneInfo.ConvertTime(DateTime.UtcNow, zoneID);
// result:           24/10/2018 7:43:29 PM
// actual ACST time: 24/10/2018 6:43:29 PM (this is what I want)
// actual ACDT time: 24/10/2018 7:43:29 PM (this is not what I want)

我从这里得到了实际的 ACST 时间:https://www.timeanddate.com/time/zones/acst

以及从这里开始的实际 ACDT 时间:https://www.timeanddate.com/time/zones/acdt

请注意,将 TimeZoneInfo.ConvertTime() 替换为 TimeZoneInfo.ConvertTimeFromUtc() 会得到相同的结果。

请注意,时区是由客户输入的,这是我掌握的所有信息。他们不记录城市。

TimeZoneInfo.ConvertTime() 的结果似乎给了 ACDT 时间,尽管我已经指定了 ACST。

问题可能是TimeZoneInfo.ConvertTime() 正在对 ACST 应用夏令时,而实际上不应该这样做?如果是这样,我该如何防止它这样做?

【问题讨论】:

  • 您的代码对于使用 DST 的阿德莱德来说是正确的。你的意思是达尔文(不是)?
  • 达尔文是"AUS Central Standard Time"。 (是的,命名很糟糕)
  • 阿德莱德不使用 ACST - 它使用 ACDT。至少谷歌告诉我。
  • 阿德莱德在 ACST 和 ACDT 之间交替。参考这里:timeanddate.com/time/zone/australia/adelaide。达尔文全年都在 ACST:timeanddate.com/time/zone/australia/darwin
  • 我不喜欢在阿德莱德度过的时光。我已经过了 ACST 时间。

标签: c# datetime timezone


【解决方案1】:

澳大利亚的时区很复杂,就像世界上许多地方一样。 Wikipedia's page on this subject 是一个很好的概述。

如您所见,有两个主要地区使用澳大利亚中部标准时间。一个使用夏令时,另一个不使用。

对于带有 TimeZoneInfo 类的 Windows 上的 .NET:

  • 使用 "Cen. Australia Standard Time" 作为使用夏令时的澳大利亚中南部时区的 ID。地点包括阿德莱德等。

  • 使用"AUS Central Standard Time" 作为不使用夏令时的澳大利亚中北部时区的 ID。地点包括达尔文等。

TimeZoneInfo 类正在根据给定的时区做正确的事情。

就选择正确的时区而言,使用TimeZoneInfo.GetSystemTimeZones() 返回所有可用时区,使用IdDisplayName 属性创建一个下拉列表。用户应该只需要从显示名称中进行选择,您只需在代码中使用 ID。

【讨论】:

  • 非常感谢!顺便说一句,你怎么知道Cen. Australia Standard Time 包括阿德莱德,但AUS Central Standard Time 包括达尔文?这是正确的,但你有一个链接,所以我可以将它用于其他时区吗?它不在维基百科中。谷歌搜索 Cen. Australia Standard Time 最初导致我走错了方向,因为谷歌回复 ACST,这在技术上是不正确的(它应该回复 ACDT)。
  • 检查来自TimeZoneInfo.GetSystemTimeZones() 的结果,正如我在帖子中解释的那样。请注意,显示名称中包含这些城市。还有许多其他方法可以查看这些数据,例如在命令行中使用TZUtil.exe /L,或者通过挖掘 Windows 注册表。
  • 好的,干杯。你没有说这是DisplayName 在帖子中给出的。
【解决方案2】:

您需要致电TimeZoneInfo.ConvertTimeFromUtc(datetime, timezoneInfo)。检查这个

 string timeZone = "Cen. Australia Standard Time";
            TimeZoneInfo zoneID = TimeZoneInfo.FindSystemTimeZoneById(timeZone);            
            DateTime nowAtTimeZone = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, zoneID);

【讨论】:

  • 这相当于问题中的内容。由于DateTimeKind 的工作方式,ConvertTimeFromUtcConvertTime 在通过 DateTime.UtcNow 时的行为相同。
  • 是的。我已经确认他们给出了相同的结果——不是我所追求的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-22
  • 1970-01-01
  • 2017-11-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多