如何正确使用Timezone?

Fel*_*sso 7 javascript c# timezone utc datetimeoffset

我正在阅读很多关于时区,偏移,utc,当地时间,javascript函数,DST,培根的内容,而我正试图将这些内容整合在一起,为我的应用程序构建一个可靠/正确的结构.

假设我的应用程序类似于StackOverflow.

这就是我在做的......

  • 服务器在另一个国家/地区,因此我将其设置为UTC 00:00.
  • 我把日期存储为DateTimeOffset.
  • 不是要存放TimeZoneID.
  • 日期以这种格式发送给客户:2012-07-19T14:30:00-03:00.
  • 我正在使用角度过滤器将其转换为当地时间.

我有几个问题......

1º服务器TimeZone?

关于我的服务器(单个服务器)......它应该以"中性"UTC(+00:00)运行吗?如果将来我们迁移到服务器在不同位置运行的服务器场,该怎么办?

2º我应该存储什么?

目前,我正在将日期存储为DateTimeOffset.我正在阅读关于保存的内容,TimeZoneID但我认为没有任何用处.我错过了什么吗?

或者我应该像DateTimeUtca 一样存储日期TimeZoneID并手动转换每个日期与TimeZone班级?

3º如何转换为当地时间?

在客户端上转换数据是否安全?或者日期转换应该始终在服务器端?

4º关于夏令时.

使用我目前的方法.DST会受到尊重吗?

Mat*_*int 9

理解日期/时间的一个非常重要的事情是,没有一种正确的方法可以做任何事情.常用答案"使用UTC" 并不总是适用.上下文非常重要,并且根据您正在使用的值表示的内容有不同的技术和方法.如果您可以详细说明它们在您的应用程序中的用途,我将相应地更新我的答案.与此同时,我将尝试解决您已提出的具体问题:

#1 - 服务器时区

将您的服务器保持在UTC是最佳做法,而您也可以从Azure或AWS等云提供商那里获得.但这不是你应该依赖的东西.您的服务器应该能够设置为任何时区而不会影响您的应用程序.只要时钟与NTP服务器同步,时区的选择就无所谓了.

那么你如何确保呢?很简单,只需确保您的应用程序避免以下所有情况:

  • DateTime.Now
  • DateTimeKind.Local
  • TimeZone (全班)
  • TimeZoneInfo.Local
  • DateTime.ToLocalTime()
  • DateTime.ToUniversalTime() (因为它假设输入是本地的)
  • 杂项.假设本地输入或输出的其他方法,例如TimeZoneInfo.ConvertTimeToUtc(DateTime)(此特定过载不占用时区,因此它假定本地时区)

另请参阅我的博客文章:The Case Against DateTime.Now.

请注意,我没有列入DateTimeOffset.Now清单.虽然它有一点点设计气味,但使用它仍然是"安全的".

#2 - 存储什么

我建议你阅读我对DateTime vs DateTimeOffset的回答.它应该澄清一些事情.没有反思整个事情,重点是虽然两者都准确地代表了一个时间点,但是DateTimeOffset提供了视角,而UTC DateTime却没有.

你还问过什么时候应该存储一个TimeZoneInfo.Id.至少有两种情况需要:

  • 如果您要记录过去或现在的事件,并且您计划允许修改记录的时间戳.您需要时区来确定新偏移量应该是什么,或者新输入如何转换回UTC.

  • 如果您计划将来的时间,则需要将时区作为重复模式的一部分(即使是一次出现).在这里这里也可以看到(对于其他语言,同样的原则适用).

同样,确切的答案取决于时间戳代表的确切内容.没有一个戒指来统治它们.

#3 - 客户安全

如果它是.NET客户端,请确保您可以转换它.但我想你是在问一个JavaScript客户端浏览器.

"安全"是一个相对术语.如果你要求完全正确,那么不.由于ECMAScript规范中的错误(ES1到ES5.1.它正在为ES6工作),JavaScript并不安全.您可以在我的博客文章中阅读更多内容:JavaScript日期类型非常糟糕.

但是,如果您正在处理相对最新的数据,并且您的应用程序的用户不属于时区易变的世界的一部分,或者您不需要100%的精确结果,那么您可以"安全地" "使用JavaScript转换为用户的本地时区.

您可以避免使用JavaScript实现IANA TZDB的库中的某些问题,例如我在此处列出的那些.但是他们中的许多人仍然依赖于JS Date,所以他们仍然有问题.(旁注 - 我正在研究一个可以解决这个问题的JS库,但尚未准备好分享).

只要您可以询问用户他们的时区,服务器端的转换是一个更好的选择.大多数时候,我认为这是可行的.

您可以考虑使用基于地图的时区选择器,例如这一个这个.这两个都需要你使用IANA时区,对于.NET来说意味着使用Noda Time,这无论如何都是一个好主意(恕我直言).

#4 - 夏令时

使用您当前的方法,DST将在用户为其本地浏览器设置的时区的当前 DST规则的定义中受到尊重.(再次,请参阅我的博客文章,了解为什么会这样).

从具有偏移(是否有任何值A变换-03:00Z),其通过穿过Date对象(我认为一个角度滤波器都行),将正确地转换为特定的Unix时间戳.

使用先前DST规则的DST转换时出现的错误是因为从Date对象内部的unix时间戳到本地时区将始终假定当前 DST规则适用,即使时间落入具有不同的规则.