Skip to content

Commit 1c4acf7

Browse files
committed
Expose oldest and newest timestamp in moving window
Signed-off-by: cwasicki <[email protected]>
1 parent 945ec5e commit 1c4acf7

File tree

3 files changed

+36
-3
lines changed

3 files changed

+36
-3
lines changed

RELEASE_NOTES.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@
2222

2323
- A new class `Fuse` has been added to represent fuses. This class has a member variable `max_current` which represents the maximum current that can course through the fuse. If the current flowing through a fuse is greater than this limit, then the fuse will break the circuit.
2424

25-
2625
- `MovingWindow` and `OrderedRingBuffer`:
2726
- NaN values are treated as missing when gaps are determined in the `OrderedRingBuffer`.
2827
- Provide access to `capacity` (maximum number of elements) in `MovingWindow`.
28+
- Methods to retrieve oldest and newest timestamp of valid samples are added to both.
2929

3030

3131
## Bug Fixes

src/frequenz/sdk/timeseries/_moving_window.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,26 @@ def sampling_period(self) -> timedelta:
209209
"""
210210
return self._sampling_period
211211

212+
@property
213+
def oldest_timestamp(self) -> datetime | None:
214+
"""
215+
Return the oldest timestamp of the MovingWindow.
216+
217+
Returns:
218+
The oldest timestamp of the MovingWindow or None if the buffer is empty.
219+
"""
220+
return self._buffer.oldest_timestamp
221+
222+
@property
223+
def newest_timestamp(self) -> datetime | None:
224+
"""
225+
Return the newest timestamp of the MovingWindow.
226+
227+
Returns:
228+
The newest timestamp of the MovingWindow or None if the buffer is empty.
229+
"""
230+
return self._buffer.newest_timestamp
231+
212232
@property
213233
def capacity(self) -> int:
214234
"""

tests/timeseries/test_moving_window.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@ def fake_time() -> Iterator[time_machine.Coordinates]:
3636

3737

3838
async def push_logical_meter_data(
39-
sender: Sender[Sample[Quantity]], test_seq: Sequence[float]
39+
sender: Sender[Sample[Quantity]],
40+
test_seq: Sequence[float],
41+
start_ts: datetime = UNIX_EPOCH,
4042
) -> None:
4143
"""Push data in the passed sender to mock `LogicalMeter` behaviour.
4244
@@ -45,8 +47,8 @@ async def push_logical_meter_data(
4547
Args:
4648
sender: Sender for pushing resampled samples to the `MovingWindow`.
4749
test_seq: The Sequence that is pushed into the `MovingWindow`.
50+
start_ts: The start timestamp of the `MovingWindow`.
4851
"""
49-
start_ts: datetime = UNIX_EPOCH
5052
for i, j in zip(test_seq, range(0, len(test_seq))):
5153
timestamp = start_ts + timedelta(seconds=j)
5254
await sender.send(Sample(timestamp, Quantity(float(i))))
@@ -165,3 +167,14 @@ async def test_resampling_window(fake_time: time_machine.Coordinates) -> None:
165167
assert len(window) == window_size / output_sampling
166168
for value in window: # type: ignore
167169
assert 4.9 < value < 5.1
170+
171+
172+
async def test_timestamps() -> None:
173+
"""Test indexing a window by timestamp."""
174+
window, sender = init_moving_window(timedelta(seconds=5))
175+
async with window:
176+
await push_logical_meter_data(
177+
sender, [1, 2], start_ts=UNIX_EPOCH + timedelta(seconds=1)
178+
)
179+
assert window.oldest_timestamp == UNIX_EPOCH + timedelta(seconds=1)
180+
assert window.newest_timestamp == UNIX_EPOCH + timedelta(seconds=2)

0 commit comments

Comments
 (0)