Skip to content

Commit 93cf86e

Browse files
committed
Add oldest and newest timestamp to ring buffer
Signed-off-by: cwasicki <[email protected]>
1 parent 7ae2915 commit 93cf86e

File tree

2 files changed

+53
-2
lines changed

2 files changed

+53
-2
lines changed

src/frequenz/sdk/timeseries/_ringbuffer/buffer.py

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,10 +190,39 @@ def time_bound_newest(self) -> datetime:
190190
Return the time bounds of the ring buffer.
191191
192192
Returns:
193-
The timestamp of the newest sample of the ring buffer.
193+
The timestamp of the newest sample of the ring buffer
194+
or None if the buffer is empty.
194195
"""
195196
return self._datetime_newest
196197

198+
@property
199+
def oldest_timestamp(self) -> datetime | None:
200+
"""Return the oldest timestamp in the buffer.
201+
202+
Returns:
203+
The oldest timestamp in the buffer
204+
or None if the buffer is empty.
205+
"""
206+
if len(self) == 0:
207+
return None
208+
209+
if self.is_missing(self.time_bound_oldest):
210+
return min(g.end for g in self.gaps)
211+
212+
return self.time_bound_oldest
213+
214+
@property
215+
def newest_timestamp(self) -> datetime | None:
216+
"""Return the newest timestamp in the buffer.
217+
218+
Returns:
219+
The newest timestamp in the buffer.
220+
"""
221+
if len(self) == 0:
222+
return None
223+
224+
return self.time_bound_newest
225+
197226
def datetime_to_index(
198227
self, timestamp: datetime, allow_outside_range: bool = False
199228
) -> int:

tests/timeseries/test_ringbuffer.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,51 +204,73 @@ def dt(i: int) -> datetime: # pylint: disable=invalid-name
204204
return datetime.fromtimestamp(i, tz=timezone.utc)
205205

206206

207-
def test_gaps() -> None:
207+
def test_gaps() -> None: # pylint: disable=too-many-statements
208208
"""Test gap treatment in ordered ring buffer."""
209209
buffer = OrderedRingBuffer([0.0] * 5, ONE_SECOND)
210+
assert buffer.oldest_timestamp is None
211+
assert buffer.newest_timestamp is None
210212
assert len(buffer) == 0
211213
assert len(buffer.gaps) == 0
212214

213215
buffer.update(Sample(dt(0), Quantity(0)))
216+
assert buffer.oldest_timestamp == dt(0)
217+
assert buffer.newest_timestamp == dt(0)
214218
assert len(buffer) == 1
215219
assert len(buffer.gaps) == 1
216220

217221
buffer.update(Sample(dt(6), Quantity(0)))
222+
assert buffer.oldest_timestamp == dt(6)
223+
assert buffer.newest_timestamp == dt(6)
218224
assert len(buffer) == 1
219225
assert len(buffer.gaps) == 1
220226

221227
buffer.update(Sample(dt(2), Quantity(2)))
222228
buffer.update(Sample(dt(3), Quantity(3)))
223229
buffer.update(Sample(dt(4), Quantity(4)))
230+
assert buffer.oldest_timestamp == dt(2)
231+
assert buffer.newest_timestamp == dt(6)
224232
assert len(buffer) == 4
225233
assert len(buffer.gaps) == 1
226234

227235
buffer.update(Sample(dt(3), None))
236+
assert buffer.oldest_timestamp == dt(2)
237+
assert buffer.newest_timestamp == dt(6)
228238
assert len(buffer) == 3
229239
assert len(buffer.gaps) == 2
230240

231241
buffer.update(Sample(dt(3), Quantity(np.nan)))
242+
assert buffer.oldest_timestamp == dt(2)
243+
assert buffer.newest_timestamp == dt(6)
232244
assert len(buffer) == 3
233245
assert len(buffer.gaps) == 2
234246

235247
buffer.update(Sample(dt(2), Quantity(np.nan)))
248+
assert buffer.oldest_timestamp == dt(4)
249+
assert buffer.newest_timestamp == dt(6)
236250
assert len(buffer) == 2
237251
assert len(buffer.gaps) == 2
238252

239253
buffer.update(Sample(dt(3), Quantity(3)))
254+
assert buffer.oldest_timestamp == dt(3)
255+
assert buffer.newest_timestamp == dt(6)
240256
assert len(buffer) == 3
241257
assert len(buffer.gaps) == 2
242258

243259
buffer.update(Sample(dt(2), Quantity(2)))
260+
assert buffer.oldest_timestamp == dt(2)
261+
assert buffer.newest_timestamp == dt(6)
244262
assert len(buffer) == 4
245263
assert len(buffer.gaps) == 1
246264

247265
buffer.update(Sample(dt(5), Quantity(5)))
266+
assert buffer.oldest_timestamp == dt(2)
267+
assert buffer.newest_timestamp == dt(6)
248268
assert len(buffer) == 5
249269
assert len(buffer.gaps) == 0
250270

251271
buffer.update(Sample(dt(99), None))
272+
assert buffer.oldest_timestamp == dt(95) # bug: should be None
273+
assert buffer.newest_timestamp == dt(99) # bug: should be None
252274
assert len(buffer) == 4 # bug: should be 0 (whole range gap)
253275
assert len(buffer.gaps) == 1
254276

0 commit comments

Comments
 (0)