Add millisecond formatting support to datetime.strftime

Hi,

I’d like to propose adding native support for millisecond precision formatting in Python’s datetime.strftime() API.

Currently, Python provides:

  • %f in strftime() for microseconds (6 digits)

  • datetime.isoformat(timespec="milliseconds") for ISO output

But there is no way to format milliseconds declaratively using strftime().


Rationale

I’ve been doing backend web development with Python and Django for about 10 years, mostly in REST APIs.

In virtually every Django codebase I’ve worked on, I’ve seen patterns like:

dt.isoformat(timespec="milliseconds").replace("+00:00", "Z")

or:

dt.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3]

These are everywhere in web projects.

The reason is simple: in JavaScript and JSON-based APIs, the de-facto standard datetime format is:

YYYY-MM-DDTHH:mm:ss.sssZ

  • millisecond precision

  • ISO-8601

  • Z for UTC

Python cannot generate this format declaratively using strftime().
You either slice strings or post-process output, which defeats the point of formatting directives.

This becomes a real problem in frameworks like Django REST Framework, where datetime formatting is configured using format strings, not functions. You cannot call Python logic there without subclassing and overriding serializers — most projects don’t, and end up with fragile hacks instead.


Precedent

Other web-centric languages offer native millisecond formatters:

  • Ruby: %L (milliseconds)

  • PHP: v (milliseconds)

This indicates that “milliseconds in formatting” is not an exotic requirement — it’s routine web plumbing.


Scope

This proposal does not aim to solve UTC rendering (Z vs +00:00) — that is a separate issue.

The goal here is strictly:

Provide a first-class way to express millisecond precision in strftime()
without string slicing or post-processing.


If this sounds acceptable conceptually, I’d be happy to help implement it (if it’s a python-only thing, I can do it with just little guidance).

Thanks.

6 Likes

I think we just expose the platform’s strftime implementation - see here:

Additional directives may be supported on certain platforms, but only the ones listed here have a meaning standardized by ANSI C. To see the full set of format codes supported on your platform, consult the strftime(3) documentation.

So you may be at the mercy of your platform’s implementation (or of ANSI C, if you’re not willing to risk using a platform-dependent code).

it’s bit more subtle than this: python’s strftime, both in C and in Python, is a wrapper, and it intercepts some format code to implement them. The %f format-code for milliseconds is one of them. Neither macOS, Linux nor Windows (winCRT) strftime defines the %f code.
So, it’s something we already do.

It makes me realize that CPython datetime’s documentation is slightly outdated and misleading.

5 Likes

In this case, you can already use dt.isoformat(timespec="milliseconds") as you said ? It’s easier than using strftime since you don’t have to provide the full format.

As a side note, I had the reverse problem: I had to recently parse a format that had a precision down to the nanosecond, and AFAIK that is not possible using datetime methods. I had to ditch the last digits (they were not critical in my usecase).

Thanks, I hadn’t realised that.

I suspect this is something that could just be raised as a PR. There’s nothing controversial enough (IMO) to need an extended discussion here. Anyone who wants to, can comment on the PR, and unless there are objections it can just get accepted and merged.

3 Likes

You may be interested in Update `str*time` to C11 format codes · Issue #140715 · python/cpython · GitHub, which does a general revamp of the section.