65.9K
CodeProject 正在变化。 阅读更多。
Home

每个开发者都应该了解的时间

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.80/5 (3投票s)

2011 年 2 月 18 日

CPOL

5分钟阅读

viewsIcon

18060

处理时间的基本介绍

引言

如何处理时间是那些棘手的问题之一,很容易出错。所以,让我们深入探讨一下。

首先,使用 UTC(也称为格林威治标准时间)通常不是正确的解决方案。然而,许多程序员认为,如果他们以这种方式存储一切,那么他们就万事大吉了。(正是这个错误,使得几年前当美国国会改变夏令时(DST)的开始日期时,你不得不为 Outlook 打一个热补丁,才能调整它重复出现的事件。)

什么是时间

那么,让我们从关键问题开始——我们所说的“时间”是什么意思?当用户说他们希望某件事在早上 7:00 运行,他们指的是什么?在大多数情况下,他们指的是他们所在位置的早上 7:00——但并非总是如此。在某些情况下,为了准确地比较,例如网络服务器统计数据,他们希望每个“天”在同一时间结束,不受夏令时调整。另一方面,那些在一天中的特定时间服用药物并将其设置在日历中的人,会希望它始终是本地时间,这样当他们旅行到世界另一端时,下午 3:00 的事件就不会变成凌晨 3:00。

所以,这里有三种主要的使用场景(还有一些其他的,但它们通常可以由以下方法处理)

  1. 相同的绝对(就为更好词而言)时间。
  2. 给定时区的本地时间,当夏令时开启/关闭时会发生变化(包括某些地区发生的双重夏令时)。
  3. 本地时间。

第一个很容易处理——将其设置为 UTC。通过这样做,一年中的每一天都将有 24 小时。(有趣的是,UTC 仅在标准时间内与格林威治时间匹配。当格林威治时间处于夏令时时,格林威治时间和 UTC 并不相同。)

第二个需要存储时间和时区。然而,时区是地理区域,而不是当前的偏移量(偏移量是与 UTC 的差异)。换句话说,你存储的是“山地时间”,而不是“山地标准时间”或“山地夏令时”。所以,“山地时间”的早上 7:00 将是科罗拉多州当地的早上 7:00,无论一年中的什么时间。

第三个与第二个相似,因为它有一个称为“本地时间”的时区。然而,它需要知道它在哪一个时区才能确定它何时发生。

实际应用

好的,那么你该如何处理呢?其实很简单。每次时间都需要以两种方式之一存储:

  1. 以 UTC 形式存储。通常,当以 UTC 存储时,你仍然会将其设置为/显示为本地时间。
  2. 以日期时间加上地理时区(可以是“本地时间”)的形式存储。

现在,诀窍在于知道使用哪种方式。以下是一些通用规则。你需要为其他使用场景弄清楚这一点,但大多数都属于这些类别。

  1. 某事发生的时间 – UTC。这是一个单一事件,无论用户希望如何显示,它发生的时间是不可改变的。
  2. 当用户选择 UTC 时区 – UTC。
  3. 将来的事件,用户希望它发生在某个时区 – 日期时间加上一个时区。现在,如果它将在未来几个月内发生,使用 UTC 可能是安全的(更改时区通常有如此多的警告——尽管有时只有 8 天——但总有一天你需要这样做,所以你应该为所有情况这样做。在这种情况下,你显示你存储的内容。
  4. 对于计划事件,何时会发生 – UTC。这是一个性能要求,你希望能够获取所有“下一个事件”,其运行时间在现在之前。搜索日期比重新计算每个事件要快得多。然而,这确实需要定期重新计算所有计划事件,以防运行每个季度的事件的规则发生变化。
  5. 对于“本地时间”的事件,当用户时区改变时,应随时发生重新计算。如果事件在更改时被跳过,它需要立即发生。

浏览器难题

我们还没有解决的一个问题是,如果用户使用浏览器访问我们的 Web 应用程序,我们如何知道用户的位置。对于大多数国家,可以使用区域设置来确定时区——但对于美国(6 个区域)、加拿大或俄罗斯(11 个区域)则不行。所以,你必须要求用户设置他们的时区——并在他们旅行时更改它。如果有人知道解决方案,请告诉我。

更新:我收到了 Justin Bonnar 的以下信息(谢谢)

<input id="timezone_offset" type="hidden" name="timezone_offset" value="">
<script type="text/javascript">
document.getElementById('timezone_offset').value = new Date().getTimezoneOffset();
</script>

使用该信息以及下面提到的 IP 地址的地理位置建议,你会接近。但并非 100% 准确。时间偏移量并不能告诉你,例如,如果你在美国亚利桑那州(他们和夏威夷都不遵守夏令时)还是太平洋/山地(取决于夏令时)时区。你还依赖于 JavaScript 的开启,尽管这对于当今 99% 的用户来说都是如此。

基于 IP 地址的地理位置也有些不可靠。我在华盛顿特区的一家酒店,当时我收到了一份关于我们演示下载表单出现问题的报告。我们根据 IP 地址的地理位置预先填充了城市、州和国家。它显示我在俄亥俄州的克利夫兰。所以,再一次,通常是对的,但并非总是如此。

我的观点是,我们可以使用偏移量,并且对于具有相同偏移量的多个时区(在给定日期),再通过 IP 地址的地理位置进行后续处理。但我真希望有关当局能在发送给 HTML 请求的头部信息中添加一个 tz=

资源

  • 原始文章(包含 Outlook 如何很好地处理此问题的截图)

历史

  • 2011 年 2 月 18 日:初始帖子
© . All rights reserved.