Skip to content

Commit 80ce12a

Browse files
author
Benjamin Moody
committed
BaseRecord: always define the base_datetime attribute.
Previously, if a record contained both a base date and base time, then rdrecord would set the undocumented 'base_datetime' attribute accordingly. This attribute is useful to have in general, so define it for all BaseRecords, Records, and MultiRecords. It is defined as a property that aliases the base_date and base_time attributes. That is to say, if the package or application sets record.base_date and record.base_time, then record.base_datetime is calculated automatically; if the package or application sets record.base_datetime, then record.base_date and record.base_time are calculated automatically. Internally, we continue to store the time and date attributes separately, to accommodate records where the base time is defined but the base date is not. Note that when storing a value in record.base_datetime, it must be a naive datetime object. Records don't have a time zone, and therefore trying to set the base time to an aware datetime object is incorrect.
1 parent 5775654 commit 80ce12a

File tree

1 file changed

+29
-0
lines changed

1 file changed

+29
-0
lines changed

wfdb/io/record.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,9 @@ class BaseRecord(object):
187187
The time of day at the beginning of the record.
188188
base_date : datetime.date, optional
189189
The date at the beginning of the record.
190+
base_datetime : datetime.datetime, optional
191+
The date and time at the beginning of the record, equivalent to
192+
`datetime.combine(base_date, base_time)`.
190193
comments : list, optional
191194
A list of string comments to be written to the header file.
192195
sig_name : str, optional
@@ -219,6 +222,26 @@ def __init__(
219222
self.comments = comments
220223
self.sig_name = sig_name
221224

225+
@property
226+
def base_datetime(self):
227+
if self.base_date is None or self.base_time is None:
228+
return None
229+
else:
230+
return datetime.datetime.combine(
231+
date=self.base_date, time=self.base_time
232+
)
233+
234+
@base_datetime.setter
235+
def base_datetime(self, value):
236+
if value is None:
237+
self.base_date = None
238+
self.base_time = None
239+
elif isinstance(value, datetime.datetime) and value.tzinfo is None:
240+
self.base_date = value.date()
241+
self.base_time = value.time()
242+
else:
243+
raise TypeError(f"invalid base_datetime value: {value!r}")
244+
222245
def check_field(self, field, required_channels="all"):
223246
"""
224247
Check whether a single field is valid in its basic form. Does
@@ -605,6 +628,9 @@ class Record(BaseRecord, _header.HeaderMixin, _signal.SignalMixin):
605628
The time of day at the beginning of the record.
606629
base_date : datetime.date, optional
607630
The date at the beginning of the record.
631+
base_datetime : datetime.datetime, optional
632+
The date and time at the beginning of the record, equivalent to
633+
`datetime.combine(base_date, base_time)`.
608634
file_name : str, optional
609635
The name of the file used for analysis.
610636
fmt : list, optional
@@ -905,6 +931,9 @@ class MultiRecord(BaseRecord, _header.MultiHeaderMixin):
905931
The time of day at the beginning of the record.
906932
base_date : datetime.date, optional
907933
The date at the beginning of the record.
934+
base_datetime : datetime.datetime, optional
935+
The date and time at the beginning of the record, equivalent to
936+
`datetime.combine(base_date, base_time)`.
908937
seg_name : str, optional
909938
The name of the segment.
910939
seg_len : int, optional

0 commit comments

Comments
 (0)