''' Time inteval module.
.. codeauthor:: Yoshifumi Futaana
It provides :class:`timeinterval` class.
'''
import copy
import datetime
import sympy
from irfpy.util.utc import date2num, num2date
[docs]class timeinterval:
''' Time interval class. Time interval and some calculation.
Time interval can be defined.
A simple interval (continuous one block) is instance as follows.
>>> t0 = datetime.datetime(2010, 1, 1, 12, 0, 0)
>>> t1 = datetime.datetime(2010, 1, 5, 12, 0, 0)
>>> tint = timeinterval(t0, t1)
>>> print(tint)
Interval(733773.500000000, 733777.500000000)
The ``print`` function print out in the matplotlib's floating point format (*date2num*).
One can check if the specific time is inside or outside of the interval as follows.
>>> t0 in tint
True
>>> t1 in tint
True
>>> datetime.datetime(2010, 1, 3) in tint
True
You can add the intervals using "plus" operator.
>>> t2 = datetime.datetime(2010, 2, 1, 12, 0, 0)
>>> t3 = datetime.datetime(2010, 2, 5, 12, 0, 0)
>>> tint2 = tint + timeinterval(t2, t3)
>>> t0 in tint2
True
>>> t1 in tint2
True
>>> t2 in tint2
True
>>> t3 in tint2
True
>>> t2 in tint
False
>>> t3 in tint
False
You can subtract the specific interval using minus operator.
>>> tint3 = tint2 - tint
>>> t0 in tint3
False
>>> t1 in tint3
False
>>> t2 in tint3
True
>>> t3 in tint3
True
The earliest/latest time in the interval can be obtained by :meth:`left_time`
and :meth:`right_time` methods.
>>> print(tint.left_time())
2010-01-01 12:00:00
>>> print(tint.right_time())
2010-01-05 12:00:00
The interval can be converted to the discrete tuple of times using :meth:`sampling` method.
>>> t_sample = tint2.sampling(datetime.timedelta(days=1))
>>> for t in t_sample: print(t)
2010-01-01 12:00:00
2010-01-02 12:00:00
2010-01-03 12:00:00
2010-01-04 12:00:00
2010-01-05 12:00:00
2010-02-01 12:00:00
2010-02-02 12:00:00
2010-02-03 12:00:00
2010-02-04 12:00:00
2010-02-05 12:00:00
*Developer information*
Delegate to the :class:`sympy:sympy.Interval`.
'''
def __init__(self, start, end, left_open=False, right_open=False):
t0 = date2num(start)
t1 = date2num(end)
self.interval = sympy.Interval(t0, t1, left_open=left_open, right_open=right_open)
def __contains__(self, t_datetime):
d = date2num(t_datetime)
return d in self.interval
def __add__(self, other):
ret = copy.copy(self)
ret.interval += other.interval
return ret
def __sub__(self, other):
ret = copy.copy(self)
ret.interval -= other.interval
return ret
def __repr__(self):
return str(self.interval)
def __str__(self):
return str(self.interval)
[docs] def left(self):
""" Return the left-most time (in float).
"""
return min(self.interval.boundary)
[docs] def right(self):
""" Return the right-most time (in float).
"""
return max(self.interval.boundary)
[docs] def left_time(self):
""" Return the left-most time
"""
return num2date(float(self.left())).replace(tzinfo=None)
[docs] def right_time(self):
""" Return the right-most time
"""
return num2date(float(self.right())).replace(tzinfo=None)
[docs] def sampling(self, dt, t0=None):
""" Return the list of the time with sampling time *dt*.
:param dt: :class:`datetime.timedelta` object that specifies the sampling time.
:keyword t0: If given in :class:`datetime.datetime` object, the start time of the sampling can be specified.
Default start time is :meth:`left_time`.
:return: Tuple of the time that in inside the interval.
>>> tint = timeinterval(datetime.datetime(2010, 3, 10, 1, 30), datetime.datetime(2010, 3, 10, 1, 40))
>>> tint = tint - timeinterval(datetime.datetime(2010, 3, 10, 1, 31, 30), datetime.datetime(2010, 3, 10, 1, 37, 30))
>>> tint = tint - timeinterval(datetime.datetime(2010, 3, 10, 1, 38, 30), datetime.datetime(2010, 3, 10, 1, 39, 30))
>>> print(tint)
Union(Interval.Ropen(733841.062500000, 733841.063541667), Interval.open(733841.067708333, 733841.068402778), Interval.Lopen(733841.069097222, 733841.069444444))
>>> print(tint.sampling(datetime.timedelta(minutes=1)))
(datetime.datetime(2010, 3, 10, 1, 30), datetime.datetime(2010, 3, 10, 1, 31), datetime.datetime(2010, 3, 10, 1, 38), datetime.datetime(2010, 3, 10, 1, 40))
"""
if t0 is None:
t0 = self.left_time()
t1 = self.right_time()
from irfpy.util import utc
tlist = utc.dtrange(t0, t1 + dt, dt)
t_true = tuple([t for t in tlist if t in self])
return t_true
[docs]def empty_interval():
''' Return :class:`timeinterval` object with empty interval.
>>> empty = empty_interval()
>>> print(empty)
EmptySet
>>> intvl0 = timeinterval(datetime.datetime(1975, 10, 10), datetime.datetime(1998, 1, 10))
>>> intvl1 = empty + intvl0
>>> print(intvl0)
Interval(721271.000000000, 729399.000000000)
>>> print(intvl1)
Interval(721271.000000000, 729399.000000000)
'''
# Quick-durty way. t0 > t1, then returning empty for sympy.Interval.
return timeinterval(datetime.datetime(2000, 1, 1), datetime.datetime(1999, 1, 1))