Paul Ganssle, a Python core developer, writes about datetime and time zone handling, packaging and testing in Python.
Commenters cite his articles as clear explanations of why not to use utcnow and of naive local datetimes, and call the first one great.
It took me some effort to understand the issue here, so an alternative explanation in case it helps someone.
First, the part that's independent of programming language. You may want to read about absolute time and civil time (e.g. from https://abseil.io/docs/cpp/guides/time) but if you don't, in short: “civil time” refers to something like “2019 May 26 at 2:45 pm in New York City” (or “in the America/New_York time zone”), which means (roughly) whatever time the locals in New York City (or a larger shared geo-political zone) would agree is 2:45 pm on that date. To convert this to an absolute time, or in other words to make sense of “2019-05-26 14:45 in America/New_York”, we need data about the real world as of that date: most obviously we need to know whether Daylight-Saving Time was in effect on that date, but also what conventions were in use at the time. (This also means it's hard to know for certain what such a notation in the future means in terms of absolute time, as possibly DST could be abolished or the dates when it comes into effect could change.)
It so happens that in 1884 the conventions of New York City were such that it was about 4 minutes ahead of the then-recently standardized Eastern Time, so about 4 hours and 56 behind GMT.
So, in any “correct” library, we should see the following respected:
• “2019 May 26 at 2:45 pm in New York” should mean “2019 May 26 at 18:45 UTC” (timezone is EDT i.e. UTC minus 4 hours).
• “2019 Jan 26 at 2:45 pm in New York”…
> Isn't assigning out what all made things fast presumptive without benchmarks?
We also have the benchmark of "pip now vs. pip years ago". That has to be controlled for pip version and Python version, but the former hasn't seen a lot of changes that are relevant for most cases, as far as I can tell.
> This also doesn't cover subtle things. Unsure if rkyv is being used to reduce the number of times that TOML is parsed but TOML parse times do show up in benchmarks in Cargo and Cargo/uv's TOML parser is much faster than Python's (note: Cargo team member, `toml` maintainer). I wish the TOML comparison page was still up and showed actual numbers to be able to point to.
This is interesting in that I wouldn't expect that the typical resolution involves a particularly large quantity of TOML. A package installer really only needs to look at it at all when building from source, and part of what these standards have done for us is improve wheel coverage. (Other relevant PEPs here include 600 and its predecessors.) Although that has also largely been driven by education within the community, things like e.g. https://blog.ganssle.io/articles/2021/10/setup-py-deprecated.html and https://pradyunsg.me/blog/2022/12/31/wheels-are-faster-pure-python/ .
Clickable footnotes:
[0]: https://pypi.org/project/stringcase
[1]: https://pypistats.org/packages/stringcase
[2]: https://pradyunsg.me/blog/2022/12/31/wheels-are-faster-pure-python
[3]: https://github.com/pypa/setuptools/issues/4910
[4]: https://github.com/zahlman/stringcase-new
[5]: https://pypi.org/project/stringcase-new
[6]: https://github.com/dmlls/python-casefy
[7]: https://pypistats.org/packages/casefy
[8]: https://peps.python.org/pep-0541/#how-to-request-a-name-transfer
[9]: https://github.com/frictionlessdata/frictionless-py
[10]: https://github.com/frictionlessdata/frictionless-py/pull/1727
[11]: https://github.com/notatallshaw
[12]: https://discuss.python.org/t/_/85847
[13]: https://blog.ganssle.io/articles/2021/10/setup-py-deprecated.html
What do you mean? You type `pip install west` and a binary will appear in `~/.local/bin/west`. This directory needs to be part of your $PATH variable. Done.
Using virtual envs or pipx or poetry or whatever are non-standard.
Packaging Python projects, however, ... don't get me started on the whole `setup.py`, `setup.cfg`, `pyproject.toml` debacle. This article has more information about it, but the fact that this is supposed to be the short version makes it even more infuriating: https://blog.ganssle.io/articles/2021/10/setup-py-deprecated.html
Actually, naïve times are considered aware in the system time zone. There's no good way to create a `tzinfo` object that behaves like "the system time zone" and doesn't have unfortunate consequences. See this article: https://blog.ganssle.io/articles/2022/04/naive-local-datetimes.html
It's not an ideal situation, but given path dependence I don't think it can be improved much from here.
Poetry still uses setuptools! It makes it a lot easier for mortals. This is the blog post that convinced me to switch away from my old build system: https://blog.ganssle.io/articles/2021/10/setup-py-deprecated.html