一個均勻隨機日期產生器的替代方案,是一款瀏覽器工具,可使用 Web Crypto 從包含首尾的 YYYY-MM-DD 範圍中抽取行事曆日期,針對每個輸入以格里高利曆閏年規則進行驗證,並在完全不將任何值上傳到伺服器的情況下回傳結果。人們通常是在注意到他們最先嘗試的隨機日期功能出現三種常見失敗模式後,才開始搜尋這樣的工具:在接近日光節約時間切換時,行事曆日期會跳過或重複;當範圍大小不是乾淨的 2 的冪次時,分佈出現明顯偏差;或是工具悄悄修復無效輸入而不是將其標示出來。Random Date Generator 透過以 UTC 日序數運作、從瀏覽器的 Web Crypto API 抽取亂數,以及對每個 YYYY-MM-DD 輸入套用 ECMAScript Date 物件所實作的格里高利曆規則進行驗證,來同時解決這三個問題。此工具完全在瀏覽器中執行,支援從 0001-01-01 到 9999-12-31 的民用日期,並以穩定的 YYYY-MM-DD 格式回傳結果。以下將仔細檢視一個真正可用的替代方案需要達成哪些條件,以及這款工具與試算表和其他線上產生器相比的表現如何。

為什麼人們會尋找 Random Date Generator 的替代方案
搜尋替代方案的人,通常帶著對他們最先嘗試之工具的特定抱怨而來。最常見的痛點可分為三類。第一是偏差。許多線上產生器使用 JavaScript 的 Math.random(),並以模運算對應其輸出,當範圍大小無法被 2^32 整除時,某些日期被選中的機率會稍微提高。第二是日光節約時間切換前後的行事曆正確性。在本地午夜 Date 物件上加上 24 小時的工具,可能會落在切換之夜的 23:00 或 01:00,這表示輸出中可能會跳過或重複某個預期的行事日。第三是私。幾款熱門的產生器會將所選範圍傳送到伺服器進行處理;對於偶爾的休閒使用來說沒問題,但當範圍屬於敏感的測試資料、合約期間或不應離開裝置的內部時程時,這種做法完全不可行。
一個值得信賴的替代方案會一次解決這三項疑慮,而不是以一個弱點換掉另一個。這道門檻比聽起來更高,因為修正日光節約時間漂移需要改變行事曆模型,修正偏差需要改變亂數來源與對應方式,而修正隱私則需要將整個流程保持在用戶端。Random Date Generator 從一開始就是依循這個綜合門檻所打造,因此希望找到真正替代方案的讀者,可以將同一款工具用於一般的實用工作,而無需重新檢查哪一種失敗模式適用。
這款工具與典型替代方案的不同之處
Random Date Generator 採取刻意精簡的取向:做好一件事、把它做對,並讓資料保留在本機。流程中的每一步都停留在瀏覽器內。
- 它僅接受嚴格的 YYYY-MM-DD 值,並依據 ECMAScript Date 規格中的格里高利曆規則進行驗證,因此 2024-02-29 會被接受,1900-02-29 會被拒絕,而 2025-04-31 不會悄悄進位到五月。
- 它將每個接受的日期轉換為 UTC 日序數,方法是在 UTC Date 物件上設定年、月、日,將其毫秒值除以精確的 86,400,000,並以相對於 1970-01-01 的整數位置作為樣本空間。
- 它從瀏覽器的 Web Crypto getRandomValues API 抽取亂數,使用的是無正負號 32 位元字,而非來自 Math.random()。
- 它使用拒絕抽樣,因此當 2^32 無法整除範圍大小時,不會有任何行事曆日繼承模運算餘數所帶來的額外來源值。
- 它使用 UTC 取得器來格式化結果,因此使用者本地時區的日光節約時間位移不會改變輸出中出現的日期。
最後這一點是大多數替代工具所忽略的。在 UTC 日序數上進行抽樣並以 UTC 取得器進行格式化,代表不論使用者位於柏林、聖保羅或加爾各答,同一個序數都會回傳同一個行事曆日期。W3C Web Cryptography API 將 getRandomValues 定義為此類亂數的標準瀏覽器介面,使實作得以與平台慣例一致,而非使用自訂的 PRNG。
三步驟產生隨機日期
介面刻意保持精簡。大多數使用者在第一次嘗試時,就能取得一份可用的隨機日期清單。
- 以 YYYY-MM-DD 格式選擇有效的開始日期與結束日期。兩個端點皆可被選中,因此從 2024-02-28 到 2024-03-01 的範圍,可能回傳 2 月 28 日、日或 3 月 1 日。
- 輸入 1 到 1,000 之間的數量,並決定是否允許同一日期重複出現。不重複模式會執行稀疏的部分 Fisher-Yates 不放回抽樣,並在數量超過可用天數時拒絕執行,因此工具絕不會悄悄啟用重複或回傳較短的清單。
- 點擊產生,確認顯示的範圍與數量,然後複製或記錄所需的值。編輯任一端點、更改數量或切換重複模式,會清除舊的清單與先前的錯誤,確保先前的結果不會殘留而與新設定混淆。
實際的轉換過程很直觀。輸入 2024-01-15 會被設定到 UTC Date 物件上,其持有的毫秒值為 1,705,276,800,000。將 1,705,276,800,000 除以精確的 86,400,000 會得到整數 19,737,將該行事曆日置於樣本空間中 1970-01-01 之後 19,737 天的位置。每個被接受的 YYYY-MM-DD 都會化約為同類的整數,抽樣發生在這些整數之上,而非原始時間戳記。
均勻抽樣如何消除偏差與日光節約時間漂移
在比較替代方案時,最重要的兩個技術選擇是亂數來源與行事曆表示方式。Math.random() 雖然方便,但不適合任何具有稽核影響的用途,也無法被植入種子以進行可重現的軟體測試。Web Crypto getRandomValues 能從平台加密安全來源提供不偏誤的隨機 Uint32 字,且當某些日位置會因此多出一個底層字時,工具會拒絕這些值。結果是,從包含首尾的開始到結束,每個符合資格的行事曆日期擁有完全相同的選中機率。
不受日光節約時間影響的表示方式同樣重要。在 UTC 日序數上而非本地午夜時間戳記上進行抽樣,代表無論使用者在執行工具當日其所在地是否將時鐘往前或往後調整,輸出清單中包含的日期都會是他們所要求的確切日期。不會有跳過的日子、不會有重複的日子,也不會有將一小時位移誤認為長篇測試固定資料中缺漏項目的情況。希望透過逐步導覽理解同樣概念套用於範圍的讀者,可以參考 how to generate random dates from any range 指南,該指南使用同一款工具作為其來源。
| 方法 | 亂數來源 | 行事曆模型 | 重複處理 | 資料位置 |
|---|---|---|---|---|
| Random Date Generator(本工具) | Web Crypto getRandomValues | UTC 日序數 | 可選的不重複模式 | 僅在瀏覽器中,不上傳 |
| 試算表 RAND 搭配 DATE 組合 | 等效的 Math.random | 本地午夜加上小時 | 每個儲存格獨立抽樣 | 本地試算表檔案 |
| 基於 Math.random 的線上產生器 | Math.random 搭配模運算 | 視實作而異 | 視實作而異 | 經常上傳到伺服器 |
| 使用伺服器腳本的線上產生器 | 伺服器端 RNG | 視實作而異 | 視實作而異 | 傳送至遠端伺服器 |
限制、驗證規則,以及工具不做的事
了解一款工具在哪裡停下來,與了解它能做什麼一樣重要。Random Date Generator 會拒絕某些輸入,而非悄悄修復它們,這本身就是它能作為真正替代方案的原因之一。
- 支援的民用年份從 0001-01-01 延伸至 9999-12-31,並對 0001 到 0099 之間的年份採取嚴格的兩位數年份拒絕政策,使它們保持字面上的年份,而不會被 Date.UTC 的歷史行為移入二十世紀。
- 空白的數量、分數、零、負值或任何超過 1,000 的值,都會產生清楚的錯誤訊息,陳述允許的範圍並確認沒有任何內容遭到截斷。
- 開始日期不得晚於結束日期。單日範圍有效且必定回傳該日期,但若要從單日範圍取得重複結果,必須啟用重複模式。
- 無效的日與溢位日會在輸入時被拒絕。工具不會將 2025-04-31 進位到 5 月 1 日,而 1900-02-29 會被拒絕,因為世紀年若不能被 400 整除則為平年。
- 清單不會排除週末、國定假日、歷史法過渡、不可預訂日或組織特定的封鎖日期。這些限制必須在使用該日期進入實際流程之前另行檢查。
這種明確拒絕的行為,正是慎的替代方案與悄悄回傳錯誤資料的工具之間的分野。如果你需要僅限工作日的日期或具假日意識的選擇,單純的隨機挑選是錯誤的起點,而本工具也不會假裝能夠做到。
瀏覽器替代方案適用與不適用的情境
對於測試固定資料、寫作提示、範例時程、隨機化練習、課堂示範及類似的非權威性用途,一款在本機執行的瀏覽器型替代方案是相當合適的選擇。其輸出僅在你保留產生的清單或執行自己可植入種子的產生器時才可重現,因為 Web Crypto 在此介面下刻意不支援種子植入。這是一項刻意的取捨:以保留方式而非以種子實現可重現性,對於一般的實用工作是可以接受的,同時也避免了在不該使用可植入種子 PRNG 的情境中,因種子化而對公平性產生錯誤的安心感。
對於公平的抽樣活動,相同的機率並不代表某次執行看起來會均勻分佈,而不重複模式也可能合理地重複某些值。若某項選擇涉及財務、法律、競賽、安全或稽核上的後果,請使用具備獨立監督與留存證據之書面化程序,而非單一的瀏覽器工具。這正是本工具的合約中明確標示為超出範疇的工作類型,而誠實面對這項區別,本身就是成為真正替代方案而非行銷說法的一部分。
一個務實的判斷方式是自問:如果結果遭到質疑,會發生什麼事?若答案是「我們會取消一場競賽」、「我們會失去一筆合約」或「我們會在稽核中失敗」,請將隨機抽選與書面化的程序搭配使用。若答案是「我們只是會挑別的示範日期」,那麼 Random Date Generator 就能獨力在瀏覽器中完成這項工作,無需將範圍傳送到任何地方。
延伸閱讀:Random IP Generator: Test Fixtures Without Public IP Risk。