Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
lib-py-b2b / datetime.py
Size: Mime:
from datetime import datetime, time, date, timezone
import logging
from dateutil.tz import gettz, UTC, tzoffset

logger = logging.getLogger(__name__)


class Time:
    @staticmethod
    def for_(dt: datetime):
        return Time(hour=dt.hour, minute=dt.minute, second=dt.second, tz=dt.tzname())

    def __init__(self, hour: int = 0, minute: int = 0, second: int = 0, tz: str = 'UTC'):
        self.tz = tz
        self.second = second
        self.minute = minute
        self.hour = hour

    def time(self):
        return self.datetime().timetz()

    def datetime(self, dt: date = None):
        _t = time(hour=self.hour, minute=self.minute, second=self.second)
        _tz = gettz(self.tz)
        _d = dt or date.today()
        _dt = datetime.combine(_d, _t).replace(tzinfo=_tz)
        return _dt

    def as_utc(self):
        return self.datetime().astimezone(UTC).timetz()

    def as_timezone(self, tz: str):
        _dt = self.datetime()
        _tz = gettz(tz)
        _dt = _dt.astimezone(_tz)
        return _dt.timetz()

    def isoformat(self):
        return self.time().isoformat()

    def __eq__(self, other):
        if isinstance(other, Time):
            o: Time = other
            return self.as_utc() == o.as_utc()
        else:
            return super().__eq__(other)

    def __ne__(self, other):
        if isinstance(other, Time):
            o: Time = other
            return self.as_utc() != o.as_utc()
        else:
            return super().__ne__(other)

    def __gt__(self, other):
        if isinstance(other, Time):
            o: Time = other
            return self.as_utc() > o.as_utc()
        else:
            return super().__gt__(other)

    def __ge__(self, other):
        if isinstance(other, Time):
            o: Time = other
            return self.as_utc() >= o.as_utc()
        else:
            return super().__ge__(other)

    def __lt__(self, other):
        if isinstance(other, Time):
            o: Time = other
            return self.as_utc() < o.as_utc()
        else:
            return super().__lt__(other)

    def __le__(self, other):
        if isinstance(other, Time):
            o: Time = other
            return self.as_utc() <= o.as_utc()
        else:
            return super().__le__(other)


class TimePeriod:
    def __init__(self, start: Time, end: Time):
        self.start = start
        self.end = end

    def __contains__(self, item: (Time, datetime)):
        if isinstance(item, datetime):
            item = Time.for_(item)
        _it = item.as_utc()
        _start = self.start.datetime()
        _end = self.end.datetime()
        if _end.utcoffset() != _start.utcoffset():
            _start = _start.replace(tzinfo=tzoffset(None, _end.utcoffset().seconds))
        _start = _start.astimezone(UTC).timetz()
        _end = _end.astimezone(UTC).timetz()
        if _end >= _start:
            return _start <= _it <= _end
        else:
            return _start <= _it or _it <= _end

    def __str__(self):
        return f"TimeRange: ({self.start.isoformat()}{self.end.isoformat()})"

    def describe(self, tz: str = None):
        if tz:
            _start = self.start.as_timezone(tz)
            _end = self.end.as_timezone(tz)
            return f"TimeRange: ({_start.isoformat()}{_end.isoformat()})"
        else:
            return str(self)


class DateTime(datetime):
    def __new__(cls, *args, **kwargs):
        if 'tzinfo' not in kwargs:
            kwargs['tzinfo'] = timezone.utc
        return super().__new__(cls, *args, **kwargs)


class NaiveDateTime(datetime):
    def __new__(cls, *args, **kwargs):
        if 'tzinfo' in kwargs:
            kwargs['tzinfo'] = None
            logger.warning('tzinfo passed into Naive Datetime (NDT) object, setting to None')
        return super().__new__(cls, *args, **kwargs)