雜記 › 生活隨筆 › 同一天既是週末又被登記成補班,工作日計算器聽誰的

同一天既是週末又被登記成補班,工作日計算器聽誰的

先看那一天同時出現在兩份清單裡

排工期最容易撞上這種日子:裝修工班說下週一照常進場,日曆上那個週一卻標著假期,另一張紙上又寫著補班。我的辦法是把起止日期丟進工具跑一遍,看它聽誰的——這篇不講假期清單哪來的,只講它內部的判定順序,因為換套日曆、換個地區,順序還是同一套。

判定順序是四行程式碼,不是政策

模板裡判單日性質的 wdKindOf() 寫在 512–517 行,順序硬得沒商量:先查補班清單(514 行)返回 makeup,再查假日清單(515 行)返回 holiday,最後才看週末開關(516 行);只有 work 與 makeup 算上班。

把 2026-10-05 這個週一同時抄進兩份清單,實測 kind 就是 makeup,單日區間給出 工作日 1 / 休息日 0 / 總數 1。整月對照更直白:同一批日期只寫進假日清單時是 20 個工作日,抄一份進補班清單變 22 個,總數始終 31——改掉的只有上班與休息這一刀。計數區還會把衝突攤開:有效 3 條,其中 2 天同時寫在補班清單裡,按補班算。

週末從 0 天設到 7 天,工作日一路塌下去

週末能設成 0 到 7 天任意組合。區間固定 2026-10、清單不動,工作日數走出一條很規整的下坡路,兩列相加永遠是 31:

設成休息的天數工作日休息日總數
0 天24731
1 天22931
2 天(預設)191231
3 天151631
4 天112031
5 天82331
6 天52631
7 天22931

塌到底會怎樣?設到 7 天全休息時 per = 7 - 7 = 0,整週批量與尾數判定一起歸零(553–558 行),base=0、cut=0,只有 add 仍=2,於是整月只剩 2 個補班日算上班。再把兩份清單清空,同一個月退化為 工作日 0 / 休息日 31 / 總數 31。

24 22 19 15 11 8 5 2 0 1 2 3 4 5 6 7 工作日 休息日 總數 31 2026-10

圖 1|橫軸是週末設幾天,綠柱是剩下的工作日;最矮那格不是 0,因為還有補班日算上班。

不重複扣、不漏加:全年只做加法

拉到整年:2026 全年 365 天,先按週末規則得到 base=261,再扣 17 天、加回 4 天,剩 248 個工作日 / 117 個休息日。清單裡明明有 29 條假日,怎麼只扣 17?因為有 12 條本來就落在週末頭上,週末的假日不再扣第二次;反過來 4 個補班日全都落在週末,所以 add=4。月度視圖也對得上帳:勾上 230 行那個核取方塊,12 個月的工作日逐月相加還是 248,與一次餵整年的結果相同。

端點算不算,四種組合差出兩天

「還剩幾個工作日」的爭吵多半不是算錯,而是首尾算沒算沒對齊。模板 170–171 行那兩個核取方塊預設都 checked,即首尾都含。2026-10-14 到 2026-10-21 四種組合實測 6 / 5 / 4 個工作日,都不含時區間縮成 10-15~10-20。寫成同一天時四種組合是 1 / 0 / 0 / 0,兩頭都不含直接判空並顯示「區間裡一天都沒有」。

數夠 N 個工作日那天是哪天

反過來問得更常:合約給了 500 個工作日,交付日落在哪天。實測 2026-10-01 往後數 500 個工作日落在 2028-09-04,跨 704 個自然日,其中 204 個是休息。往前數也走得動,2026-10-14 數 -1 就是 2026-10-13;N=0 原地返回起始日,哪怕那天是週六。想復現就用 工作日計算器 的推算模式,別拿系統當天當基準。上限 1000000,再多一位直接被拒;正好踩線時撞的是支援域邊界,報 結果超出支援範圍(1900-01-01 ~ 2999-12-31),還差 746094 個工作日。

區間沒有長度上限,明細只給 200 條

這兩件事得分開看。1900-01-01 到 2999-12-31 一共 401767 個自然日,一次餵進去照樣算出 286,964 個工作日,全程整數運算。明細清單卻是另一套閘門:每種只給 200 條、只掃描 4000 天,餵 2000-01-01~2019-12-31 這 7305 天的區間,頁面原樣寫出「這段區間太長,只掃描了 4000 天,後面 3305 天沒進清單」。也別預設它逐天判定:區間統計是整週批量 weeks * (7 - weekendSize) 加尾數逐個,401767 天裡進入逐日判定的只有 2 天。這跟 每 28 天與每月同一天為什麼會錯開是同一類口徑問題。

清單解析:報錯但不丟整表

清單是 textarea,貼進來的東西往往不乾淨。解析口徑是壞行報錯但不中斷:一份 10 行混合清單(9 行有內容、第 9 行是空行)實測給出 有效 3 條(重複已去重 2 條),錯誤面板逐行給原文——第 5 行是月份寫成 13、第 7 行是 2026-02-30 這個日子不存在、第 8 行是亂寫的一行;空行和 # 註釋一樣佔號。重複行絕不會讓某天被扣兩次:3 行寫同一個日子仍是 cut=1。清單規模是法定假日 29 條 + 調休補班 4 條、合併去重 33 天,年份只有 2026 一個;2027 起兩份清單裡一天都沒有,cut=0、add=0,全年實測 261 個工作日 / 104 個休息日,純走週末分支。那兩份清單只是模板內建的樣本資料,換個地區就換一份,判定順序仍是同一套。

2026 上班 2027 上班 2026 休息 2027 休息 248 261 117 104 清單內:扣 17 加 4 清單外:0 / 0

圖 2|同一套 base=261,差別只來自 cut 與 add:清單內扣 17 加回 4,清單外是 0 和 0。

三處文案與程式碼打架

一是起止寫反時,報錯原文讓用戶「點下面按鈕按反過來的順序算」,可 wdSwap() 全文只有 1223 行那一處定義、0 處 onclick,那個按鈕並不存在。二是日序原點:intro 說日期換算成從 1900-01-01 起的天數,實測 wdDaysFromCivil(1970,1,1)=0、(1900,1,1)=-25567,1900-01-01 只是支援域下界。三最影響明天繼續用:weekend 欄位存成 33 字元的 "falsefalsefalsefalsefalsetruetrue",回讀條件卻要求長度正好 7(1284 行),於是兩份清單能回來、週末勾選重新整理即丟。

FAQ

Q:同一天既寫進假日清單又寫進補班清單,會不會被扣一次再加一次?

不會兩個都算。補班那關排在假日前面,第一個命中就返回:整月從 20 個工作日變 22 個,總數還是 31。搶一天時先定優先級,數距離某個日子還剩幾天也一樣。

Q:週末勾滿 7 天,是不是整月一天都不上班?

不是。per = 7 - 7 = 0 只讓批量與尾數歸零,補班清單還在,2026-10 實測仍有 2 個工作日;把兩份清單一起清空才得到 0 / 31 / 31。

Q:能不能讓它自己認得接下來每一年的假期?

不能。內建那兩份只是範例資料,年份只到 2026;清單外的日子得自己一行一條貼進去。

📎 相關文章

字帖每頁放幾個字:預設 A4 是 20 個,不是 100÷4=25 2026-10-27 倒數計時裡的 86400 秒一天,碰上夏令時間會少給你 1 天 2026-10-27 世界時間的偏移是誰給的:一條正則,和一個沒有夏令時間的寫死小時數 2026-10-27 同一次計算給出兩個體脂率:預設一組差 6.1 個百分點,腰圍 1 cm 值 0.7 2026-10-26 照片轉了 90°,換一部裝置方向又回來了:EXIF 標記與真實旋轉的分工 2026-10-22