src.util.datelabel module¶
Classes for serializing and deserializing dates and times expressed as strings in filenames and paths.
Intended use case is, e.g., determining if a file contains data for a given year based on the filename alone, without having to open it and parse the header.
Warning
Classes are implemented on top of the Python standard library
datetime
package, and as such always assume a proleptic Gregorian
calendar. This is adequate for the intended filename-parsing use case.
Timezone support is not currently implemented, for the same reason.
Warning
These classes should not be used for detailed calendar math. We currently implement and test comparison logic only, not anything more (e.g. addition, subtraction, although increment/decrement are supported).
Properties and use of DateRange
, Date
and DateFrequency
objects are best illustrated by examples:
>>> Date('20001215').month
12
>>> Date('200012') == datetime(2000, 12, 1)
True
>>> DateRange('2010-2020') in DateRange('2008-2019')
False
>>> DateRange('2010-2020').overlaps(DateRange('2008-2019'))
True
>>> DateFrequency('daily') < DateFrequency('24hr')
True
- class src.util.datelabel.AtomicInterval(left, lower, upper, right)[source]¶
Bases:
object
This class represents an atomic interval. An atomic interval is a single interval, with a lower and upper bound, and two (closed or open) boundaries.
- CLOSED = True¶
- OPEN = False¶
- __init__(left, lower, upper, right)[source]¶
Create an atomic interval. If a bound is set to infinity (regardless of its sign), the corresponding boundary will be exclusive.
- Parameters:
left – Boolean indicating if left boundary is inclusive (True) or exclusive (False).
lower – value of the lower bound.
upper – value of the upper bound.
right – Boolean indicating if right boundary is inclusive (True) or exclusive (False).
- property left¶
Boolean indicating whether the left boundary is inclusive (True) or exclusive (False).
- property lower¶
Lower bound value.
- property upper¶
Upper bound value.
- property right¶
Boolean indicating whether the right boundary is inclusive (True) or exclusive (False).
- replace(left=None, lower=None, upper=None, right=None, ignore_inf=True)[source]¶
Create a new interval based on the current one and the provided values. Callable can be passed instead of values. In that case, it is called with the current corresponding value except if ignore_inf if set (default) and the corresponding bound is an infinity.
- Parameters:
left – (a function of) left boundary.
lower – (a function of) value of the lower bound.
upper – (a function of) value of the upper bound.
right – (a function of) right boundary.
ignore_inf – ignore infinities if functions are provided (default is True).
- Returns:
An Interval instance.
- overlaps(other, adjacent=False)[source]¶
Test if intervals have any overlapping value. If ‘adjacent’ is set to True (default is False), then it returns True for adjacent intervals as well (e.g., [1, 2) and [2, 3], but not [1, 2) and (2, 3]).
- Parameters:
other – an atomic interval.
adjacent – set to True to accept adjacent intervals as well.
- Returns:
True if intervals overlap, False otherwise.
- intersection(other)[source]¶
Return the intersection of two intervals.
- Parameters:
other – an interval.
- Returns:
The intersection of the intervals.
- union(other)[source]¶
Return the union of two intervals. If the union cannot be represented using a single atomic interval, return an Interval instance (which corresponds to an union of atomic intervals).
- Parameters:
other – an interval.
- Returns:
The union of the intervals.
- contains(item)[source]¶
Test if given item is contained in this interval. This method accepts atomic intervals, intervals and arbitrary values.
- Parameters:
item – an atomic interval, an interval or any arbitrary value.
- Returns:
True if given item is contained, False otherwise.
- classmethod span(*args)[source]¶
Return an AtomicInterval covering the collection of intervals in args.
- classmethod contiguous_span(*args)[source]¶
Return an AtomicInterval covering the collection of intervals in args if those intervals are contiguous and nonoverlapping.
- Raises:
ValueError – If collection of intervals is not contiguous and nonoverlapping.
- class src.util.datelabel.DatePrecision(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)[source]¶
Bases:
IntEnum
IntEnum
to encode the recognized levels of precision forDate
s andDateRange
s. Example:>>> Date('200012').precision == DatePrecision.MONTH True
because the date in the example, “December 2000,” is only defined up to a month, and hence is represented by the interval from 1 Dec 2000 to 31 Dec 2000.
- STATIC = -1¶
- YEAR = 1¶
- MONTH = 2¶
- DAY = 3¶
- HOUR = 4¶
- MINUTE = 5¶
- SECOND = 6¶
- as_integer_ratio()¶
Return integer ratio.
Return a pair of integers, whose ratio is exactly equal to the original int and with a positive denominator.
>>> (10).as_integer_ratio() (10, 1) >>> (-10).as_integer_ratio() (-10, 1) >>> (0).as_integer_ratio() (0, 1)
- bit_count()¶
Number of ones in the binary representation of the absolute value of self.
Also known as the population count.
>>> bin(13) '0b1101' >>> (13).bit_count() 3
- bit_length()¶
Number of bits necessary to represent self in binary.
>>> bin(37) '0b100101' >>> (37).bit_length() 6
- conjugate()¶
Returns self, the complex conjugate of any int.
- denominator¶
the denominator of a rational number in lowest terms
- from_bytes(byteorder='big', *, signed=False)¶
Return the integer represented by the given array of bytes.
- bytes
Holds the array of bytes to convert. The argument must either support the buffer protocol or be an iterable object producing bytes. Bytes and bytearray are examples of built-in objects that support the buffer protocol.
- byteorder
The byte order used to represent the integer. If byteorder is ‘big’, the most significant byte is at the beginning of the byte array. If byteorder is ‘little’, the most significant byte is at the end of the byte array. To request the native byte order of the host system, use `sys.byteorder’ as the byte order value. Default is to use ‘big’.
- signed
Indicates whether two’s complement is used to represent the integer.
- imag¶
the imaginary part of a complex number
- numerator¶
the numerator of a rational number in lowest terms
- real¶
the real part of a complex number
- to_bytes(length=1, byteorder='big', *, signed=False)¶
Return an array of bytes representing an integer.
- length
Length of bytes object to use. An OverflowError is raised if the integer is not representable with the given number of bytes. Default is length 1.
- byteorder
The byte order used to represent the integer. If byteorder is ‘big’, the most significant byte is at the beginning of the byte array. If byteorder is ‘little’, the most significant byte is at the end of the byte array. To request the native byte order of the host system, use `sys.byteorder’ as the byte order value. Default is to use ‘big’.
- signed
Determines whether two’s complement is used to represent the integer. If signed is False and a negative integer is given, an OverflowError is raised.
- class src.util.datelabel.DateMixin[source]¶
Bases:
object
Utility methods for dealing with dates.
- static date_format(dt, precision=None)[source]¶
Print date dt in YYYYMMDDHHMMSS format, with length being set automatically from precision.
Note
strftime() is broken for dates prior to 1900 in python < 3.3, see https://bugs.python.org/issue1777412 and https://stackoverflow.com/q/10263956. For this reason, the workaround implemented here should be used instead.
- class src.util.datelabel.DateRange(start, end=None, precision=None, log=<Logger>)[source]¶
Bases:
AtomicInterval
,DateMixin
Class representing a range of dates specified with variable precision.
Endpoints of the interval are represented internally as
datetime
objects.Note
In keeping with convention, this is always defined as a closed interval (containing both endpoints). E.g., DateRange(‘1990-1999’) starts at 0:00 on 1 Jan 1990 and ends at 23:59 on 31 Dec 1999, inclusive.
- Attributes:
precision (
DatePrecision
) – Precision to which both endpoints of the DateRange are known. E.g., DateRange(‘1990-1999’) has a precision of DatePrecision.YEAR.
- property is_static¶
Property indicating time-independent data (e.g.,
fx
in the CMIP6 DRS.)
- classmethod from_contiguous_span(*args)[source]¶
Given multiple DateRanges, return interval containing them only if their time intervals are continguous and nonoverlapping.
- classmethod from_date_span(*args)[source]¶
Return a DateRange coresponding to the interval containing a set of
Date
s. Differs fromfrom_contiguous_span()
in that we don’t expect intervals to be contiguous.
- format(precision=None)[source]¶
Return string representation of this DateRange, of the form YYYYMMDD…-YYYYMMDD…. The length of the YYYYMMDD… representation is determined by the precision attribute if not manually given.
- contains(item)¶
Override
AtomicInterval.__contains__()
to handle differences in datelabel precision. Finite precision means that the interval endpoints are ranges, not points (which is whyDate
inherits fromDateRange
and not vice-versa). We replace strict equality of endpoints (==) with appropriate conditions on the overlap of these ranges.
- overlaps(item)[source]¶
Test if intervals have any overlapping value. If ‘adjacent’ is set to True (default is False), then it returns True for adjacent intervals as well (e.g., [1, 2) and [2, 3], but not [1, 2) and (2, 3]).
- Parameters:
other – an atomic interval.
adjacent – set to True to accept adjacent intervals as well.
- Returns:
True if intervals overlap, False otherwise.
- intersection(item, precision=None)[source]¶
Return the intersection of two intervals.
- Parameters:
other – an interval.
- Returns:
The intersection of the intervals.
- CLOSED = True¶
- OPEN = False¶
- adjoins(other)¶
Returns True if there is no gap or overlap between self and other.
- adjoins_left(other)¶
Returns True if other follows self with no gap or overlap.
- adjoins_right(other)¶
Returns True if self follows other with no gap or overlap.
- classmethod contiguous_span(*args)¶
Return an AtomicInterval covering the collection of intervals in args if those intervals are contiguous and nonoverlapping.
- Raises:
ValueError – If collection of intervals is not contiguous and nonoverlapping.
- static date_format(dt, precision=None)¶
Print date dt in YYYYMMDDHHMMSS format, with length being set automatically from precision.
Note
strftime() is broken for dates prior to 1900 in python < 3.3, see https://bugs.python.org/issue1777412 and https://stackoverflow.com/q/10263956. For this reason, the workaround implemented here should be used instead.
- classmethod decrement(dt, precision)¶
Return a copy of dt moved back by one time unit as specified by the precision attribute.
- classmethod increment(dt, precision)¶
Return a copy of dt advanced by one time unit as specified by the precision attribute.
- is_empty()¶
Test interval emptiness.
- Returns:
True if interval is empty, False otherwise.
- property left¶
Boolean indicating whether the left boundary is inclusive (True) or exclusive (False).
- property lower¶
Lower bound value.
- replace(left=None, lower=None, upper=None, right=None, ignore_inf=True)¶
Create a new interval based on the current one and the provided values. Callable can be passed instead of values. In that case, it is called with the current corresponding value except if ignore_inf if set (default) and the corresponding bound is an infinity.
- Parameters:
left – (a function of) left boundary.
lower – (a function of) value of the lower bound.
upper – (a function of) value of the upper bound.
right – (a function of) right boundary.
ignore_inf – ignore infinities if functions are provided (default is True).
- Returns:
An Interval instance.
- property right¶
Boolean indicating whether the right boundary is inclusive (True) or exclusive (False).
- classmethod span(*args)¶
Return an AtomicInterval covering the collection of intervals in args.
- union(other)¶
Return the union of two intervals. If the union cannot be represented using a single atomic interval, return an Interval instance (which corresponds to an union of atomic intervals).
- Parameters:
other – an interval.
- Returns:
The union of the intervals.
- property upper¶
Upper bound value.
- class src.util.datelabel.Date(*args, **kwargs)[source]¶
Bases:
DateRange
Defines a single date with variable level precision.
The date is represented as an interval, with precision setting the length of the interval (which is why this inherits from
DateRange
and not vice versa.)Date objects are mapped to
datetime
s representing the start of the interval implied by their precision, e.g. Date(‘2000-05’) maps to 0:00 on 1 May 2000.- Attributes:
year, month, day, hour, minute, second – Components of the
datetime
representing the start of the interval defined by Date. We do not check that the attribute access is appropriate to the Date’s precision.precision (
DatePrecision
) – Precision to which both endpoints of the DateRange are known. E.g., Date(1990) has a precision of DatePrecision.YEAR.
- format(precision=None)[source]¶
Return YYYYMMDD… string representation of this Date. The length of the representation is determined by the precision attribute if not manually given.
- isoformat()[source]¶
Return string representation of the start datetime of this Date interval in
YYYY-MM-DD HH:MM:SS
format.
- CLOSED = True¶
- OPEN = False¶
- adjoins(other)¶
Returns True if there is no gap or overlap between self and other.
- adjoins_left(other)¶
Returns True if other follows self with no gap or overlap.
- adjoins_right(other)¶
Returns True if self follows other with no gap or overlap.
- contains(item)¶
Override
AtomicInterval.__contains__()
to handle differences in datelabel precision. Finite precision means that the interval endpoints are ranges, not points (which is whyDate
inherits fromDateRange
and not vice-versa). We replace strict equality of endpoints (==) with appropriate conditions on the overlap of these ranges.
- classmethod contiguous_span(*args)¶
Return an AtomicInterval covering the collection of intervals in args if those intervals are contiguous and nonoverlapping.
- Raises:
ValueError – If collection of intervals is not contiguous and nonoverlapping.
- static date_format(dt, precision=None)¶
Print date dt in YYYYMMDDHHMMSS format, with length being set automatically from precision.
Note
strftime() is broken for dates prior to 1900 in python < 3.3, see https://bugs.python.org/issue1777412 and https://stackoverflow.com/q/10263956. For this reason, the workaround implemented here should be used instead.
- classmethod decrement(dt, precision)¶
Return a copy of dt moved back by one time unit as specified by the precision attribute.
- classmethod from_contiguous_span(*args)¶
Given multiple DateRanges, return interval containing them only if their time intervals are continguous and nonoverlapping.
- classmethod from_date_span(*args)¶
Return a DateRange coresponding to the interval containing a set of
Date
s. Differs fromfrom_contiguous_span()
in that we don’t expect intervals to be contiguous.
- classmethod increment(dt, precision)¶
Return a copy of dt advanced by one time unit as specified by the precision attribute.
- intersection(item, precision=None)¶
Return the intersection of two intervals.
- Parameters:
other – an interval.
- Returns:
The intersection of the intervals.
- is_empty()¶
Test interval emptiness.
- Returns:
True if interval is empty, False otherwise.
- property is_static¶
Property indicating time-independent data (e.g.,
fx
in the CMIP6 DRS.)
- property left¶
Boolean indicating whether the left boundary is inclusive (True) or exclusive (False).
- property lower¶
Lower bound value.
- overlaps(item)¶
Test if intervals have any overlapping value. If ‘adjacent’ is set to True (default is False), then it returns True for adjacent intervals as well (e.g., [1, 2) and [2, 3], but not [1, 2) and (2, 3]).
- Parameters:
other – an atomic interval.
adjacent – set to True to accept adjacent intervals as well.
- Returns:
True if intervals overlap, False otherwise.
- replace(left=None, lower=None, upper=None, right=None, ignore_inf=True)¶
Create a new interval based on the current one and the provided values. Callable can be passed instead of values. In that case, it is called with the current corresponding value except if ignore_inf if set (default) and the corresponding bound is an infinity.
- Parameters:
left – (a function of) left boundary.
lower – (a function of) value of the lower bound.
upper – (a function of) value of the upper bound.
right – (a function of) right boundary.
ignore_inf – ignore infinities if functions are provided (default is True).
- Returns:
An Interval instance.
- property right¶
Boolean indicating whether the right boundary is inclusive (True) or exclusive (False).
- classmethod span(*args)¶
Return an AtomicInterval covering the collection of intervals in args.
- union(other)¶
Return the union of two intervals. If the union cannot be represented using a single atomic interval, return an Interval instance (which corresponds to an union of atomic intervals).
- Parameters:
other – an interval.
- Returns:
The union of the intervals.
- property upper¶
Upper bound value.
- src.util.datelabel.FXDateRange = _FXDateRange()¶
Singleton placeholder/sentinel object for use in describing static data with no time dependence.
- class src.util.datelabel.DateFrequency(quantity, unit=None)[source]¶
Bases:
timedelta
Class representing a frequency or time period.
Warning
Period lengths are not defined accurately, eg. a year is taken as 365 days and a month is taken as 30 days. For this reason, we do not implement addition and subtraction of DateFrequency objects to Dates, as is possible for
timedelta
anddatetime
.- property is_static¶
Property indicating time-independent data (e.g.,
fx
in CMIP6 DRS.)
- classmethod from_struct(str_)[source]¶
Object instantiation method used by
src.util.dataclass.mdtf_dataclass()
for type coercion.
- format_local()[source]¶
String representation as used in framework’s local directory hierarchy (defined in
src.data_manager.DataManager.dest_path()
.)
- max = datetime.timedelta(days=999999999, seconds=86399, microseconds=999999)¶
- min = datetime.timedelta(days=-999999999)¶
- resolution = datetime.timedelta(microseconds=1)¶
- src.util.datelabel.FXDateFrequency = _FXDateFrequency('fx')¶
Singleton placeholder/sentinel object for use in describing static data with no time dependence.
- class src.util.datelabel.AbstractDateRange[source]¶
Bases:
ABC
Defines interface (set of attributes) for
DateRange
objects.
- class src.util.datelabel.AbstractDate[source]¶
Bases:
ABC
Defines interface (set of attributes) for
Date
objects.
- class src.util.datelabel.AbstractDateFrequency[source]¶
Bases:
ABC
Defines interface (set of attributes) for
DateFrequency
objects.