Skip to content

Commit 01e8a43

Browse files
committed
Message.mesage_datetime property
1 parent 057e03b commit 01e8a43

File tree

2 files changed

+30
-0
lines changed

2 files changed

+30
-0
lines changed

dramatiq/message.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import dataclasses
1919
import time
2020
import uuid
21+
from datetime import datetime, timezone
2122
from typing import Any, Dict, Generic, Optional, Tuple, TypeVar
2223

2324
from .broker import get_broker
@@ -187,3 +188,13 @@ def _fields(self) -> Tuple[str, ...]:
187188

188189
def _replace(self, **changes) -> "Message[R]":
189190
return dataclasses.replace(self, **changes)
191+
192+
@property
193+
def message_datetime(self) -> datetime:
194+
"""Read ``message_timestamp`` as a UTC-aware datetime.
195+
196+
Datetime precision is limited by the representation of ``Message.message_timestamp``, which is an
197+
integer storing milliseconds.
198+
"""
199+
unix_seconds, ms = divmod(self.message_timestamp, 1000)
200+
return datetime.utcfromtimestamp(unix_seconds).replace(microsecond=ms * 1000, tzinfo=timezone.utc)

tests/test_messages.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import dramatiq
2+
from datetime import datetime, timezone, timedelta
23

34

45
def test_messages_have_namedtuple_methods(stub_broker):
@@ -45,3 +46,21 @@ def actor(arg):
4546

4647
assert repr(message) in repr(message_proxy), "Expecting MessageProxy repr to contain Message repr"
4748
assert str(message) == str(message_proxy), "Expecting identical __str__ of MessageProxy and Message"
49+
50+
51+
def test_message_datetime(stub_broker):
52+
"""Test reading message time as datetime."""
53+
54+
@dramatiq.actor
55+
def actor(arg):
56+
return arg
57+
58+
message = actor.send("input")
59+
after = datetime.now(timezone.utc)
60+
61+
assert message.message_datetime.tzinfo is timezone.utc
62+
assert message.message_datetime < after
63+
assert message.message_datetime > after - timedelta(seconds=1)
64+
65+
# no rounding problems here because message_timestamp is an int
66+
assert message.message_datetime.timestamp() == message.message_timestamp / 1000

0 commit comments

Comments
 (0)