使用 bttf 精通日期時間運算:現代化的 CLI 十字鎬工具

在終端機中處理日期和時間是一件令人沮喪的體驗。對於許多開發者來說,標準的 date 指令是一個使用頻率不夠高,以至於其參數(flags)和特有的行為在每次使用之間都會被遺忘的工具,導致不斷重複閱讀手冊的惡性循環。這時,bttf 就登場了,它是一款用於日期時間運算、解析和格式化的命令列「十字鎬」工具。

由 BurntSushi 開發的 bttf 並非設計作為 POSIX date 的直接替代品,而是作為一個更直觀且功能更強大的替代方案。其目標是提供一種簡潔的方式來處理複雜的時間計算和格式化任務,否則這些任務可能需要繁瑣的 shell 腳本或自定義代碼。

超越簡單的格式化

雖然 bttf 可以執行基本任務,例如列印當前時間或透過 strftime 語法格式化日期,但其真正的威力在於處理相對時間和複雜序列的能力。

相對時間與運算

與其與複雜的參數糾纏不清,bttf 允許使用類似自然語言的運算。您可以輕鬆地將持續時間添加到當前時間,或尋找過去或未來的特定日期:

# 將一週和 12 小時添加到當前時間
$ bttf time add '1 week, 12 hours ago' now

# 尋找自特定日期以來的持續時間,並四捨五入到最近的一天
$ bttf span since 2025-01-20T12:00 | bttf span round -l day -s day

強大的序列生成

最突出的功能之一是 seq 指令,它可以取代數十行 Bash 腳本。例如,生成一個清單,列出直到年底前的每個月第二個星期二,只需一行指令即可完成:

$ bttf time seq monthly -w 2-tue --until $(bttf time end-of year now) | bttf time fmt -f '%a, %F'

架構:Jiff 與「民用時間」問題

在底層,bttf 是由 Jiff 提供動力,這是一個 Rust 函式庫,旨在解決許多日期時間 API 中的一個根本缺陷:混淆了「民用時間」(civil time)與「絕對瞬間」(absolute instants)。

正如社群成員所指出的,大多數 API 在處理日光節約時間(DST)時會默默地選擇一邊。例如,在特定時區內詢問「現在 30 天後是什麼時候」可能會導致 29 天又 23 小時或 30 天又 0 小時的經過時間,具體取決於是否發生了 DST 轉換。Jiff(受 TC39 為 JavaScript 提出的 Temporal 提案啟發)將這些視為不同的類型,確保計算是明確且可預測的。

進階工作流:tag 指令

或許 bttf 最具創新性的功能是 tag 指令。這允許該工具處理任意數據——不僅僅是日期時間——透過在文本流中識別時間戳,將其包裝在 JSON lines 格式中進行處理,然後再將其「取消標記」(untagging)回原始文本。

這使得強大的流水線(pipelines)成為可能。例如,作者展示了如何列出 git 儲存庫中的所有文件,按其最後一次提交日期排序,並以本地時間格式化:

$ git ls-files | bttf tag exec git log -n1 --format='%aI' | bttf time in system | bttf time sort | bttf time fmt -f '%a %Y-%m-%d %H:%M:%S' | bttf untag -f '{tag}|t{data}'

在此工作流中,bttf tag exec 會為每個文件並行地執行 git 指令,隨後的 bttf time 指令會處理時區轉換、排序和格式化,最後由 untag 恢復原始文件路徑並附帶格式化後的日期。

社群觀點:CLI vs. AI

bttf 的發布引起了關於在 LLM 時代,專用化 CLI 工具實用性的有趣辯論。一些用戶認為,一次性的時間戳轉換或日期計算現在可以透過詢問 AI 來更高效地處理。

然而,其他人指出,對於程式化工作流、自動化和整合到 AI 代理(agent)中(其中工具可以作為函數調用),一個確定性、高速度、精確的且 CLI 工具是不可或缺的。正如一位用戶所說,單單 bttf time seq 就能取代 40 行用於電子報排程的自定義 Bash 腳本。

安裝與使用

對於想要嘗試的人,bttf 提供 Windows、macOS 和 Linux 的預編譯二進位檔,或者透過 Cargo 為 Rust 開發者提供:

cargo install bttf

註:語言區域(Locale)支持默認啟用,但可以在安裝時禁用它(--no-default-features)以減少二進位檔大小並加快編譯速度。

Sources