計算指定月份的天數是常見需求 (如利息計算、報表週期)。Oracle 提供 LAST_DAY 直接取得月份最後一天,配合 TO_CHAR(...,'DD') 即可輕鬆獲得天數。本文示範標準寫法、跨月計算、閏年自動處理,並說明為何不建議手寫 CASE WHEN 判斷閏年。
-- 取得 2008 年 9 月天數
SELECT TO_CHAR(LAST_DAY(TO_DATE('2008-09-01', 'YYYY-MM-DD')), 'DD') AS days
FROM DUAL;
-- 結果:30
關鍵點:輸入 TO_DATE 時建議使用月初第一天,格式掩碼 YYYY-MM-DD 清晰無誤。
-- 上個月天數 (以 2008-03-30 為基準)
SELECT TO_CHAR(
LAST_DAY(
ADD_MONTHS(TO_DATE('2008-03-30', 'YYYY-MM-DD'), -1)
),
'DD'
) AS days
FROM DUAL;
-- 結果:29 (2008 年為閏年,2 月 29 天)
-- 直接看 ADD_MONTHS 計算結果
SELECT TO_CHAR(ADD_MONTHS(TO_DATE('2008-03-30', 'YYYY-MM-DD'), -1), 'YYYYMMDD')
FROM DUAL;
-- 結果:20080229 (自動識別閏年)
| 錯誤寫法 | 問題 | 正確寫法 |
|---|---|---|
TO_DATE('200809', 'YYYYMM') 直接餵給 LAST_DAY | 隱含轉換依賴 NLS_DATE_FORMAT,跨環境不穩定 | 明確指定 TO_DATE('2008-09-01','YYYY-MM-DD') |
自寫 CASE WHEN MOD(year,4)=0 ... 判斷閏年 | 邏輯複雜、易漏掉 100/400 年規則 | 信任 ADD_MONTHS + LAST_DAY 內建邏輯 |
使用 EXTRACT(DAY FROM LAST_DAY(...)) | 回傳 NUMBER 需再轉字串 | TO_CHAR(...,'DD') 一步到位 |
CREATE OR REPLACE FUNCTION get_month_days(p_year NUMBER, p_month NUMBER)
RETURN NUMBER IS
BEGIN
RETURN TO_CHAR(LAST_DAY(TO_DATE(p_year||'-'||p_month||'-01','YYYY-MM-DD')), 'DD');
END;
/
-- 呼叫範例
SELECT get_month_days(2024, 2) FROM DUAL; -- 回傳 29
掌握 LAST_DAY + ADD_MONTHS 組合,即可以最簡潔、最可靠的方式解決所有月份天數計算需求,無需自行處理閏年邏輯。