如何在 Oracle 中检测给定年份是否为闰年?
问题
您需要确定任何给定年份是否为闰年。
解决方案
解决此问题的方法有很多。这些方法包括计算以确定该年份是否存在 2 月 29 日,或 3 月 1 日是该年份的第 61 天还是第 62 天。
示例
SELECT to_number(to_char(sysdate,'YYYY')) Year, CASE WHEN MOD(to_number(to_char(sysdate,'YYYY')),400) = 0 then 'Yes' WHEN MOD(to_number(to_char(sysdate,'YYYY')),100) = 0 then 'No' WHEN MOD(to_number(to_char(sysdate,'YYYY')),4) = 0 then 'Yes' ELSE 'No' END AS "Leap Year?" FROM dual;
输出
2020 Yes
显然 2020 年是不值得纪念的一年,它是一个闰年。让我们在非闰年上尝试一下,例如 2019 年。
示例
SELECT '2019' Year, CASE WHEN MOD(2019,400) = 0 then 'Yes' WHEN MOD(2019,100) = 0 then 'No' WHEN MOD(2019,4) = 0 then 'Yes' ELSE 'No' END AS "Leap Year?" FROM dual;
输出
2019 No
该解决方案基于从年份数字推导出的闰年的标准定义。标准算法指出,如果年份可以被四整除,则它是闰年。但是,如果年份也可以被 100 整除,则此规则将覆盖可被四整除的规则,并且该年份不是闰年。最后,如果年份也可以被 400 整除,则此规则将覆盖所有其他规则,并且该年份是闰年。
上述步骤序列在我们的 SQL 中使用 CASE 语句执行。
我们使用 CASE 语句来驱动闰年检测的主体。我们在 case 语句中反向应用闰年算法,以利用 CASE 语句的行为。一旦找到匹配规则,CASE 语句就会中断。这意味着我们希望首先评估最重要的规则,即覆盖所有其他规则的规则,年份是否可以被 400 整除?如果结果为假,我们希望评估下一个最严格的规则——被 100 整除——依此类推。
我们使用 MOD 函数执行模除法。首先,如果年份模 400 没有余数,我们知道它可以被 400 整除,因此它是闰年。对于这种情况,我们返回字符串“闰年”,并且 CASE 语句结束。如果我们的年份模 400 有余数,我们知道它不是闰年,然后继续对年份模 100 进行除法。如果没有余数,我们知道年份可以被 100 整除,因此不是闰年。我们知道这一点,因为如果年份也可以被 400 整除,我们不会评估 CASE 表达式的这一部分,因为 CASE 语句已经终止了。
类似地,如果两个模除法都有余数,我们将继续执行第三个模除法,该除法找到年份除以四的余数。同样,如果没有余数,我们知道前两个规则没有匹配,因此年份是闰年。
此时,我们的 CASE 语句已用尽,我们知道该年份与任何查找闰年的显式规则都不匹配。