跳到主要內容跳到頁尾

日期函式的陷阱:2/29 週年、月底、季末、DATEDIF 與週末字串

9 分鐘閱讀Lv.4 進階摘要與日期

整理 DATE、EDATE、EOMONTH、DATEDIF、NETWORKDAYS.INTL、WORKDAY.INTL 常踩的坑:年份小於 1900 被加 1900、2/29 的週年日、月底連續推算、帶時間的月底篩選、DATEDIF 的 MD 單位、週末字串漏引號、補班日,以及 TODAY 讓結果每天都變。

發布 更新

文章目錄

2024/02/29 到職的同事,2027 年的週年日是哪一天?2027 年沒有 2/29,公式會給你 2/28 還是 3/1?答案看你用哪個函式。

DATE、EDATE、DATEDIF 的語法在 日期與時間入門 和 日期計算實戰 講過了,這篇只挑會出事的地方,從 2/29、月底、季末,一路看到 DATEDIF 的 "MD"、週末字串、補班日,最後是 TODAY 為什麼同一格每天都不一樣。

DATE 的年份小於 1900

入門篇提過 DATE 的年份 0 到 1899 會被加上 1900。這個規則害人的方式有三種:

公式結果發生什麼事
3799/12/30想找序號 0 那天,結果跑到 1899 加 1900
1926/10/11兩位數的年份變成 19xx
2015/10/11民國 115 年被當成 115 加 1900

民國年的那一列最危險,因為 2015 是個合理的日期,不會報錯,只會悄悄算錯。民國年要先加 1911: 才是 2026/10/11。

序號 0 那天是 1899/12/30,用 DATE 組不出來。想看到 0,可以用 ,1900/01/01 的序號是 2,減 2 就是 0。

另外一個小技巧,日填 0 會退到上個月的最後一天: 預期得到 2026/10/31。這是 EOMONTH 出現之前常見的月底寫法,我現在還是比較習慣直接用 EOMONTH。

2/29 的週年

資料放這樣,到職日在 B2,基準日在 E1,這邊假設今天是 2026/10/11:

BE
1到職日基準日
22024/02/292026/10/11

我想列出之後每年的週年日,有兩種寫法。一種是自己拼:,另一種是 ,n 是第幾年。來看看結果:

週年DATE(年,2,29)EDATE($B$2,12*n)
第 1 年(2025)2025/03/012025/02/28
第 2 年(2026)2026/03/012026/02/28
第 3 年(2027)2027/03/012027/02/28
第 4 年(2028)2028/02/292028/02/29

2025 年沒有 2/29,DATE 的做法是日期溢出,往後進位成 3/1。EDATE 則是夾回該月的最後一天,變成 2/28。到了 2028 年,兩個都回到 2/29。

要選哪個,其實是公司規則:閏日出生的人,平年的生日要過 2/28 還是 3/1?我個人偏好 EDATE,因為它永遠落在同一個月,月份不會跳掉。

還有一個更容易犯的錯,是一年一年往後推:

Google 試算表公式
fx

連推四次,每次加 12 個月

=EDATE(EDATE(EDATE(EDATE(B2,12),12),12),12)

結果是 2028/02/28,不是 2028/02/29。第一次推到 2025/02/28 之後,日子就掉成 28 了,後面再推都是 28。一律從原始日期推,月數用 12 乘以年數,也就是上表右邊那種寫法。

下一個週年日怎麼算?先用 DATEDIF 算出已經滿幾年,加 1 再丟進 EDATE:

Google 試算表公式
fx

下一個週年日

=EDATE(B2, 12*(DATEDIF(B2, E1, "Y")+1))

滿 2 年,所以是 EDATE(B2,36),結果 2027/02/28。

DATEDIF 對 2/29 的看法是 2025/02/28 還沒滿 1 年,2025/03/01 才滿: 是 0, 是 1。這和上面 EDATE 的 2/28 並不一致,所以同一份名單裡,「滿週年」和「週年日」最好用同一套邏輯,不要混著用。

月底連續推算

同一個問題換成月底。合約簽在 2026/01/31,我想列出每個月的付款日:

月數一個月一個月累加從 B2 直接推
12026/02/282026/02/28
22026/03/282026/03/31
32026/04/282026/04/30
42026/05/282026/05/31

左邊是 往下填,右邊是 。左邊被 2 月夾成 28 之後就回不去了。原因跟 2/29 一樣,一律從原始日期推。

如果合約本來就是「每月月底付款」,直接用 EOMONTH,不用管 28、30、31:

Google 試算表公式
fx

簽約月往後 2 個月的月底

=EOMONTH(B2, 2)

結果是 2026/03/31。

帶時間的資料

篩「這個月」的資料,常寫成大於等於月初、小於等於月底。資料如果帶時間,月底那天會少算。下單時間放在 A2:A7:

A
1下單時間
22026/10/01 09:15
32026/10/12 18:40
42026/10/30 16:20
52026/10/31 14:30
62026/10/31 23:05
72026/11/01 08:10

D1 放月初 ,D2 放月底 。10 月的單明明有 5 筆,這樣數:

Google 試算表公式
fx

小於等於月底,當天的時間被排除

=COUNTIFS(A2:A7, ">="&D1, A2:A7, "<="&D2)

結果是 3。EOMONTH 回傳的是 10/31 00:00,所以 10/31 14:30 和 23:05 都比它晚,被排掉了。改成小於「月底加 1」,也就是下個月的月初:

Google 試算表公式
fx

小於下個月月初,整個月底都算進去

=COUNTIFS(A2:A7, ">="&D1, A2:A7, "<"&(D2+1))

結果是 5。COUNTIFS 的條件寫法在 SUMIFS 進階陷阱 有講。

季初與季末

季末不用判斷一年四季,用 MOD 算出「離季末還差幾個月」就好:

Google 試算表公式
fx

這個日期所在季的最後一天

=EOMONTH(B2, MOD(3-MONTH(B2), 3))

10 月:MOD(3-10,3) 是 MOD(-7,3),在 Sheets 的結果是 2,所以往後推 2 個月,12 月底。季初則是先退回季末的前一季,再加 1 天:

Google 試算表公式
fx

這個日期所在季的第一天

=EOMONTH(B2, MOD(3-MONTH(B2), 3)-3)+1

用幾個日期試試看:

日期季初季末
2026/10/112026/10/012026/12/31
2026/11/302026/10/012026/12/31
2026/12/312026/10/012026/12/31
2026/03/152026/01/012026/03/31
2026/01/012026/01/012026/03/31
2026/05/022026/04/012026/06/30

季末當天(12/31、3/31)MOD 是 0,推 0 個月,還是自己所在的季。要「本季」就把 B2 換成 TODAY(),不過寫報表的時候,我會把 TODAY() 放在一格設定,其他公式去參照它,原因在最後一節。

DATEDIF 的 MD

DATEDIF 的 "MD" 單位,意思是扣掉整年整月之後剩下的天數。Microsoft 在 Excel 的 DATEDIF 說明裡建議不要用 "MD",說有已知的限制,可能算出負數或不對的數字。Sheets 這邊我找不到對應的官方說明,不過實際算下來,它真的會出現負數,這個單位的名聲不太好是有原因的。

最容易出怪結果的是起日在月底、終點月比較短的組合。拿 2026/01/31 到 2026/03/01 來看,直覺答案是「1 個月又 1 天」。"M" 是 1,"MD" 卻會算出 -2,不是 1,也不是任何看得出道理的天數。

我自己的做法是不用 "MD",先算滿幾個月,再用 EDATE 算出那一天,最後相減:

Google 試算表公式
fx

滿整月之後剩下的天數

=C2 - EDATE(B2, DATEDIF(B2, C2, "M"))

B2 是 2026/01/31、C2 是 2026/03/01 的話,滿 1 個月的那天是 EDATE(B2,1),也就是 2026/02/28,3/1 減掉它剩 1 天。

另外一個陷阱,開始日比結束日晚,DATEDIF 預期會回 #NUM!,不像 NETWORKDAYS 會回負數。報表裡如果結束日可能是空的或比較早,先用 IF 擋一下。

週末字串

NETWORKDAYS 和 WORKDAY 的週末固定是六、日。公司週日單休、週六要上班的話,改用 NETWORKDAYS.INTL 和 WORKDAY.INTL,多一個週末參數:

週末可以填數字代碼,也可以填 7 個字元的字串。字串從週一排到週日,1 是休息、0 是上班。預設的週六日是 "0000011",週日單休是 "0000001"。

資料這樣放:開始日 B2 是 2026/10/01(週四),結束日 C2 是 2026/10/31(週六),假日放在 H2:H3,示範用 2026/10/09 和 2026/10/10。實際放假日請以人事行政總處的公告為準。

週末設定假日工作日數
"0000011"(週六日休)有21
"0000001"(週日單休)無27
"0000001"(週日單休)有25
"0000000"(天天上班)無31

週日單休的時候,國慶日 10/10 剛好是週六,這次它不再被週末排掉,所以假日清單要扣 2 天:27 變 25。同樣的假日在週六日休的設定下,10/10 已經是週末,只會多扣 10/9 一天。

數字代碼也可以:11 是「只有週日休」,所以 NETWORKDAYS.INTL(B2,C2,11,H2:H3) 的結果和 "0000001" 一樣是 25。

漏了引號

這是最容易中的坑。字串一定要有引號:

Google 試算表公式
fx

漏了引號的寫法

=NETWORKDAYS.INTL(B2, C2, 0000001, H2:H3)

沒有引號,0000001 會被當成數字 1,開頭的零不見了,而代碼 1 就是預設的週六日休。結果預期是 21,不會報錯,只是悄悄用錯了週末。看到週末字串,先確認有沒有引號。

WORKDAY.INTL

WORKDAY.INTL(開始日, 天數, [週末], [假日]) 的週末參數同理。從 2026/10/01 起算 10 個工作日,週日單休、扣掉 H2:H3:

Google 試算表公式
fx

週日單休,往後 10 個工作日

=WORKDAY.INTL(DATE(2026,10,1), 10, "0000001", H2:H3)

結果是 2026/10/15。手算一下:10/2 週五是第 1 天,10/3 週六第 2 天,10/5 到 10/8 是第 3 到 6 天,10/9 和 10/10 放假跳過,10/12 到 10/15 是第 7 到 10 天。

沒有假日清單的話,是 2026/10/13。同樣的 10 天,用預設的 WORKDAY(週六日休)加上假日清單,結果是 2026/10/16。

假日範圍與補班日

假日清單的範圍有兩件事要注意。

第一,裡面要是真的日期。如果是 TEXT 做出來的「2026/10/09」文字,NETWORKDAYS 會直接回 #VALUE!,不是默默不扣。清單換成真正的日期值(例如 DATE(2026,10,9)),結果才會是扣掉 10/9 的 21 天。拿 ISNUMBER 檢查一下清單,比較保險。

第二,台灣有補班日,週六要上班。NETWORKDAYS 沒有「例外上班」的參數,得自己加回去。補班日放在 J2:J3,示範假設 2026/10/17(週六)要補班:

Google 試算表公式
fx

工作日數,加上落在期間內的補班日

=NETWORKDAYS(B2, C2, H2:H3) + COUNTIFS(J2:J3, ">="&B2, J2:J3, "<="&C2)

預設週六日休的 10 月是 21 天,加上那一個補班日,結果是 22。補班日必須是週末,而且不要同時寫進假日清單,不然就抵銷了。

TODAY 讓結果每天都變

TODAY 每天都是新的值。這件事在報表上會有點尷尬,我拿一位到職日 2022/08/01 的員工(放在 B2)來看,年資公式是:

Google 試算表公式
fx

年資寫成 X年Y個月

=DATEDIF(B2, E1, "Y") & "年" & DATEDIF(B2, E1, "YM") & "個月"

E1 放不同的基準日,結果就不一樣:

E1(基準日)結果
2026/10/114年2個月
2026/11/114年3個月
2027/03/014年7個月

如果 E1 放的是 ,上個月存起來的報表,這個月打開,數字就變了。所以我的習慣:

  • 需要「即時」的儀表板,E1 放 ,其他公式都參照 E1,不要每條公式各放一個 TODAY()。
  • 需要「存檔」的報表,把 E1 換成固定日期。快速打入今天日期的快捷鍵,在 Chrome 上 Windows 是 Ctrl+;,Mac 是 Cmd+;,輸入後是固定的值,不會再變。
  • 已經算好的結果要凍起來,複製後用 Ctrl+Shift+V(Mac 是 Cmd+Shift+V)貼上值。

還有一個小地方,TODAY 的「今天」是依試算表自己的時區,而不是你電腦的時區。跨時區共用的檔案,開出來的日期可能差一天,時區設定在「檔案」>「設定」裡看。

練習

1

找出錯在哪

同事要算 2026/10/01 到 2026/10/31 的工作日,公司週日單休,假日放在 H2:H3(2026/10/09 與 2026/10/10)。他寫了 ,算出 21,可是週六也要上班,答案應該更多。錯在哪裡?正確答案是多少?

日期的坑大多是同一種:先想清楚「2/29 要算 2/28 還是 3/1」「月底那天算不算」這種規則,再選函式,公式才不會被 2 月打到。

我是喜特先生,Mr. Sheet,我們下個教學見!

分享:
喜特先生 Mr. Sheet

喜特先生 Mr. Sheet

數據分析師/商業分析師

八年工作經驗,跨不同業界解決數據需求。做過的案例都整理在作品集。

接下來可以

這篇在技能樹的 Lv.4「進階應用」,模組「進階日期處理」(第 1/1 篇)。讀完這篇,路線上的下一個模組是「進階資料處理」。

回到技能樹

相關文章

查看所有文章

留言討論

共 0 則留言

訂閱電子報,新文章上線就通知你

免費,隨時可取消。

送出即表示同意服務條款與隱私權政策。