我真的应该将餐桌预订时间保存为 UTC 吗?

Kca*_*evo 4 .net c# timezone datetime

这可能是一个愚蠢的问题,我提前道歉,但考虑到业务背景,我是否真的需要在数据库中以 utc 格式保存餐桌预订时间,并担心将其转换为网络客户端上的本地时间?

预订将始终针对特定位置(地理/城市)进行,因此无论当前与 UTC 的时间偏移是什么(夏令时或非夏令时等),下午 3:00 的预订时间都是下午 3:00 的预订时间对于那个位置,无论是未来还是过去。这不是在网上举行的活动,而是餐厅的现场活动。

我觉得即使我们要开始在另一个时区明显不同的国家(比如西班牙)预订,这也将成立。仅仅因为伦敦的 3:00 与西班牙的 3:0 是不同的时间(UTC),对系统来说并没有多大影响..?

我在这里遗漏了一些非常明显的东西吗?我是否可以简单地忽略处理不同的时区,而只是将时间保存在数据库中而不带偏移量(假设所有时间都是本地时间,该位置的本地时间)?

Mat*_*int 6

鉴于你说:

...但是考虑到业务环境,我是否真的需要将餐桌预订时间以 utc 格式保存在数据库中,并担心将其转换为 Web 客户端上的本地时间?

...这不是在网上发生的活动,而是餐厅的现场活动。

对于此用例,您不应使用UTC。您并不是记录某件事发生的绝对时间点(现在或过去),而是捕获有关未来事件预计发生的时间和地点的意图。

  • 输入预订日期和时间时,客户提供意图的“时间”部分。他们按照餐厅的当地时区提供。将其转换为 UTC 或其他时区可能会失去该意图。

    • 假设这是一次预订(不是重复规则),那么在 .NET 中,您可以DateTime为此使用一个类型,并将其Kind属性设置为DateTimeKind.Unspecified(在许多情况下这是默认值)。
  • 当您设置系统或添加新的餐厅位置时,意图的“哪里”部分由您提供。最好在系统中保留每个餐厅设置或记录的时区标识符,而不是暗示它。

    • Id在 .NET 中,您应该使用与对象属性相对应的字符串值TimeZoneInfo。它可以是 IANA 时区 ID(例如"Europe/London")或 Windows 时区 ID(例如"GMT Standard Time")。根据 .NET 的实现方法和版本,您可能能够在任何平台上支持其中任何一个。(如果您可以选择,我强烈建议您使用 IANA 时区 ID。)

在这种情况下,您只应该考虑一种边缘情况。问问自己,您的餐厅是否可能在一天中可能发生回退过渡的时间附近有预订?

  • 当本地与 UTC 的偏移量减小时,例如 DST 结束时(例如,伦敦的 BST 变为 GMT),或者政府修改时区的标准偏移量时,偶尔会发生这种情况。

  • 如果答案是“否”,那么您不需要做任何其他事情。由于大多数餐厅在这些过渡发生时不会在很晚的时间内预订餐桌,因此我怀疑您可能就是这种情况。

  • 如果答案是“是”,那么您在预订时需要某种方式来消除歧义。例如,如果有人在2021-10-31at预订了一张桌子01:00,您可能想问他们的意图是01:00 BST(第一次出现)还是01:00 GMT(第二次出现)——因为那天是夏令时结束时时钟倒退的那一天。一个简单的布尔值可以存储这个意图。

如果您正在考虑使用基于 UTC 的DateTime或 a DateTimeOffset,我会请您考虑我关于捕获意图的观点。例如,您可能认为一家餐馆(位于伦敦)2021-10-30T18:00:00+01:00在 a 中记录预订时间DateTimeOffset或其等效的 UTC 值2021-10-30T17:00:00Z在 a 中没有任何问题DateTime。问题变成了 - 如果规则在活动预订时和活动发生时发生变化怎么办?也许政府提前一周结束夏令时,或者完全停止使用它。这种不规则的变化在世界各地的不同时区已经发生过很多次,而且总是有可能在任何地方再次发生。一般来说,事件发生的时间越长,我们就越不可能预测当时与 UTC 的偏移量。(对于给出的示例,您应该捕获:2021-10-30T18:00:00"Europe/London"。)

如果您正在处理重复发生的事件,这个问题会更加严重,因为偏移量可能会在夏令时开始或结束时定期发生变化。虽然我不确定餐厅是否会预订重复餐桌,但这种情况确实会发生在重复会议、每日闹钟和其他周期性事件中。

我只想说,总会有人说“始终使用 UTC”,但这种建议是短视的。总会有 UTC 不合适的用例,未来的调度肯定是其中之一。