Answers:
欢迎来到非计算编程中最困难的问题之一-正确地向最终用户表示日期和时间。
实际上,无论如何解释,都应将时间戳存储在固定的单一表示形式中,因为无论您多么努力,总是会出现歧义,而且如果没有固定的表示形式就无法解决。您已经选择了最糟糕的用例之一-安排约会。唯一最糟糕的常见用例是空中旅行,其中旅行可能在一个时区开始,而在另一个时区结束,可能在当地时间更早。
始终始终将UTC存储在UTC中,并在用户的首选或明确指定的时区中显示。 如果有可能,请让用户告诉您输入时相信的时间戳是哪个时区(例如,具有一个明确的时区字段,并使用其首选时区预填充该时区)。
处理日期/时间信息的最简单方法取决于应用程序的要求。
如果用户输入了日期和时间,并且服务器不对该日期/时间信息进行任何处理,只是将其存储在数据库中,并且不希望输入的时间适合查看的位置(例如,则用户输入了“ 8:00 PM”,并且无论在世界上哪个地方查看,都应该显示为“ 8:00 PM”),然后最简单的方法是将DateTime存储为本地时间而没有任何时区信息。
另一方面,如果服务器必须使用输入的DateTime作为执行某事的触发器,或者如果应该将时间正确调整为当前时区,那么最好的选择是将DateTime存储为UTC时间并将其调整为本地时间。每次从数据库中读取时间(针对用户的当前位置)。
不要混淆两个相关概念,这一点很重要。
如果要操纵实际时间点,即特定日期的特定时间,那么唯一的方法就是始终使用通用UTC时间值。 切勿尝试将其存储为与时区相关的值。向用户显示此时间值时,请始终转换为该用户的时区。(并且不要忘记时间和日期都取决于时区。)
另一个概念是“时间表达”的概念,例如“每个星期二8:00 PM”。您特别提到允许人员安排约会,如果您有定期约会,则需要这样的表达。我不知道任何标准表达语言,但是无论您使用什么语言,它都会与指定它的人所在的时区有关。最好将其标明,例如“太平洋时区的每个星期二晚上8:00 PM”。对于时间表达式,您始终将其存储为字符串,并且永远不涉及任何系统时间格式。
这里的许多答案都表示存储为UTC。但是要特别小心。例如,如果您将约会安排在12:00,但是约会发生在更改夏令时之后,那么会发生什么?在存储约会时,UTC不会保留有关dst是否处于活动状态的任何信息。许多大型的著名系统都犯了此错误,用户在夏季的上午9点发送电子邮件,然后在冬季的晚上8点发送电子邮件,因为从UTC返回的时间取决于您查看日期时间的时间,记录日期时间的日期。
更好的做法是假设您的用户希望始终拥有自己选择的时间。没有UTC转换,没有时间转换,没有时区信息,什么都没有。在2016年3月21日从08:00到12:00进行预约就是这样。不要使用本地时间或UTC时间,而是使用未指定的时间(在json中既没有z也没有+,基本上在.NET中没有DateTime.Kind = DateTimeKind.Unspecified)。
当然,如果您的用例是您是一家与来自不同时区的人举行会议的公司,并且您想在公司日历中查看此信息,但允许用户查看他们所在时区的时间,变得更加复杂。对于不同时区的不同人员(供应商和客户),时间必须正确。
在这种情况下,你甚至可能要录制时预约保存到数据库中,在什么时区以及如果包含DST与否。这样,您始终可以将本地时间计算为其他时间,无论是现在的时间还是历史的预期时间。因为时区在很大程度上不是静态的,所以使事情变得更加复杂。
幸运的是,强烈推荐使用http://nodatime.org/之类的库。他们使用日期更加一致。即使那样,我还是建议您使用接口将所有日期时间变量和逻辑包装在自己的包装器中,以便可以对它们进行模拟,然后您以后仍可以切换逻辑。