Skip to content

Commit 8103652

Browse files
committed
Add oldest and newest timestamps to moving window
Methods to retrieve the timestamps of the oldest and newest sample in the moving window. Signed-off-by: cwasicki <[email protected]>
1 parent 6c035ff commit 8103652

File tree

3 files changed

+46
-1
lines changed

3 files changed

+46
-1
lines changed

RELEASE_NOTES.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
## New Features
1212

1313
- DFS for compentent graph
14-
- `MovingWindow`: Provide access to `capacity` (maximum number of elements).
14+
- `MovingWindow`: Provide access to `capacity` (maximum number of elements),
15+
`oldest_timestamp` and `newest_timestamp` of the window.
1516

1617
## Bug Fixes
1718

src/frequenz/sdk/timeseries/_moving_window.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,32 @@ def capacity(self) -> int:
221221
"""
222222
return self._buffer.maxlen
223223

224+
@property
225+
def oldest_timestamp(self) -> datetime | None:
226+
"""
227+
Return the oldest timestamp in the MovingWindow.
228+
229+
Returns:
230+
The oldest timestamp in the MovingWindow.
231+
If the MovingWindow is empty, None is returned.
232+
"""
233+
if len(self._buffer) == 0:
234+
return None
235+
return self._buffer.time_bound_oldest
236+
237+
@property
238+
def newest_timestamp(self) -> datetime | None:
239+
"""
240+
Return the newest timestamp in the MovingWindow.
241+
242+
Returns:
243+
The newest timestamp in the MovingWindow.
244+
If the MovingWindow is empty, None is returned.
245+
"""
246+
if len(self._buffer) == 0:
247+
return None
248+
return self._buffer.time_bound_newest
249+
224250
async def _run_impl(self) -> None:
225251
"""Awaits samples from the receiver and updates the underlying ring buffer.
226252

tests/timeseries/test_moving_window.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,24 @@ async def test_window_size() -> None:
131131
assert len(window) == 5, "Window should be full"
132132

133133

134+
async def test_timestamps() -> None:
135+
"""Test the timestamp methods of the window."""
136+
window, sender = init_moving_window(timedelta(seconds=5))
137+
assert (
138+
window.oldest_timestamp is None
139+
), "For an empty window, oldest timestamp should be None"
140+
assert (
141+
window.newest_timestamp is None
142+
), "For an empty window, newest timestamp should be None"
143+
await push_logical_meter_data(sender, range(0, 20))
144+
assert window.oldest_timestamp == UNIX_EPOCH + timedelta(
145+
seconds=15
146+
), "Wrong oldest timestamp"
147+
assert window.newest_timestamp == UNIX_EPOCH + timedelta(
148+
seconds=19
149+
), "Wrong newest timestamp"
150+
151+
134152
# pylint: disable=redefined-outer-name
135153
async def test_resampling_window(fake_time: time_machine.Coordinates) -> None:
136154
"""Test resampling in MovingWindow."""

0 commit comments

Comments
 (0)