# -*- 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 )