SqlDateTime.MinValue!= DateTime.MinValue,为什么?


Answers:


131

我认为SQL和.NET的Date数据类型之间的差异源于以下事实:SQL Server的datetime数据类型,其最小值和最大值以及精度比.NET的DateTime数据类型要老得多。

随着.NET的出现,团队决定Datetime数据类型应具有更自然的 最小值,而01/01/0001似乎是一个合理的选择,并且从编程语言(而不是数据库角度)肯定是这样。更自然。

顺便提及,在SQL Server 2008中,有许多新的基于日期的数据类型(DateTimeDateTime2DateTimeOffset)实际上确实提供了更大的范围和精度,并且紧密映射到.NET中的DateTime数据类型。例如,DateTime2数据类型的日期范围是0001-01-01至9999-12-31。

SQL Server的标准“日期时间”数据类型始终具有最小值01/01/1753(实际上确实具有!)。我必须承认,我也对此价值的意义感到好奇,因此进行了一些挖掘。.我发现如下:

在公元1日到今天之间,西方世界实际上使用了两个主要日历:朱利叶斯·凯撒的儒略历和教皇格里高利十三世的公历。两个日历的区别仅在于一条规则:确定:年是什么的规则。在儒略历中,所有可以被四整除的年份是leap年。在公历中,所有可被四整除的年份都是are年,但不可被100整除(但不能被400整除)的年份不是leap年。因此,年份1700、1800和1900是儒略历中的leap年,而不是公历,而1600和2000是两个历法中的leap年。

当教皇格里高利十三世在1582年提出日历时,他还指示应该跳过1582年10月4日至1582年10月15日之间的日期,也就是说,他说10月4日之后的第二天应该是10月15日。许多国家但是,延迟了转换。英格兰和她的殖民地直到1752年才从朱利安转向格里高利安,因此对他们来说,跳过的日期是在1752年9月4日至9月14日之间。其他国家/地区则在其他时间转换,但1582和1752年是该日期的相关日期。我们正在讨论的DBMS。

因此,当日期算术回溯到很多年时会出现两个问题。第一个是,应该根据朱利安规则或格里高利规则计算转换之前的leap年吗?第二个问题是,何时以及如何处理跳过的日期?

八大数据库管理系统就是这样处理以下问题的:

  • 假装没有开关。尽管标准文档尚不清楚,但这似乎是SQL标准的要求:它只是说日期“受到使用公历的自然规则的约束”,无论“自然规则”是什么。这是DB2选择的选项。如果假装单个日历的规则即使在没人听过日历的情况下也始终适用,则技术术语是“多用”日历有效。因此,例如,我们可以说DB2遵循一个多事的公历。

  • 完全避免该问题。 Microsoft和Sybase将其最小日期值设置为1753年1月1日,这已经安全地超过了美国转换日历的时间。这是可以辩护的,但有时会抱怨说这两个DBMS缺乏其他DBMS所具有的有用功能以及SQL Standard所要求的。

  • 选择1582。这就是Oracle所做的。Oracle用户会发现日期算术表达式1582年10月15日减去1582年10月4日得出的值是1天(因为10月5日至14日不存在),并且日期1300年2月29日有效(因为朱利安飞跃式-年份规则适用)。当SQL标准似乎不需要Oracle时,为什么会给它带来更多麻烦呢?答案是用户可能需要它。历史学家和天文学家使用这种混合系统代替了多事的格里高利历。(这也是Sun在为Java实现GregorianCalendar类时选择的默认选项,尽管名称为GregorianCalendar,但它是一个混合日历。)

以上引用来自以下链接:

SQL性能调整:SQL中的日期


2
从i18n开始,不要依赖所有SQL Server DatTime值始终为Gregorian。俄罗斯和中国(以及其他欧洲国家)在20世纪从儒略历改为公历。
理查德

1
@Richard-同意。这些东西应该首先广泛检查。在世界范围内从朱利安转向格里高利安的整个过程是历史上一个阴暗的时期,我怀疑在每种情况下是否总是可以应用一组确定性规则。
CraigTP

1
我想知道哪些应用程序需要使用19世纪甚至是1960年代之前的日期?但这将使用SQL Server的考古学家限制为1753年,或者将Oracle与1582年一起使用。
克里斯S

5
拥有遗嘱信息的应用程序通常会保留旧的信息。
MartW

12

由于在SQL Server中,可以存储在datetime字段(1753/1/1)中的最小日期不等于DateTime .NET数据类型的最小值(0001/1/1)。


1
是的,这是正确的答案。如果您尝试将DateTime.MinValue存储到SqlServer,则会出现错误。
Stefan Steinegger's

9
我完全不确定这将如何回答OP的问题。他问他们为什么不一样。这个答案只是说“是的,他们不一样”。克雷格斯(Craigs)在根本问题上的答案要多得多。
NotMe 2010年

11

1753年是公历(英国)的第一个采用者。至于为什么要在01/01/0001上选择它,这无疑是从1990年代SQL Server成为Sybase以来的遗产。他们必须尽早做出设计决定,并且Microsoft SQL团队还没有找到更改它的理由。

由于.NET爆炸式增长并将其集成到Sql Server中,因此现在有了DateTime2对象以实现兼容性。如果您是NHibernate用户,则可以在类型映射中提供此类型以避免DateTime.Min出现问题

.NET Dates可以满足除公历之外的其他日历:

  • 日历
    • 中文月历日历
    • 东亚月历日历
    • 公历
    • 希伯来语日历
    • 回历日历
    • 日语日历
    • 日文日历
    • 朱利安·卡伦达(JulianCalendar)
    • 韩国日历
    • 韩语Lunisolar日历
    • 波斯日历
    • 台湾日历
    • 台湾Lunisolar日历
    • 泰国佛教日历
    • UmAlQuraCalendar

朱利安·卡伦达(JulianCalendar)实际发生日期 DateTime.MinValue


嗯,您回答了其他问题。问题是“为什么”,而不是“我如何解决它”
Gabriel Magana 2010年

7

两个不同的小组决定在日期/时间上“最小”对他们意味着什么。


1
我认为,这是确切的答案。(无讽刺)
无抛出

1
如果您不满意,请花花公子,是因为您给出了一个愚蠢的答案...“因为我这么说”在询问者超过10岁(并且我在那里很慷慨)时不算作答案。但我没有对你投反对票:-)
加布里埃尔·麦格纳

5

SQL对DateTime使用不同的内部表示形式。


6
这对OP的问题有什么帮助?
ANeves认为SE是邪恶的2010年

1
@ANeves很有帮助。鉴于.NET和MSSQL相距10年以上的计算发展,因此这意味着它们不太可能具有不同的最小日期。
康坦戈2015年

1
@Contango它没有任何含义。它们对于DateTime可能具有不同的内部表示形式,并且仍然具有相同的任意最小值(例如,出于兼容性目的或用于实现给定标准)。同样,取决于内部表示的最小值将是实施泄漏到规范中,我认为这是Very Bad Thing™。
ANeves认为SE是邪恶的
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.