datetime: strftime/strptime sub-second precision specifier (%Nf)
還沒有人認領這個 Issue。
- 主要語言
- Python
- 星號
- 77.2k
- 分支
- 35.9k
- PR 合併指標
- PR 指標待擷取
描述
Feature or enhancement
Note: in this issue datetime refers to datetime.datetime, while time refers to datetime.time. This issue doesn't talk about the time module.
Background
Currently, in datetime.strftime/time.strftime, the only sub-second formatting code available is %f, which produces a fixed-width string of microsecond digits, padded from the left with zeros, like "004312".
Despite %f coding for an integer, its zero-padded nature makes it usable in producing the "fraction of the second" part of a datetime string. For example "%T.%f" results in a string like 22:11:55.012345.
Problem
There is still no way for datetime.strftime/time.strftime, alone to produce milliseconds, like 22:11:55.012, or any other fraction length between 1 and 5.
Non-solutions
If you control the code, you can call d.isoformat(timespec="milliseconds"). If all you have is configuration where you specify the datetime.strftime format string, you're in no luck.
Proposal
I'm proposing an expanded variant of the %f datetime.strftime format code in the form of %Nf where N∈{1,2,3,4,5,6}. It would produce datetime microseconds, zero-padded to 6 decimal positions and truncated to N most significant positions.
Examples:
- If
%f→"012345", then:
%6f→"012345"%5f→"01234"%4f→"0123"%3f→"012"%2f→"01"%1f→"0"
- An ISO 8601 format specifying millisecond precision:
%Y-%m-%dT%H:%M:%S.%3f%:z - A human-friendly format with 2 sub-second decimal places:
%Y-%m-%d %H:%M:%S.%2f %z
Issues and choices
Truncation or rounding
For microseconds equal to 012345, should %5f produce:
"01234"(truncation)"01235"(arithmetic rounding)- some other rounding mode?
My proposed change truncates.
Format code syntax
N in %Nf theoretically conflicts with "optional minimum field width" in POSIX libc. The post by @jb2170 highlights that the conflict is very theoretical because %f is a Python extension (and libc doesn't include sub-seconds in struct tm).
This theoretical conflict could still be avoided by following alternative codes:
%.Nfinstead of%Nf. This however was deemed confusing, since having a dot in the format code suggests that the code would also produce a dot in its output, and generally, round a float rather than truncating an integer.%:Nf(where:Nis analogous to the slicing operation) was floated, with no traction.
Overall, the 2 recently active discussion members are in favour of %Nf. I believe that either %Nf or %:Nf could be valid, which makes 3/3 recent posters in favour of %Nf.
Format code corner cases
In my initial implementation, if N falls outside of the supported [1, 6] range, a ValueError is raised. Since format code scanning operates on characters, such detection will only occur for 0, 7, 8 and 9. A code like "%10f" will not be intercepted and will hit the libc - handling always-incorrect multi-digit codes would complicate parsing in the C variant of wrap_strftime so I'm not considering that.
As an alternative to the ValueError, N=0 could produce nothing while values of 7, 8, 9 could act like N=6.
My preference: No change to initial code.
strptime leniency
In my initial implementation a %Nf code in datetime.strptime/time.strptime means that exactly N digits are expected. "%3f" will accept "111" but not "11" or "1111". This is OK since the existing %f code still accepts any number of digits in the [1, 6] range, as before.
Alternatively, a relaxation could be made instead: for a %Nf code, any number of digits from the range [1, N] could be accepted.
My preference: No relaxation.
Prior art
Rust's chrono lib permits %3f, %6f, and %9f (datetime cannot support %9f, since it doesn't go beyond microseconds).
Has this already been discussed elsewhere?
I have already discussed this feature proposal on Discourse
Links to previous discussion of this feature:
https://discuss.python.org/t/add-millisecond-formatting-support-to-datetime-strftime
Implementation
My initial implementation is in this PR:
Linked PRs
- gh-157291
- gh-157704
貢獻指南
從這裡開始
- 先讀完整個 Issue,再讀專案的貢獻指南。
- 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
- Fork 儲存庫,在一個分支上完成修改。
- 送出 Pull Request,並在描述裡引用這個 Issue 編號。
研究方向
先從連結的 PR gh-157291 和 gh-157704 開始,然後閱讀連結的 Discourse 討論,以及此 issue 中尚未解決的選擇。完成工作需要就 format-code 語法,以及格式化、無效寬度、截斷和 strptime 剖析的行為達成共識,並在連結的工作中反映該實作。
由索引模型根據 Issue 內容生成。
評估
- 技術堆疊
- python
- 領域
- backend
- Issue 類型
- 功能
- 難度
- 5/5
- 預估耗時
- 一週以上
- 活躍度
- 停滯
- 描述清晰度
- 描述清楚
- 新手友好度
- 25/100