我知道公历始于 1582 年 10 月 15 日,在从儒略历过渡期间,已经减少了 10 天。
当我执行此查询时:
SELECT STR_TO_DATE('1582-10-05', '%Y-%m-%d')
我得到这个结果:
1582-10-15 (the 10 days difference).
但是当我尝试匹配这些日期时,我得到的是原始日期(10 月 5 日而不是 15 日)。
例如:
SELECT STR_TO_DATE('1582-10-05', '%Y-%m-%d') = STR_TO_DATE('1582-10-15', '%Y-%m-%d')
我得到了一个错误的回复,尽管你会期望得到一个真实的,因为 10 月 5 日实际上算作 10 月 15 日,正如我们在第一个例子中看到的那样。
任何人都可以解释一下这里发生了什么?
在文档中指出,由于您注意到的转换,必须谨慎调用TO_DAYS
和FROM_DAYS
函数。此外,当我检查MySQL的源代码时,我意识到STR_TO_DATE
使用这些函数类似的方法。据我了解,直接转换日期存储或应用操作是完全不安全的。文件说;"Dates during a cutover are nonexistent."
也是。
另外,对于不同服务器之间的不一致,我可能会有一个解释。我有 2 台不同的机器,它们在土耳其伊斯坦布尔和德国法兰克福安装了 MySQL。它们具有相同的设置,不包括本地化设置。第一个显示 1,另一个显示日期减法查询的 11。这意味着(以我的拙见)官方文档中有关于日历切换和本地化的无法解释的部分。
请参阅以下结果:
SELECT STR_TO_DATE('1582-10-05', '%Y-%m-%d');
# Result #1: 1582-10-15
SELECT DATE_FORMAT(STR_TO_DATE('1582-10-05', '%Y-%m-%d'), '%Y-%m-%d');
# Result #2: 1582-10-05
SELECT DATE_FORMAT(STR_TO_DATE('1582-10-15', '%Y-%m-%d'), '%Y-%m-%d');
# Result #3: 1582-10-15
SQL小提琴演示。
这些表明问题在于1582-10-05
日期的显示方式,而不是存储方式。结果 #2 显示,如果使用DATE_FORMAT
函数将日期显式转换为相同的字符串格式,则会显示输入日期。这也解释了为什么问题中的比较查询返回 false:在后台,两个存储的日期是不同的。
正如您所发现的,这种怪癖发生在1582-10-05
和1582-10-14
(含)之间的所有日期,即实际上不存在的日期范围:所有这些日期的隐式文本转换为文本都会给出 10 天后的日期。因此,如果由于某种原因需要显示此范围内的日期(可能有问题),一个简单的解决方法是始终使用DATE_FORMAT
函数。