要求之一是对所有 RDBMS 类型的 DateTimes 进行一致处理。
请注意,日期时间处理能力在不同的数据库系统中存在很大差异。这范围从几乎不支持(SQLite)到优秀(Postgres)。一些如 Oracle 的遗留数据类型可能会混淆情况,因此请仔细研究而不做任何假设。
与其建立一个笼统地说我们必须支持“任何或所有数据库”的要求,不如说得更具体一些。准确研究哪些数据库可能真正适合在现实世界中部署。“任何或所有数据库”的要求是幼稚且不切实际的,因为数据库的许多功能各不相同——日期时间处理只是多数据库支持问题的开始。
SQL 标准几乎没有涉及日期时间的主题,广泛地定义了几种类型,几乎没有讨论日期时间工作的细微差别和复杂性。
另请注意,大多数编程平台对日期时间处理的支持极差。请注意,Java 凭借其出色设计的java.time类在该领域处于行业领先地位。该框架从 Java 的Joda-Time项目演变而来,该项目作为NodaTime移植到 .Net 平台。
所有 DateTime 值必须以毫秒为精度,
很好,你已经指定了那个重要的细节。了解各种系统将日期时间值解析为整秒、毫秒、微秒、纳秒或其他值。
包括时区信息并存储在单个列中。
精确定义时区。
了解从 UTC 偏移和时区之间的区别:第一个是小时-分钟-秒加或减数,第二个有格式名称,Continent/Region
是过去、现在和未来的历史更改特定区域的人们使用的偏移量。
CST、PST、IST 等 2-4 个字母的缩写不是正式的时区名称,没有标准化,甚至不是唯一的(避免使用它们)。
由于不同的 RDBMS 处理日期和时间的方式不同,我担心在这种情况下我不能依赖它们的原生列类型,所以我必须想出一个不同的解决方案。
SQL 标准确实定义了一些主要数据库支持的类型。
TIMESTAMP WITH TIME ZONE
代表一个时刻,时间线上的一个特定点。我隐约记得听说过一个实际存储传入时区的数据库。但是大多数,例如 Postgres,使用传入值上指示的时区来调整为 UTC,然后存储该 UTC 值,最后丢弃时区信息。检索后,您将返回一个 UTC 值。当心工具和中间件具有令人困惑的反特性,即在检索后和显示给用户之前应用默认时区。
TIMESTAMP WITHOUT TIME ZONE
表示带有时间的日期,但故意缺少时区或偏移量的上下文。没有区域/偏移量,这样的值不代表片刻。您可以应用时区来确定大约 26-27 小时范围内的时刻,即全球时区范围。
标准中还有其他类型,例如仅日期 ( DATE
) 和仅时间 ( TIME
)。
请参阅我为 Java 制作的此表,但在此上下文中,SQL 标准类型的列是相关的。请注意,这TIME WITH TIME ZONE
在逻辑上没有意义,不应使用。

如果您缩小了候选数据库列表,请研究他们的文档以了解它们是否具有类似于您感兴趣的标准类型的类型,以及该类型的名称是什么(并不总是标准名称)。
我正在考虑将我的 DateTime 值存储在无符号 largeint 列类型(8 个字节)中。
64 位值可能不太合适。例如,java.time类使用一对数字,自 UTC 1970 第一时刻的纪元参考以来的整秒数,再加上小数秒中纳秒计数的另一个数字。
如果它们在您的候选数据库列表中相似,那么最好使用数据库的数据时间数据类型。使用从纪元开始计数本质上是模棱两可的,这使得识别错误数据变得困难。
存储您自己的从纪元开始计数是可能的。如果您必须这样做,请确保整个团队都了解选择了哪个时代参考。至少有几十个已在各种计算系统中使用。假设正在使用特定的纪元参考,请注意工作人员。
定义您自己的日期时间跟踪的另一种方法是使用标准ISO 8601格式的文本。此类字符串将按字母顺序按时间顺序排序。该排序的一个例外是可选的,但通常Z
在末尾用于指示与 UTC 的偏移量为零(发音为“Zulu”)。
我能够以这种方式存储的最小日期时间为 0001-01-01T00:00:00.000+xx:xx,
考虑到 0001..8000 的最大年份跨度
你真的保存了基督时代的价值观吗?这个软件真的会在 8000 年左右执行交易吗?
这是负责任的利益相关者应该定义他们真正需求的领域。例如,对于许多业务系统,您可能只需要产品发布那年的数据,并且只需要一两个世纪的未来。
不同数据库之间的最小值/最大值范围差异很大。如果您选择在每个数据库系统中使用内置数据类型,请调查其限制。例如,有些可能只到 2038 年,即常见的Y2038 问题。
总结一下我的建议:
- 了解您的日期时间需求:最小/最大范围、分辨率和各种类型(时刻与非时刻、仅日期等)。
- 了解您可能用于部署的数据库。
- 如果可能,请使用数据库提供的内置数据类型。
- 确保您和您的团队了解日期时间处理。根据我的经验,许多人不这样做,因为 (a) 该主题很少被教授,并且 (b) 许多程序员和管理员错误地认为他们对日期时间的日常直观理解足以完成编程工作。(正如他们所说,无知是幸福的。)
- 确定除日期时间处理之外的其他功能领域,并比较哪些数据库支持这些领域。