Skip to content

Commit 1600b0f

Browse files
authored
TimeStamper() now uses TZ-aware objects (#709)
* TimeStamper() now uses TZ-aware objects The default output doesn't change but manual formatting allows for TZ data now. Fixes #703 * Add changelog * Handle negative timezones * Only add TZ when potentially useful
1 parent 3a7006d commit 1600b0f

File tree

3 files changed

+20
-4
lines changed

3 files changed

+20
-4
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ You can find our backwards-compatibility policy [here](https://github.com/hynek/
2626
- `structlog.stdlib.BoundLogger`'s binding-related methods now also return `Self`.
2727
[#694](https://github.com/hynek/structlog/pull/694)
2828

29+
- `structlog.processors.TimeStamper` now produces internally timezone-aware `datetime` objects.
30+
Default output hasn't changed, but you can now use `%z` in your *fmt* string.
31+
[#709](https://github.com/hynek/structlog/pull/709)
32+
2933

3034
### Fixed
3135

src/structlog/processors.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,8 @@ def now() -> datetime.datetime:
525525
else:
526526

527527
def now() -> datetime.datetime:
528-
# A naive local datetime is fine here, because we only format it.
528+
# We don't need the TZ for our own formatting. We add it only for
529+
# user-defined formats later.
529530
return datetime.datetime.now() # noqa: DTZ005
530531

531532
if fmt is None:
@@ -553,7 +554,7 @@ def stamper_iso_utc(event_dict: EventDict) -> EventDict:
553554
return stamper_iso_local
554555

555556
def stamper_fmt(event_dict: EventDict) -> EventDict:
556-
event_dict[key] = now().strftime(fmt)
557+
event_dict[key] = now().astimezone().strftime(fmt)
557558

558559
return event_dict
559560

tests/processors/test_renderers.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -396,8 +396,8 @@ def test_inserts_utc_unix_timestamp_by_default(self):
396396
@freeze_time("1980-03-25 16:00:00")
397397
def test_local(self):
398398
"""
399-
Timestamp in local timezone work. We can't add a timezone to the
400-
string without additional libraries.
399+
Timestamp in local timezone work. Due to historic reasons, the default
400+
format does not include a timezone.
401401
"""
402402
ts = TimeStamper(fmt="iso", utc=False)
403403
d = ts(None, None, {})
@@ -414,6 +414,17 @@ def test_formats(self):
414414

415415
assert "1980" == d["timestamp"]
416416

417+
@freeze_time("1980-03-25 16:00:00")
418+
def test_tz_aware(self):
419+
"""
420+
The timestamp that is used for formatting is timezone-aware.
421+
"""
422+
ts = TimeStamper(fmt="%z")
423+
d = ts(None, None, {})
424+
425+
assert "" == datetime.datetime.now().strftime("%z") # noqa: DTZ005
426+
assert "" != d["timestamp"]
427+
417428
@freeze_time("1980-03-25 16:00:00")
418429
def test_adds_Z_to_iso(self):
419430
"""

0 commit comments

Comments
 (0)