HOWTO · Python
在 Python 中將 datetime 轉換為帶毫秒的字串
將 Python datetime 轉換為正好包含三位毫秒數字的 ISO 風格或自訂字串。
本頁內容
當 ISO 風格結果合適時,使用 value.isoformat(timespec="milliseconds")。當需要自訂版面時,使用帶 %f 的 strftime() 並移除最後三位。兩種方法都會把微秒截斷為毫秒,而不是四捨五入。
格式化只改變表示形式,不改變 datetime 值本身。範例使用固定輸入,因此可以精確驗證輸出;選好需要的版面後,請把這些建構子替換為應用程式中的值。如果接收系統需要偏移量,請在格式化前讓該值具備時區。
使用 isoformat() 取得三位毫秒精度
datetime.isoformat() 是產生 ISO 8601 風格字串最清楚的選擇。timespec="milliseconds" 參數永遠輸出正好三位秒的小數部分。它可用於 Python 3.6 及更新版本。
請準確傳入小寫複數字串 "milliseconds"。其他支援的 timespec 值會選擇不同精度,而未知值會引發 ValueError。當下游結構描述需要固定欄位寬度時,這個明確參數比依賴預設 "auto" 行為更合適。
以下決定性範例使用具備時區的 datetime,因此結果也顯示 isoformat() 會保留 UTC 偏移量:
"""Show the recommended ISO-style millisecond formatting behavior."""
from datetime import datetime, timezone
value = datetime(2026, 9, 16, 12, 34, 56, 789654, tzinfo=timezone.utc)
print(value.isoformat(timespec="milliseconds"))
輸出:
2026-09-16T12:34:56.789+00:00
六位 microsecond 值 789654 會變成 .789。Python 不會把該值四捨五入為 .790;timespec 控制顯示哪些元件,而被排除的時間元件會被截斷。
當字串必須跨系統識別真實時刻時,請使用具備時區的 datetime。naive 值沒有 UTC 偏移量,因此其格式化文字本身無法區分本地時間、UTC 或其他時區。
isoformat() 會保留物件上既有的偏移量;它不會把值轉換為 UTC。如果資料契約要求 UTC,請先正規化 datetime。相反地,只有當消費端明確期待本地壁鐘時間時,才省略時區轉換。
使用 strftime() 建立自訂版面
當需要控制順序、分隔符或其他欄位時,使用 strftime()。%f 指令會產生六位微秒數字。使用 [:-3] 切片會刻意移除最後三位並留下毫秒精度:
"""Show millisecond precision in a custom datetime string format."""
from datetime import datetime
value = datetime(2026, 9, 16, 12, 34, 56, 789654)
print(value.strftime("%Y-%m-%d %H:%M:%S.%f")[:-3])
輸出:
2026-09-16 12:34:56.789
這種切片是安全的,因為 %f 永遠提供一個以零補齊的六位欄位,即使原始值沒有微秒也是如此。在使用 [:-3] 之前,請讓 .%f 位於格式末尾;否則切片可能會移除其他欄位中的字元。
該操作是截斷而不是四捨五入。例如,789999 微秒仍會變成 789 毫秒。如果規格要求四捨五入,請在格式化前對 datetime 進行捨入,並處理可能進位到下一秒的情況;單純切片 %f 無法實作該規則。
匯入方式決定如何呼叫這個類別。使用 from datetime import datetime 時,呼叫 datetime.now()。如果改寫為 import datetime,則呼叫 datetime.datetime.now()。
理解 str() 與切片邊界
普通 str(value) 等同於 value.isoformat(" ")。其預設 timespec="auto" 會在 microsecond 為零時省略小數欄位,否則輸出全部六位微秒數字。因此,str(value) 不保證三位毫秒欄位,盲目套用 [:-3] 並不安全。
這種可變寬度行為適合非正式顯示,但不適合固定寬度欄位。切片前檢查小數點可以避免破壞秒數,但它仍會重複 isoformat(timespec="milliseconds") 已處理的邏輯,並且還要額外注意時區後綴。
這個邊界範例也顯示,毫秒輸出會在 999999 微秒處被截斷,而且單數值 "millisecond" 無效:
"""Expose truncation, zero-microsecond slicing, and invalid-timespec boundaries."""
from datetime import datetime
almost_next_second = datetime(2026, 9, 16, 12, 34, 56, 999999)
without_fraction = datetime(2026, 9, 16, 12, 34, 56)
print(almost_next_second.isoformat(timespec="milliseconds"))
print(str(without_fraction))
print(str(without_fraction)[:-3])
try:
without_fraction.isoformat(timespec="millisecond")
except ValueError as error:
print(f"{type(error).__name__}: {error}")
輸出:
2026-09-16T12:34:56.999
2026-09-16 12:34:56
2026-09-16 12:34
ValueError: Unknown timespec value
第三行不是有效的毫秒轉換:它刪除了 :56,因為輸入沒有小數欄位。請優先使用 isoformat(timespec="milliseconds"),或者使用包含 %f 的格式,而不是切片 str() 的可變長度結果。
選擇合適的方法
對於機器可讀時間戳與標準交換,使用 isoformat(timespec="milliseconds")。它無需手動字串處理,就能處理零微秒、截斷與時區偏移。只有在消費端需要自訂版面時,才使用 strftime() 加 [:-3]。
請根據輸出契約而不是方便程度來選擇:isoformat() 提供標準化日期時間形狀,strftime() 提供呼叫方定義的形狀,而 str() 提供適合人類閱讀但小數精度可變的預設值。無論哪種情況,都要說明缺少偏移量代表本地時間、約定的 UTC,還是未知時區。
這些方法會格式化既有的 datetime;它們不會把它轉換為 Unix epoch 以來的毫秒,也不會把字串解析為 datetime。也請記住,顯示的三位數字描述的是毫秒精度,不一定代表時鐘或儲存來源值的準確度。