Skip to content

Commit a353232

Browse files
committed
Add stream created datetime to StreamInfo
The field is already exposed by NATS "$JS.API.STREAM.INFO.{name}" API: https://nats-io.github.io/nats.js/jetstream/types/StreamInfo.html Since it's official part of protocol, let's expose it to the user. Golang implementation already do so: https://github.com/nats-io/nats.go/blob/4ec2f446e4cd829a7be3bf9aa16c43a7fddeaed9/jetstream/stream_config.go#L32 Example API response: ```json { "type": "io.nats.jetstream.api.v1.stream_info_response", "total": 0, "offset": 0, "limit": 0, "created": "2025-11-02T15:34:21.730004852Z", "config": { "name": "stream", "subjects": [ "test.>" ], "retention": "limits", "max_consumers": -1, "max_msgs": -1, "max_bytes": 2147483648, "max_age": 86400000000000, "max_msgs_per_subject": -1, "max_msg_size": -1, "discard": "old", "storage": "file", "num_replicas": 1, "duplicate_window": 120000000000, "compression": "s2", "allow_direct": false, "mirror_direct": false, "sealed": false, "deny_delete": false, "deny_purge": false, "allow_rollup_hdrs": false, "consumer_limits": {} }, "state": { "messages": 1249954, "bytes": 1036040689, "first_seq": 3326784, "first_ts": "2025-11-03T08:38:40.571255423Z", "last_seq": 4576737, "last_ts": "2025-11-03T13:34:30.52654449Z", "num_subjects": 2, "consumer_count": 1 }, "cluster": { "leader": "nats-0" }, "ts": "2025-11-03T13:34:30.530396449Z" } ```
1 parent 9afa315 commit a353232

File tree

2 files changed

+20
-11
lines changed

2 files changed

+20
-11
lines changed

nats/src/nats/js/api.py

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,18 @@ def _to_nanoseconds(val: Optional[float]) -> Optional[int]:
8585
return 0
8686
return int(val * _NANOSECOND)
8787

88+
@classmethod
89+
def _python38_iso_parsing(cls, time_string: str):
90+
# Replace Z with UTC offset
91+
s = time_string.replace("Z", "+00:00")
92+
# Trim fractional seconds to 6 digits
93+
date_part, frac_tz = s.split(".", 1)
94+
frac, tz = frac_tz.split("+")
95+
frac = frac[:6] # keep only microseconds
96+
s = f"{date_part}.{frac}+{tz}"
97+
return s
98+
99+
88100
@classmethod
89101
def from_response(cls: type[_B], resp: Dict[str, Any]) -> _B:
90102
"""Read the class instance from a server response.
@@ -410,6 +422,7 @@ class StreamInfo(Base):
410422
sources: Optional[List[StreamSourceInfo]] = None
411423
cluster: Optional[ClusterInfo] = None
412424
did_create: Optional[bool] = None
425+
created: Optional[datetime.datetime] = None
413426

414427
@classmethod
415428
def from_response(cls, resp: Dict[str, Any]):
@@ -418,6 +431,12 @@ def from_response(cls, resp: Dict[str, Any]):
418431
cls._convert(resp, "mirror", StreamSourceInfo)
419432
cls._convert(resp, "sources", StreamSourceInfo)
420433
cls._convert(resp, "cluster", ClusterInfo)
434+
435+
if "created" in resp and resp["created"]:
436+
resp["created"] = datetime.datetime.fromisoformat(cls._python38_iso_parsing(resp["created"])).astimezone(
437+
datetime.timezone.utc
438+
)
439+
421440
return super().from_response(resp)
422441

423442

@@ -711,17 +730,6 @@ def header(self) -> Optional[Dict]:
711730
"""
712731
return self.headers
713732

714-
@classmethod
715-
def _python38_iso_parsing(cls, time_string: str):
716-
# Replace Z with UTC offset
717-
s = time_string.replace("Z", "+00:00")
718-
# Trim fractional seconds to 6 digits
719-
date_part, frac_tz = s.split(".", 1)
720-
frac, tz = frac_tz.split("+")
721-
frac = frac[:6] # keep only microseconds
722-
s = f"{date_part}.{frac}+{tz}"
723-
return s
724-
725733
@classmethod
726734
def from_response(cls, resp: Dict[str, Any]):
727735
resp["time"] = datetime.datetime.fromisoformat(cls._python38_iso_parsing(resp["time"])).astimezone(

nats/tests/test_js.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1251,6 +1251,7 @@ async def test_stream_management(self):
12511251
assert isinstance(current.config, nats.js.api.StreamConfig)
12521252
assert current.config.name == "hello"
12531253
assert isinstance(current.state, nats.js.api.StreamState)
1254+
assert isinstance(current.created, datetime.datetime)
12541255

12551256
# Send messages
12561257
producer = nc.jetstream()

0 commit comments

Comments
 (0)