我会做一个假设,你的意思是“......在东部时间全年每周”。当您说 EST 时,您具体指的是东部标准时间。当 DST 适用时,它被称为东部夏令时间 (EDT)。
此外,缩写不是识别时区的好方法。我怎么知道您指的是美国的 EST (UTC-5) 而不是澳大利亚的 EST (UTC+10)?缩写是模棱两可的。你可以在这里看到一个相当全面的列表。
首先要做的是决定如何识别用户的时区。常用的数据库有两种:
Microsoft 时区数据库
专业人士
- 内置于 Windows 操作系统。
- 通过 Windows 更新自动部署的更新。
- 易于从 Win32 或 .Net Framework 使用。
缺点
- 由 Microsoft 而非标准机构或社区维护。
- 区域往往非常广泛而不是精细。
- 不适合历史时区变化。
- 与非 Microsoft 服务器的互操作性可能很痛苦。
- 更新频率较低。
IANA/奥尔森时区数据库
专业人士
- 在 Linux、Mac、Java、PHP 和许多其他平台上广泛实现。
- 库可用于JavaScript和Windows/.Net。
- 以典型城市命名的精致、独特的时区。
- 包含时区更改的历史数据。
- 在许多 RFC 和其他标准中引用。
- 社区维护,最近由 IANA 支持。
- 经常更新,一年几次。
缺点
- 通常不会自动维护,尽管某些实现可能会这样做。
- 有这么多区域,很难向您的用户呈现一个简单的下拉列表。良好的用户体验需要基于地图的时区选择器,例如这个。
现在您已经确定了您的用户所在的时区 - 让我们进入您最初问题的核心。在不考虑 DST 更改的情况下,您应该如何处理在同一本地时间的重复事件?
你实际上有两个不同的关注点,持久性和执行。
对于持久性(以及传输、显示等),您需要存储组合的本地时间和时区。例如,America/New_York
IANA 区域中的晚上 8:00。如果可能,请在您的框架中存储此时间而不使用日期组件。不要将其转换为 UTC 或尝试针对 DST 进行调整。您只是以用户向您表达的方式捕获用户意图。
为了执行,您需要在特定的预定时间触发您的重复作业。您的作业正在运行的服务器可能完全位于不同的时区。您需要的是一系列 UTC DateTime 值,因此您可以将任务调度程序设置为在瞬间的特定时刻触发。您也可以为此使用本地时间加 utc 偏移量,例如DateTimeOffset
在 .Net 中。这将具有在每个值上看到 8:00PM 的优势,即使偏移量在 -4 和 -5 之间切换。请参阅DateTime 与 DateTimeOffset。
为了协调这两个概念,您需要一些代码来评估本地时间并计算执行时间戳。您可以在每个作业运行时设置下一个计划作业,或者您可以定期执行此操作并为未来的 X 个事件预测事件时间。这取决于你。如果您需要将未来的事件日期放在日历上 - 那么您当然需要后一种方法。