以年、月、日表示的日期差,是將兩個日期之間的差距,依行事曆正確地拆解成三個口語化部分——整年數、再加上剩餘的整月數、再加上剩餘的天數——而日期差計算機填入這些部分的方式,和熱門的 date-fns intervalToDuration 函式相同,都是以起始日期為錨點,依序往前推進一整年、一整月、最後再以一天為單位移動。這樣的先後順序比聽起來更重要,因為每個月份的天數不同,某些年的二月有 29 天,而僅差一天的小差距並不會被進位成整整一個月。輸出結果會以你自然口語的方式呈現,例如「1 年、2 個月又 5 天」,而且這些部分一定能加回原本的總和,也就是起始日期加上這份拆解結果,會剛好落在結束日期上。這種行事曆正確的處理方式,也讓這個工具能夠處理過去到未來、未來到過去,以及同一天的日期配對,而不會回傳負數結果。

how to calculate date difference in years months and days
如何以年、月、日計算日期差

以年、月、日閱讀日期差距

總天數告訴你差距的大小;年、月、日的拆解則告訴你差距的形狀。這兩種看法回答的是不同的問題。當你要倒數某個截止日、預估每日預算,或是逐日比較兩趟行程時,總天數就是正確的單位。當你要描述一個人生事件、契約期限,或某個專案的存續時間——任何你會用概略單位而非精確數量來談論的事情——年/月/日的拆解就是正確的單位。現實中的差距很少剛好是整整一年或整整一個月,因此拆解必須能處理每一種零碎的剩餘,包括剩餘天數為 0 天的情況,以及因為差距只差一天就滿一個 31 天的行事曆月、而剩餘為 30 天的情況。

最常見的日期差距需求,同時也是最具有欺騙性、最棘手的一種。光計算完整的月份數並不足夠,因為當 28 天的二月和 31 天的五月被當作單位時,表現差異極大。日期差計算機採用的是和「對某個日期加上月份」相同的月底夾擠規則,因此,一個只差一天就滿整整一個月的區間,會被計算為月份數減一再加上剩下的零散天數,絕不會被進位成下一個整月。下方表格整理了這個工具所顯示的每一項輸出,以及各自的計算方式。

輸出顯示內容計算方式
總天數精確的行事曆差距套用完整閏年規則的年內日序差
兩日期相隔週數進位後的週數總天數除以 7,再向下取整
完整月份數僅計算整月數以行事曆為錨點填入,絕不進位
年、月、日口語化的差距與 date-fns intervalToDuration 採用相同方法
週間/週末拆分(選用)工作天對週末天數週一至週五 對 週六至週日,合計等於總天數

如何用三個步驟找出拆解結果

  1. 在第一個欄位中選擇起始日期。挑選器預設為今天的日期,因此若要從現在往前計算,保留今天即可,或將它改成任何過去或未來的日期。
  2. 在第二個欄位中選擇結束日期。輸出會在任一日期變更的瞬間立即更新,沒有「計算」或「送出」按鈕需要按下。
  3. 在兩個挑選器下方,即時讀取總天數、兩日期相隔週數、完整月份數,以及年、月、日拆解結果。勾選「僅週間」切換鈕,可將檢視從行事曆天數拆分,切換為週一至週五對週末的拆分。

兩個挑選器會即時更新結果,因此你可以在行事曆上四處點選,來回捲動時間軸或比較不同的結束日期,而不會失去目前的進度。一切都在你的瀏覽器中執行,你輸入的日期從未離開你的裝置,沒有註冊流程、沒有每日使用上限,也沒有上傳步驟。兩次都選擇相同的日期,則每一項輸出都會回傳零,這是在嘗試真實的日期配對之前,確認結果面板能正確更新最簡潔的方式。

為什麼年/月/日拆解比總天數更難處理

總天數只是對行事曆網格上的日序進行一次帶正負號的減法,因此它是一個連續的計算,試算表用一個儲存格就能完成。年、月、日的拆解則不然,它是由三種不同的單位層層堆疊而成,而且每個單位都會和下層的單位相互影響。經典的樸素作法——將總天數除以 365 得出年數,再除以 30 得出月數,然後將餘數當作天數——只要起始日期落在月底附近,或落在閏年的 2 月 29 日附近,得出的答案幾乎每次都會差一天。

有三條規則能讓拆解結果做到行事曆正確,而非只是近似正確。第一,先填入整年:從起始日期加上剛好一個行事曆年,鎖定年數部分,再從新的錨點以月為單位處理剩下的部分。第二,從這個已平移年份的錨點填入整月,當起始日超過該月最後一天時,將日期夾擠到目標月的最後一天——這正是避免「1 月 31 日加上一個月變成 3 月 3 日」的同一條規則。第三,以一天為單位填入剩下的天數,這會自動吸收 2 月閏日的調整。

格里曆的閏年規則被完整遵守:一個年份若能被 4 整除就是閏年,但若是世紀年,除非也能被 400 整除,否則不算閏年。這就是為什麼 2000 年是閏年、1900 年不是閏年,以及 2024 年的二月有 29 天而 2023 年的二月只有 28 天。這個工具會自動套用這條規則,因此跨越 2 月 29 日的差距,會比同樣區間在非閏年中多出一天,你完全不需要自己去標記閏年。

計算範例:2021 年 4 月 15 日到 2022 年 6 月 20 日

為了實際觀察年/月/日拆解的運作,我們挑選一段兩個年份都是非閏年、且拆解的每一部分都非零的乾淨區間。起始日期是 2021 年 4 月 15 日,結束日期是 2022 年 6 月 20 日,兩個年份都是非閏年,因此這個跨年區間本身就是普通的 365 天。

第一步——從起始日期填入整年。2021 年 4 月 15 日加上一個行事曆年是 2022 年 4 月 15 日,因此將年數鎖定為 1 年。剩下的差距是從 2022 年 4 月 15 日到 2022 年 6 月 20 日。

第二步——從已平移年份的錨點填入整月。4 月 15 日到 5 月 15 日是一個月(30 天,因為 4 月有 30 天),5 月 15 日到 6 月 15 日是第二個月(31 天,因為 5 月有 31 天)。結束日期是 6 月 20 日,超過 6 月 15 日,因此停在 2 個月。剩下的差距是從 2022 年 6 月 15 日到 2022 年 6 月 20 日。

第三步——填入剩餘天數。從 6 月 15 日到 6 月 20 日剛好是 5 天,因此天數部分為 5。

日期差計算機對這個區間回傳的結果是 1 年、2 個月又 5 天,總天數為 431 天,完整月份數為 14 個月,以及 61 週又 4 天。以總天數驗算拆解結果:跨年區間的 365 天(沒有跨越閏日),加上第一個月的 30 天,加上第二個月的 31 天,再加上剩餘的 5 天,合計為 431 天,與總天數相符。如果你反過來輸入日期,把 2022 年 6 月 20 日放在第一個欄位、2021 年 4 月 15 日放在第二個欄位,你仍然會得到 431 天以及相同的年/月/日拆解結果,因為這個工具無論順序為何,一律回傳正數答案。

切換為僅週間

勾選「僅週間」選項,可將差距的檢視從行事曆天數切換為工作天。這個工具會將區間拆分成週間天數(週一至週五)和週末天數(週六及週日)。這兩個數字一定會加總為總行事曆天數,讓你在估算專案工時、交貨時段或通知期時,仍能以總天數來驗算。

週間天數僅依行事曆計算,並不會扣除國定假日,因此區間中即使包含國定假日,該日仍會計入週間。若需要會自動扣除假日的商業天數計算,請使用專門打造的商業天數計算機,它正是為了這個用途而設計,可以略過你指定的國定假日。請把這裡的「僅週間」拆分視為單純的週一至週五統計,而非合約上的工作天數計算。

年/月/日差距最重要的應用場景

對於任何以口語或概略方式表述的區間,年/月/日都是最自然的單位。法定通知期、租期、契約期限以及終止通知條款,通常都是以年、月、日來撰寫。專案計畫、課程註冊以及訂閱期間的描述方式也是如此。年齡通常也是這樣表達,因為年/月/日拆分正是人們在第一個生日之後說自己年齡的方式。針對單次計算,你可以在這裡手動挑選起始和結束日期;若需要一個會在每次生日更新的年齡,那麼綁定出生日期的年齡計算機才是合適的工具。

實務上常見的用途列於下方,並對應說明年/月/日為何是各自最自然的單位。

常見用途為何年/月/日是最自然的單位
法定通知期法律條文以年、月、日撰寫
租期或契約期限標準的契約用語與續約措辭
專案或課程期間進度更新與里程碑描述
年齡或週年人們實際描述自己年齡的方式
訂閱期間續約與取消的相關說明

對於同類的其他單一日期操作,相關計算機也涵蓋了:日期加/減計算機可從單一日期往前或往後移動;年齡計算機可根據出生日期提供即時年齡;星期計算機可找出任意日期落在星期幾。這些工具都無法取代用於兩個日期差距的年/月/日拆解,但在你取得拆解結果後,它們能回答接踵而來的延伸問題。

延伸閱讀:精準日期格式轉換器:ISO、美式、歐式與文字格式。