因为我认为时区问题对日历应用程序很重要,并且一些现有的应用程序不能很好地处理这个问题(甚至是 Outlook,2007 年之前),所以我将此信息添加为答案,并作为先前评论的后续行动。
我希望 Google 开发人员也能阅读这篇文章,因为基于http://support.google.com/calendar/answer/2367918?hl=en,他们似乎也有“转移”问题。这是他们所说的,这对我来说似乎是错误的/不可接受的:
但是,如果一个国家/地区决定在切换到 DST 甚至整个时区时进行更改,则此过程并不总是有效。如果您在我们知道更改之前创建了活动,日历会使用创建时可用的信息将您的时区转换为 UTC。知道时区更改后,日历将使用新规则在您的时区显示事件,这可能会导致事件在您的日历中发生变化。
粗体字的最后一部分是不应该发生的事情。如果我将会议设置为太平洋标准时间上午 8 点,它将在太平洋标准时间上午 8 点举行,它不会仅仅因为某些时区规则发生变化而“转移”。
在日历应用程序中,如果用户输入“2020 年 4 月 26 日下午 12:00,亚利桑那时间”的事件。如果您将其转换为 UTC 进行存储,就像大多数应用程序一样,您将把它保存为(使用我输入 ths 时的规则)“2020 年 4 月 26 日,下午 7:00,UTC”。
然后,如果您想查询“2020 年 4 月 26 日下午 12:00,亚利桑那时间”是否有任何事件发生,您将查询“2020 年 4 月 26 日,下午 7:00,UTC”,因为那是当前的转换规则告诉你要做的。
起初你会找到这个项目,正确的,是的。
现在,如果时区规则发生变化,比如说在 2018 年,亚利桑那州变为 -0800 UTC 而不是 -0700 UTC(也许他们决定支持 DST,谁知道呢)。然后您再次进行查询,查找在“2020 年 4 月 26 日下午 12:00,亚利桑那时间”发生的任何事件。这一次,当您进行查询时,您将寻找“2020 年 4 月 26 日,晚上 8:00,UTC”。这是因为您在进行查询时只知道使用当前规则,而您不知道某些数据在保存时使用了旧规则。 因此,即使您应该找到该项目,您也找不到该项目,并且用户错过了该事件。
现在,您决定显示该项目的方式因应用程序而异,但对于日历/日程安排应用程序,它永远不应更改用户输入的时间。当用户查看它时,它仍应显示为“2020 年 4 月 26 日,下午 12:00,亚利桑那时间”。但是,由于规则更改,您用于查询的 UTC 值与该时间不匹配。
一个好的日历应用程序应该处理这个问题的方式(从我经过大量研究后了解到的)是:
- 存储用户每次输入的以下信息:
时区(在 Windows 中,我使用 Windows 时区 ID,但这可以来自其他来源,只要它是唯一的并且是您用来进行转换的)。
用户输入的日期和时间
使用用户输入信息时的规则将日期和时间转换为 UTC(问题区域)
- 每当时区规则发生变化时,请确保您的转换代码已更新(即 Windows 更新、库更新等),并且在同一更新过程中,使用新规则更新数据库中的所有 UTC 时间。
“更新”过程是这样的:
查询更改时区的所有记录。如果需要,可以过滤在规则更改之后具有日期的记录,因为之前的任何记录都没有更改(这将基于用户输入的日期,而不是 UTC 值)。
对于这些记录中的每一个(如果您没有精确过滤,或者即使您只是对每个时区的数据库中的每条记录进行盲目操作,也没有关系)...运行您在记录时执行的相同转换代码最后添加/编辑,只需获取用户输入的值并使用当前规则将其转换为 UTC,然后保存新的 UTC 值。
需要这种混乱的证据是结果将是您的某些 UTC 值已更改,并且用户输入的值都没有更改(因为我们不能允许这样做,这对于日历应用程序来说是愚蠢的,除非事件时间基于 UTC,在这种情况下,用户应该在添加时区时将时区设置为 UTC)。
想想如果您不执行此更新过程会发生什么。您基于 UTC 所做的所有查询都不正确。他们怎么可能不是?