将所有内容存储为 GMT?

按照嵌入偏移量输入的方式存储所有内容?

每次渲染时都进行数学计算吗?

显示相对时间“1 分钟前”?

有帮助吗?

解决方案

您必须以 UTC 格式存储 - 如果您不这样做,您在夏令时等情况下的历史报告和行为将会...有趣的。GMT 是当地时间,相对于 UTC 实行夏令时(但并非如此)。

如果您存储的是本地时间,那么向不同时区的用户进行演示可能会很糟糕。如果您的原始数据采用 UTC 格式,则很容易调整为本地 - 只需添加用户的偏移量即可完成!

乔尔在一个播客中谈到了这一点(以一种迂回的方式)——他说 以尽可能最高分辨率存储您的数据 (搜索“保真度”),因为当它再次熄灭时你总是可以咀嚼它。这就是为什么我说将其存储为 UTC,作为当地时间,您需要为不在该时区的任何人进行调整,这是一项艰巨的工作。例如,您需要存储存储时间时夏令时是否有效。哎呀。

过去我经常在数据库中存储两个 - UTC 用于排序,当地时间用于显示。这样用户和计算机都不会感到困惑。

现在,关于显示:当然,您可以执行“3 分钟前”的操作,但前提是您存储 UTC - 否则,在不同时区输入的数据将会执行诸如显示为“-4 小时前”之类的操作,这会让人们感到害怕。如果您要显示实际时间,人们喜欢使用当地时间 - 如果数据是在多个时区输入的,则只有存储 UTC 时才能轻松做到这一点。

其他提示

一如既往,答案是“取决于”。

这取决于您所描述的时间以及数据是如何提供给您的。决定如何存储时间值的关键是确定是否会因删除时区而丢失信息,以及不要让用户感到惊讶。

在 UTC time_t 中存储数据有明显的好处 - 它是单个 int,允许快速排序和轻松存储。

我认为问题被分解为特定领域:

  1. 历史数据
  2. 未来、短期数据
  3. 未来的长期数据

每个都有以下子类:

  1. 系统提供
  2. 用户提供

让我们一次一个地看它们。

系统提供:我建议在 UTC 中运行系统,这样就可以避免时区问题,并且不会出现任何信息丢失(始终是 UTC)。

历史数据:这些是系统日志文件、进程统计信息、跟踪、评论日期/时间等。数据不会更改,时区描述符也不会追溯更改。对于此类数据,无论提供的时区如何,以 UTC 存储信息都不会丢失任何信息。所以,放弃时区。

未来的长期数据:这些事件要么是遥远的未来,要么将继续发生。如果它们保留足够长的时间,时区描述符一定会发生变化。此类数据的一个很好的例子是“每周管理会议”。这是输入一次的数据,预计将永久有效。对于这些值,确定它是系统提供的还是用户提供的非常重要。对于用户提供的数据,时间应与创建者的时区一起存储,其他任何情况都会导致信息丢失。当时区定义发生变化并且向创建者显示的时间具有完全不同的值时,这种信息丢失就会变得明显!

正如 Bwooce 所指出的,创作者和观众位于不同时区,这会造成一些混乱。在这种情况下,我希望应用程序能够指示哪些时间值由于时区与之前位置的变化而发生了移动。

未来、短期数据:这些数据很快就会成为历史数据,或者仅在短时间内有效。例如间隔计时器、评级转换等。对于此数据,由于定义在值的创建和成为历史的时间之间发生变化的可能性很低,因此可能无需删除时区。然而,我发现这些值有一个坏习惯,会成为“未来的长期数据”。

一旦决定存储时区,就必须注意它的存储方式。

  • 不要将时区存储为偏移量或完整描述符。

如果您将时区存储为偏移量,那么如果时区发生变化,您会怎么做?您是否检查系统并对现有数据进行全面更改?如果您这样做,那么您现在就已经将所有历史值设置为不正确的了。Oracle 和 iCal 就是这种错误的典型例子。Oracle 将时区信息存储为与 UTC 的偏移量,iCal 包含创建时区的完整描述符。

  • 请将其存储为名称。

这允许更改时区的定义,而无需修改现有值。它确实使排序变得更加困难,因为如果时区数据发生更改,生成的任何索引都可能无效。

如果开发人员继续以 UTC 存储所有内容,而不管时区如何,我们将继续看到上一批时区更改中出现的问题。

在一个组织中,秘书们必须在夏令时之前为其团队打印日历,然后在更改后再次打印。最后,他们对两者进行了比较,并重新创建了所有已移动的约会。当然,他们错过了几个,并且经历了几周的痛苦,直到旧的夏令时日期到来并且时间再次变得正确。

乔什在上面完全正确,但我有一个微妙的警告需要解释。这是一个关于未来事件和时区没有正确答案的案例。

考虑重复约会的情况。它发生在 GMT 0000(为简单起见),即 NZST(新西兰标准时间)1200 点和澳大利亚悉尼 AEST 1000 点。

当夏令时在某一区域生效时,预约会发生什么情况?应该是:

1a.如果TZ更改位于任命的“所有者”(谁预订)的区域中,那么请尝试在同一桌子时钟时间(例如10:00 am)?
1b.如果TZ的更改是在另一个会议与会者的区域之一中

结果:由于所有者的变更,它出乎意料地为其他所有人带来了行动,但就所有者而言,它一直保持“上午10点会议”。

'2.如上所述,但相反。

结果:它会为会议所有者移动(上午 10 点的会议变成上午 9 点的会议,或 v/v),这可能是预料之中的,但不方便。对于其他与会者来说,它保持相同的桌面时钟时间,直到他们完成自己的 TZ 转换。

两者都不完美。考虑两次约会的情况,一次由 A 预订,发生在当地时间上午 10 点,另一次由 B 预订,A 作为与会者,发生在上午 9 点。如果 A 和 B 位于不同的 TZ,那么 DST 更改很容易导致他们被重复预订。

如果此时你的想法有点偏执,那么我很理解。

这个例子背后的要点是,要正确执行这些行为,您不仅需要知道当地时间的 UTC 版本,还需要知道所有者预订时所在的 TZ(而不是偏移量)。否则你别无选择,只能默默地采取选项 2,甚至不通知任何人事情发生了变化,因为 GMT 时间没有改变,只有演示文稿发生了变化......对吧?(不,这是陷阱,当上午 10 点的会议自行进行时,演示很重要)

我必须感谢我的同事兼朋友杰森·波洛克(Jason Pollock)的这一见解。读 他的观点在这里, ,以及后续讨论 iCal 和 VTIMEZONE 这里。

对我来说,以 GMT/UTC 存储所有内容似乎最合乎逻辑。然后,您可以显示所需的每个时区的日期和时间。

一些注意事项:

  1. 如果仅将时间指定为壁时钟时间,而这是领先表示,那么它不是绝对指定的时间。您应该(也不能)将其转换为任何GMT表示。例如。每天早上9:00。换句话说:这不是(日期)时间。
  2. 如果保留将来约会的日期和时间,则应将输入时区和GMT的偏移使用。 时间本身. 。因此,如果这是冬季夏天的约会,例如西欧是+2:00,但正常(冬季)偏移量为+1:00。这将解决BWOOCE提到的紧密问题。
  3. 当然,在转换为GMT时,适用于使用右偏移的同样,在任何特定时区中转换为日期和时间时也适用。

幸运的是,如果使用正确,(.NET) DateTime 类型会处理保存日历等的所有细节。对于您来说,当您知道它是如何工作时,所有这一切都应该非常容易。

就我个人而言,我看不出有什么理由不将所有内容存储在 GMT 中,然后使用用户本地时区来显示与他们相关的时间。

如果你想显示相对时间,显然你仍然需要时间并进行翻译,但如果你确实想进行翻译,我认为 GMT 仍然是你最好的选择。

所以我用 MSSQL 服务器做了一个小实验。

我创建了一个表并添加了一行包含当前本地时区(澳大利亚)的行。然后我将日期时间更改为 GMT 并添加了另一行。

尽管这些行是相隔大约 10 秒添加的,但它们在 SQL Server 中显示的时间间隔却是相隔 10 小时。

如果不出意外,它至少告诉我应该以一致的方式存储日期,这对我来说,增加了将日期存储为 GMT 的论点。

MS Dynamics 存储 GMT,然后在用户级别了解您相对于 GMT 的时区。然后它会向您显示您所在时区的项目。

只是想我会把它扔掉,因为微软有一个相当大的团队,这就是他们决定处理它的方式。

我更喜欢用时区存储所有内容。客户可以决定稍后以哪种方式呈现。我最喜欢的转换库是 PostgreSQL-数据库.

看看这里,w3c 已经很好地回答了这个问题。

查看用例。

http://www.w3.org/TR/timezone/

请注意,他们建议将日期时间存储为 UTC 而不是 GMT,GMT 受夏令时限制。

我喜欢以 GMT 格式存储并仅显示相对时间(“大约 10 秒前”、“5 个月前”)。对于大多数用例,用户不需要查看实际时间戳。

当然也有例外,并且单个应用程序可能有很多例外,因此它不可能是“单向”答案。需要强大审核能力的事物(例如投票),而时间是讨论领域(天文学、科学研究)一部分的系统可能需要向用户显示真实的时间戳。

不过,大多数应用程序通过简单的相对时间更容易理解。

我通常只使用 Unix 时间。未来不一定安全,但效果很好。

始终以 GMT(或 UTC)存储。从那里可以轻松转换为任何本地时区值。

日期应存储为 UTC,除非它是用户提供的数据,并且您无法知道用户希望该数据位于哪个时区。有时(非常非常罕见),您只需要存储小时、分钟、秒、日、月和年部分,而不需要任何时区,以便您可以将其返回给用户。现在,对于新开发人员或者如果您不确定,请存储 UTC,您的正确率将达到 99%。

但不要误以为这对于所有情况都 100% 有效。它不是。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top