diff --git a/CHANGELOG.md b/CHANGELOG.md index b781577b..63cb557e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,10 @@ You can find our backwards-compatibility policy [here](https://github.com/hynek/ - `structlog.stdlib.BoundLogger`'s binding-related methods now also return `Self`. [#694](https://github.com/hynek/structlog/pull/694) +- `structlog.processors.TimeStamper` now produces internally timezone-aware `datetime` objects. + Default output hasn't changed, but you can now use `%z` in your *fmt* string. + [#709](https://github.com/hynek/structlog/pull/709) + ### Fixed diff --git a/src/structlog/processors.py b/src/structlog/processors.py index 24731521..4ef75780 100644 --- a/src/structlog/processors.py +++ b/src/structlog/processors.py @@ -525,7 +525,8 @@ def now() -> datetime.datetime: else: def now() -> datetime.datetime: - # A naive local datetime is fine here, because we only format it. + # We don't need the TZ for our own formatting. We add it only for + # user-defined formats later. return datetime.datetime.now() # noqa: DTZ005 if fmt is None: @@ -553,7 +554,7 @@ def stamper_iso_utc(event_dict: EventDict) -> EventDict: return stamper_iso_local def stamper_fmt(event_dict: EventDict) -> EventDict: - event_dict[key] = now().strftime(fmt) + event_dict[key] = now().astimezone().strftime(fmt) return event_dict diff --git a/tests/processors/test_renderers.py b/tests/processors/test_renderers.py index 9fa24e5c..be8007ad 100644 --- a/tests/processors/test_renderers.py +++ b/tests/processors/test_renderers.py @@ -396,8 +396,8 @@ def test_inserts_utc_unix_timestamp_by_default(self): @freeze_time("1980-03-25 16:00:00") def test_local(self): """ - Timestamp in local timezone work. We can't add a timezone to the - string without additional libraries. + Timestamp in local timezone work. Due to historic reasons, the default + format does not include a timezone. """ ts = TimeStamper(fmt="iso", utc=False) d = ts(None, None, {}) @@ -414,6 +414,17 @@ def test_formats(self): assert "1980" == d["timestamp"] + @freeze_time("1980-03-25 16:00:00") + def test_tz_aware(self): + """ + The timestamp that is used for formatting is timezone-aware. + """ + ts = TimeStamper(fmt="%z") + d = ts(None, None, {}) + + assert "" == datetime.datetime.now().strftime("%z") # noqa: DTZ005 + assert "" != d["timestamp"] + @freeze_time("1980-03-25 16:00:00") def test_adds_Z_to_iso(self): """