存储用户时区首选项

Mat*_*don 6 .net c# timezone

我的要求是相当标准的; 我需要允许用户选择他们当前的TimeZone并将其保存在他们的帐户中.然后,我将使用此值将存储的DateTime值转换为本地化的时间.

我目前的想法是,我将允许用户TimeZoneInfo.Id从列表中选择一个.NET (在数据库中保存以允许更友好的描述但使用构造TimeZoneInfo.GetSystemTimeZones()) - 然后我将使用此值返回相关TimeZoneInfo实例TimeZoneInfo.FindSystemTimeZoneById()并执行转换.我在这里看到的主要问题是,它TimeZoneInfo.Id是注册表中保存的值,并不是"标准"ID(例如,与Olson相比).因此,服务器更新/迁移可能会使存储的ID完全无效并中断转换.

简而言之 - 这种方法有效/安全吗?如果没有,是否有更好的方法来存储用户时区偏好,同时还可以处理夏令时等而无需额外的逻辑?

Mat*_*int 8

我刚刚发现了这个没有答案的老问题,所以我认为我应该抓住它.

简而言之 - 这种方法有效/安全吗?

这一切都取决于你打算用它们做什么.

如果您只是在服务器端代码中使用它,那么是的.您只需存储Id时区,并向用户显示相应的时区DisplayName. FindSystemTimeZoneById并且GetSystemTimeZones完全有效.

请记住,虽然Id值始终相同 - 但是DisplayName根据您运行代码的Windows操作系统的语言,属性会有所不同.实现不是文化意识,所以只在.Net中设置不同的目标文化不会改变DisplayName字符串.

Microsoft Windows时区数据库中的记录相当稳定,并通过Windows Update保持更新. 一些信息来自注册表,但本地化的资源字符串来自tzres.dll.当然,所有这些都是由TimeZoneInfo相关类隐藏的.

但是,如果您将这些时区Id值传递给其他系统 - 请注意.Windows的早期版本有一些变化.例如,我知道所有显示名称都使用"GMT",现在更准确地说"UTC".该Id值是相同的,但谁知道是不是一致的到底是什么东西.特别是如果目标计算机没有收到您拥有的同一组Windows更新.顺便说一句 - 更新在这里公布.

您还应该了解有关Windows时区数据库的一些信息:

  • 它无法在每个日历年代表两个以上的DST转换.例如 - 在2010年,埃及开罗有四次过渡.微软发布了一个修补程序,但这只是进行了妥协修正,而不是历史上准确的修正.还有其他区域具有此类历史更改,无法正确表示.

  • Windows XP/2003和Vista/2008之间发生了一些变化.有关于这一些非常好的信息,在这里,与有关注册表是如何使用的很多细节一起.

  • Microsoft是唯一拥有自己的时区数据库的主要玩家.世界其他地方使用IANA/Olson数据库.这导致了互操作性问题.我在timezone标签wiki中对此进行了大量的写作.

您还应该知道它TimeZoneInfoDateTimeDateTimeOffset类有着千丝万缕的联系.这些都有各自的怪癖. DateTimeOffset有点可用,但DateTime充满了细微差别.读:

一个更好的解决日期和时间在.NET是使用NodaTime.此库实现两个时区数据库,包括它们之间的CLDR映射.它还提供了更安全的API,不会让您遇到麻烦.这可能需要一点重新学习,但你知道它之前,你可以使用像这样的类LocalDateTime,ZonedDateTime,OffsetDateTimeInstant.

您仍然遇到时区数据库经常更新的问题,因为我们将计时规则留给了政治家.但是,TZDB人员在保持数据库历史准确性方面做得非常好,并在区域名称更改时提供别名/链接.您可以在此处查看tz名称列表.

此外,如果你使用NodaTime,你可以选择坚持编译到发行版中的TZDB副本,或者你可以随应用程序发送你自己的副本.您可以(理论上)编写自己的代码以从IANA下载最新版本并保持应用程序更新 - 所有这些都不依赖于主机操作系统.