转换不同时区之间的时间

我正在build立一个橱窗时钟应用程序,以显示用户的当前时间,也为世界各地的不同城市。

最初,我曾计划完全使用Google等的时区networking服务,但是在查看了免费帐户允许的请求数和获得付费帐户的费用之后,我觉得最好find一个备用解决scheme,而不必抵押房子。

到处寻找,我find了John Skeet和团队的优秀NodaTime图书馆。 通过文档和这里在stackoverflow深入挖掘,我的头仍然嗡嗡与所有的date时间和时区相关的术语和转换方法。 无论如何,我认为我可以做到这一点有两个select:

选项1 :使用DateTime.Now获取当前系统时间,然后使用nodatime为其他区域获取时间(基于由Matt Johnson提供的代码回答关于SO的另一个问题):

DateTimeZone homeZone = DateTimeZoneProviders.Tzdb["Asia/Colombo"]; LocalDateTime homeTime = LocalDateTime.FromDateTime(DateTime.Now); ZonedDateTime homeTimeInZone = homeTime.InZoneStrictly(homeZone); TbTime1.Text = "Home time is: " + homeTimeInZone.ToDateTimeOffset(); DateTimeZone timeZone1 = DateTimeZoneProviders.Tzdb["Australia/Perth"]; ZonedDateTime timeZone1Time = homeTimeInZone.WithZone(timeZone1); TbTime2.Text = "Timezone 1 time is: " + timeZone1Time.ToDateTimeOffset(); 

scheme2 :在进一步研究之后,我find了这个解决scheme,并且觉得它也可以很好地工作:

 public ZonedDateTime GetTimeInTimeZone(string timeZone) { // Timezone is olson timezone eg "Asia/Colombo" Instant now = SystemClock.Instance.Now; var zone = DateTimeZoneProviders.Tzdb[timeZone]; ZonedDateTime zonedDateTime = now.InZone(zone); return zonedDateTime; } 

现在让我试着回答这个问题:在上面的两个选项中,都依赖于DateTime.NowSystemClock.Instance.Now首先识别用户的系统时间,然后将其转换为所需的时区的城市时间。 但是,如果用户的系统没有设置到正确的时间会发生什么? 我相信(纠正我,如果错误)DateTime.Now和SystemClock.Instance.Now都使用系统时钟获取当前时间? 假设系统时间设置不正确,那么由于我们依赖用户的系统时间,所以任何时区转换都会显示其他城市的错误时间。

在这种情况下,如何在不依赖系统时钟的情况下build立用户的当前时间? 我应该恢复使用Web服务来获取用户的当前时区使用lat / long还是有更好的select使用NodaTime等可以离线工作? 谢谢。

几点:

  • 避免使用DateTime.Now

    • 它已经转换到当地时区,所以在DST回退转换期间,结果可能不明确。
    • 如果您需要在不使用Noda时间的情况下及时获得准确无误的时间,请使用DateTime.UtcNow
    • 您还可以使用DateTimeOffset.UtcNowDateTimeOffset.Now 。 包含偏移量时,不存在歧义。
    • 另请参阅我的博客中的“对付DateTime.Now ”一文。
  • 在Noda Time中,意识到SystemClock.InstanceIClock接口的一个实现。 只要有可能,你应该对接口进行编码,这样你可以根据需要替换单元测试中的实现。 尽管在最简单的例子中,调用SystemClock.Instance.Now没有任何问题 ,但现在它并不是可测试的。

  • 至于使用哪个时区输入,那完全是根据你的应用需求而定的。

    • 如果您可以依靠系统将其设置到正确的区域,则可以使用该区域进行检索

       DateTimeZone tz = DateTimeZoneProviders.Tzdb.GetSystemDefault(); 
    • 如果您不能依赖系统时区进行正确设置,则可以考虑其他一些输入源。

    • 你提到了GPS坐标。 如果你有,也许从移动设备,有解决方案,以解决它的时区。 看到这里的一些选项。 野田时间在这方面不能帮助你。

    • 您也可以考虑要求您的应用程序的用户从下拉列表或地图中选择一个时区。 HTML / JS 在这里和这里有一些基于地图的时区选择器。 (我不确定他们是否会在基于WinJS的Windows应用商店应用程序中工作,我不知道任何基于XAML的解决方案。)

  • 如果他们的时钟的实际时间设置错误,除了尝试联系另一台服务器以检索时间戳之外,您可以做的不多。 在大多数情况下,您应该依赖于操作系统已经与时间服务器同步。

    • 如果您确实需要与外部服务进行同步,那可能会很有挑战性。 您需要正确实施NTP的一些事情,包括测量和补偿传输延迟。 这并不容易,可能需要一个外部库。 我不知道要推荐一个。

    • 接触到Web服务并返回当前时间不一定会像您想象的那样准确,因为这不会补偿服务器将响应传输给您的时间。

    • 如果您正在使用带有GPS接收器的设备上运行,那么从技术上讲,它可以提供从GPS信号接收到的准确时间戳。 无论是否可通过Windows Store API检索和使用,我都不确定。 我在MSDN上查了几个参考,但是空了。

  • 关于你提供的两个代码示例,他们做的是稍微不同的事情,但是选择2.它更干净,而且是纯粹的Noda时间。

通常可以依靠当地的时间准确,如时钟显示。 任何Windows机器都设置为与时间服务器交谈,默认是time.windows.com。 用户会注意到他家的其余时钟有差异。 夏令时过渡日期错误是肯定可能的。 但是,如果你不想推翻用户的设置,他可能会住在靠近时区边界的一个县,选择退出DST或者像美国印第安部落地区那样自己制定规则的地方。

对这个世界上遥远的地方作出这样的决定是完全不同的一个蜡球。 值得注意的是萨摩亚岛,它在2011年跨越时区,甚至跨越从UTC-11到UTC + 13的日期线。 日光节约规则总是受到当地政治决策的影响,它们不会成为当地报纸的头条新闻。 它确实使它成为一个Web服务的一些可能性。 将城市映射到时区本身就是需要大量数据库的东西。 如果要求绝对的准确性,那么你真的需要一个服务。