123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122 |
- # -*- coding: utf-8 -*-
- #!/usr/bin/env python
- """
- A set of utils for datetime/date/ objects
- Majorly borrowed from maya.
- We don't need to import maya for this since we don't need to parse timezones and other non-trivial datetime operations for now.
- """
- import datetime
- from .utils import validate_arguments_type_of_function
- def _seconds_or_timedelta(duration):
- """Returns `datetime.timedelta` object for the passed duration.
- Keyword Arguments:
- duration -- `datetime.timedelta` object or seconds in `int` format.
- """
- if isinstance(duration, int):
- dt_timedelta = datetime.timedelta(seconds=duration)
- elif isinstance(duration, datetime.timedelta):
- dt_timedelta = duration
- else:
- raise TypeError(
- 'Expects argument as `datetime.timedelta` object '
- 'or seconds in `int` format'
- )
- return dt_timedelta
- def intervals(start, end, interval):
- """
- Yields MayaDT objects between the start and end MayaDTs given,
- at a given interval (seconds or timedelta).
- """
- interval = _seconds_or_timedelta(interval)
- current_timestamp = start
- while current_timestamp.epoch < end.epoch:
- yield current_timestamp
- current_timestamp = current_timestamp.add(seconds=interval.seconds)
- class Interval(object):
- def __init__(self, start=None, end=None, duration=None):
- try:
- # Ensure that proper arguments were passed.
- assert any(
- (
- (start and end),
- (start and duration is not None),
- (end and duration is not None),
- )
- )
- assert not all((start, end, duration is not None))
- except AssertionError:
- raise ValueError(
- 'Exactly 2 of start, end, and duration must be specified'
- )
- # Convert duration to timedelta if seconds were provided.
- if duration:
- duration = _seconds_or_timedelta(duration)
- if not start:
- start = end - duration
- if not end:
- end = start + duration
- if start > end:
- raise ValueError('MayaInterval cannot end before it starts')
- self.start = start
- self.end = end
- @property
- def duration(self):
- return self.timedelta.total_seconds()
- @property
- def timedelta(self):
- return datetime.timedelta(seconds=(self.end.epoch - self.start.epoch))
- @property
- def is_instant(self):
- return self.timedelta == datetime.timedelta(seconds=0)
- @validate_arguments_type_of_function()
- def __cmp__(self, maya_interval):
- return (
- cmp(self.start, maya_interval.start)
- or cmp(self.end, maya_interval.end)
- )
- @validate_arguments_type_of_function()
- def intersection(self, maya_interval):
- """Returns the intersection between two intervals."""
- start = max(self.start, maya_interval.start)
- end = min(self.end, maya_interval.end)
- either_instant = self.is_instant or maya_interval.is_instant
- instant_overlap = (self.start == maya_interval.start or start <= end)
- if (either_instant and instant_overlap) or (start < end):
- return Interval(start, end)
- @validate_arguments_type_of_function()
- def contains(self, maya_interval):
- return (
- self.start <= maya_interval.start and self.end >= maya_interval.end
- )
- def __contains__(self, maya_dt):
- if isinstance(maya_dt, datetime.datetime):
- return self.contains_dt(maya_dt)
- return self.contains(maya_dt)
- def contains_dt(self, dt):
- return self.start <= dt < self.end
- @validate_arguments_type_of_function()
- def is_adjacent(self, maya_interval):
- return (
- self.start == maya_interval.end or self.end == maya_interval.start
- )
|