以下表达式在Ruby中返回"366",意味着100 AD是闰年(事实并非如此):
(Date.ordinal(101) - Date.ordinal(100)).to_i
与DateTime相同。
但是,Date.leap?(100)
正确地返回false
。
1.9.1版本的结果相同。和2.0.0版本。
什么东西?我应该提交错误报告吗?
更新
此外,公元1582年显然还差10天!
(Date.ordinal(1583) - Date.ordinal(1582)).to_i
=> 355
根据维基百科,100确实是闰年,1582确实跳过了10天。
显然,在1582-10-15之前,Ruby将日期解释为儒略历日期,而不是公历日期。更多详细信息请点击此处:
http://teleologi.blogspot.com/2013/05/ruby-times-dates-good-bad-and-so-on.html
显然不是一个bug,但肯定违反了最少惊喜的原则(至少在这个程序员看来)。
多么令人困惑!
编辑
撇开关于"合理默认值"的争论不谈,与其他语言相比,Ruby在日历选择的这些敏感问题上似乎相当灵活。我了解到,Date和DateTime构造函数可以接收一个"改革日期"常量,该常量决定从儒略历到格里高利历的转换何时发生。默认为意大利(1582-10-15),但英格兰也是一个选项(跳跃发生在1752-09-14)。
为了避免在日历之间转换时出现意外,我应该对所有日期使用公历:
(Date.ordinal(i+1,1,Date::GREGORIAN) - Date.ordinal(i,1,Date::GREGORIAN)).to_i
=> 365
此外,Date.leap?(100)
返回"false",因为它是Date.gregorian_leap?
的别名。同时,Date.julian_leap(100)
返回true。为了避免意外,可能最好使用方法版本的飞跃?,它使用你选择的任何改革日期。
Date.new(100, 1, 1, Date::JULIAN).leap?
=> true
Date.new(100, 1, 1, Date::GREGORIAN).leap?
=> false