4

这不是一篇关于技术本身的文章,而是一篇关于适当算法的文章。我希望我的用户能够将我的应用程序上的事件安排在每周的特定时间发生(他们将在我的网站上看到显示在他们的时区中)。

假设纽约的一位用户将事件安排在美国东部标准时间晚上 8 点发生。无论夏令时如何,我都希望该用户全年在美国东部标准时间每周 8 点发生该事件。

目前,我将时间值以 UTC 格式存储在我的数据库中,但 UTC 不会根据一年中的时间而改变。似乎某些时区确实有夏令时的概念,而有些则没有,这意味着如果我要即时进行任何时区转换处理(在任何查询日期以安排事件或显示之前)网站上的预定时间)我必须查看用户的时区是否支持夏令时以及目标时间戳是否在夏令时期间。

人们通常如何解决这类问题?换句话说,对于所有用户时区,我应该如何以最简单的方式在我的数据库中存储逻辑时间,正确显示它,使用它来正确调度任务,而不考虑夏令时?

4

3 回答 3

1

我会做一个假设,你的意思是“......在东部时间全年每周”。当您说 EST 时,您具体指的是东部标准时间。当 DST 适用时,它被称为东部夏令时间 (EDT)。

此外,缩写不是识别时区的好方法。我怎么知道您指的是美国的 EST (UTC-5) 而不是澳大利亚的 EST (UTC+10)?缩写是模棱两可的。你可以在这里看到一个相当全面的列表。

首先要做的是决定如何识别用户的时区。常用的数据库有两种:

Microsoft 时区数据库

专业人士

  • 内置于 Windows 操作系统。
  • 通过 Windows 更新自动部署的更新。
  • 易于从 Win32 或 .Net Framework 使用。

缺点

  • 由 Microsoft 而非标准机构或社区维护。
  • 区域往往非常广泛而不是精细。
  • 不适合历史时区变化。
  • 与非 Microsoft 服务器的互操作性可能很痛苦。
  • 更新频率较低。

IANA/奥尔森时区数据库

专业人士

  • 在 Linux、Mac、Java、PHP 和许多其他平台上广泛实现。
  • 库可用于JavaScriptWindows/.Net
  • 以典型城市命名的精致、独特的时区。
  • 包含时区更改的历史数据。
  • 在许多 RFC 和其他标准中引用。
  • 社区维护,最近由 IANA 支持。
  • 经常更新,一年几次。

缺点

  • 通常不会自动维护,尽管某些实现可能会这样做。
  • 有这么多区域,很难向您的用户呈现一个简单的下拉列表。良好的用户体验需要基于地图的时区选择器,例如这个。

现在您已经确定了您的用户所在的时区 - 让我们进入您最初问题的核心。在不考虑 DST 更改的情况下,您应该如何处理在同一本地时间的重复事件?

你实际上有两个不同的关注点,持久性和执行。

对于持久性(以及传输、显示等),您需要存储组合的本地时间和时区。例如,America/New_YorkIANA 区域中的晚上 8:00。如果可能,请在您的框架中存储此时间而不使用日期组件。不要将其转换为 UTC 或尝试针对 DST 进行调整。您只是以用户向您表达的方式捕获用户意图。

为了执行,您需要在特定的预定时间触发您的重复作业。您的作业正在运行的服务器可能完全位于不同的时区。您需要的是一系列 UTC DateTime 值,因此您可以将任务调度程序设置为在瞬间的特定时刻触发。您也可以为此使用本地时间加 utc 偏移量,例如DateTimeOffset在 .Net 中。这将具有在每个值上看到 8:00PM 的优势,即使偏移量在 -4 和 -5 之间切换。请参阅DateTime 与 DateTimeOffset

为了协调这两个概念,您需要一些代码来评估本地时间并计算执行时间戳。您可以在每个作业运行时设置下一个计划作业,或者您可以定期执行此操作并为未来的 X 个事件预测事件时间。这取决于你。如果您需要将未来的事件日期放在日历上 - 那么您当然需要后一种方法。

于 2013-03-08T14:46:33.843 回答
0

我会尽快转换为 UTC 并尽可能晚地退出 UTC,因为当国家在夏季结束时退出 DST 时,他们会将时钟调回去,并且一天中有两个小时的时间相同 -所以 DST 时间不能唯一地描述所有时间。

于 2013-03-07T05:22:25.817 回答
0

也许您可以使用任何公开可用的时区 API。例如。https://developers.google.com/maps/documentation/timezone/

于 2013-03-07T04:32:08.730 回答