From f75e87b7f24a8c0029d6c22ada1ec5b7a7026a67 Mon Sep 17 00:00:00 2001 From: kokokoXUY <13682395396@163.com> Date: Sat, 26 Sep 2026 13:00:30 +0800 Subject: [PATCH] fix: accept stdlib timezones in now helper annotations The public now, today, tomorrow, and yesterday helpers already accept datetime.tzinfo objects at runtime. Align their signatures with DateTime.now and cover standard library timezone and ZoneInfo inputs with typed tests. Fixes #783. --- README.rst | 5 +++++ docs/docs/instantiation.md | 3 +++ src/pendulum/__init__.py | 8 ++++---- tests/test_main.py | 22 ++++++++++++++++++++++ 4 files changed, 34 insertions(+), 4 deletions(-) diff --git a/README.rst b/README.rst index e2ae92f2a..84930fda2 100644 --- a/README.rst +++ b/README.rst @@ -24,6 +24,11 @@ Supports Python **3.10 and newer**. >>> now_in_paris '2016-07-04T00:49:58.502116+02:00' + # Standard library timezone objects work too + >>> from datetime import timezone as datetime_timezone + >>> pendulum.now(datetime_timezone.utc).is_utc() + True + # Seamless timezone switching >>> now_in_paris.in_timezone('UTC') '2016-07-03T22:49:58.502116+00:00' diff --git a/docs/docs/instantiation.md b/docs/docs/instantiation.md index a49c6a26c..0223fb94f 100644 --- a/docs/docs/instantiation.md +++ b/docs/docs/instantiation.md @@ -64,6 +64,9 @@ There is also the `now()` method. 'Europe/London' ``` +`now()` also accepts standard library `datetime.tzinfo` objects, including +`datetime.timezone.utc` and `zoneinfo.ZoneInfo`. + To accompany `now()`, a few other static instantiation helpers exist to create known instances. The only thing to really notice here is that `today()`, `tomorrow()` and `yesterday()`, besides behaving as expected, all accept a timezone parameter diff --git a/src/pendulum/__init__.py b/src/pendulum/__init__.py index 16ae0865c..4625f8568 100644 --- a/src/pendulum/__init__.py +++ b/src/pendulum/__init__.py @@ -238,28 +238,28 @@ def instance( return DateTime.instance(obj, tz=tz) -def now(tz: str | Timezone | None = None) -> DateTime: +def now(tz: str | _datetime.tzinfo | None = None) -> DateTime: """ Get a DateTime instance for the current date and time. """ return DateTime.now(tz) -def today(tz: str | Timezone = "local") -> DateTime: +def today(tz: str | _datetime.tzinfo = "local") -> DateTime: """ Create a DateTime instance for today. """ return now(tz).start_of("day") -def tomorrow(tz: str | Timezone = "local") -> DateTime: +def tomorrow(tz: str | _datetime.tzinfo = "local") -> DateTime: """ Create a DateTime instance for tomorrow. """ return today(tz).add(days=1) -def yesterday(tz: str | Timezone = "local") -> DateTime: +def yesterday(tz: str | _datetime.tzinfo = "local") -> DateTime: """ Create a DateTime instance for yesterday. """ diff --git a/tests/test_main.py b/tests/test_main.py index 76033450a..9ebefb947 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -5,6 +5,7 @@ from datetime import date from datetime import datetime from datetime import time +from datetime import timezone as datetime_timezone from dateutil import tz @@ -15,6 +16,27 @@ from pendulum.tz.timezone import Timezone +def test_now_helpers_accept_stdlib_timezone() -> None: + for value in ( + pendulum.now(datetime_timezone.utc), + pendulum.today(datetime_timezone.utc), + pendulum.tomorrow(datetime_timezone.utc), + pendulum.yesterday(datetime_timezone.utc), + ): + assert value.timezone_name == "UTC" + + +def test_now_helpers_accept_zoneinfo_timezone() -> None: + paris = zoneinfo.ZoneInfo("Europe/Paris") + for value in ( + pendulum.now(paris), + pendulum.today(paris), + pendulum.tomorrow(paris), + pendulum.yesterday(paris), + ): + assert value.timezone_name == "Europe/Paris" + + def test_instance_with_naive_datetime_defaults_to_utc() -> None: now = pendulum.instance(datetime.now()) assert now.timezone_name == "UTC"