这是一个很难的问题。事实上,它似乎很难,SQL 标准和大多数主要数据库在它们的实现中都没有线索。
将所有日期时间转换为 UTC 可以轻松比较记录,但会丢弃时区信息,这意味着您不能对它们进行计算(例如,将 8 个月添加到存储的日期时间),也不能在它们存储的时区中检索它们。所以幼稚的方法就出来了。
除了时间戳之外存储与 UTC 的时区偏移量(例如,在 postgres 中带有时区的时间戳)似乎就足够了,但是由于 DST,不同的时区可以在一年中的某个时间点具有相同的偏移量,并且在 6 个月后具有不同的偏移量. 例如,您现在(8 月)可以在 UTC-4 拥有纽约和智利,但 11 月 4 日之后,纽约将是 UTC-5,智利(9 月 2 日之后)将是 UTC-3。因此,仅存储偏移量也不允许您进行准确的计算。像上面的幼稚方法一样,它也丢弃了信息。
如果您将时区标识符(例如 America/Santiago)与时间戳一起存储会怎样?这将允许您区分智利日期时间和纽约日期时间。但这还不够。如果您要存储到期日期,例如 6 个月后的午夜,并且 DST 规则发生变化(不幸的是政客们喜欢这样做),那么您的时间戳将是错误的,并且到期可能发生在晚上 11 点或凌晨 1 点。这对您的应用程序可能或可能不是什么大问题。所以使用时间戳也会丢弃信息。
似乎要真正准确,您需要使用时区标识符存储本地日期时间(例如,使用非时区感知时间戳类型)。为了支持更快的比较,您可以缓存它的 utc 版本,直到您使用的时区数据库被更新,然后如果缓存值已更改,则更新它。因此,这将是 2 个简单的时间戳类型加上一个时区标识符和某种外部 cron 作业,用于检查时区数据库是否已更改并为缓存的时间戳运行适当的更新查询。
这是一个准确的解决方案吗?还是我还缺少什么?能不能做得更好?
我对 MySQL、SQL Server、Oracle、PostgreSQL 和其他处理 TIMESTAMP WITH TIME ZONE 的 DBMS 的解决方案感兴趣。