<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">from __future__ import division

from datetime import timedelta, tzinfo
from copy import deepcopy


class FixedOffset(tzinfo):
    '''
    Represent a timezone with a fixed offset from UTC and no adjustment for
    DST.

    &gt;&gt;&gt; FixedOffset(4,0)
    &lt;UTC+04:00&gt;
    &gt;&gt;&gt; FixedOffset(-4,0)
    &lt;UTC-04:00&gt;
    &gt;&gt;&gt; FixedOffset(4,30)
    &lt;UTC+04:30&gt;

    &gt;&gt;&gt; tz = FixedOffset(-5,0)
    &gt;&gt;&gt; tz.dst(None)
    datetime.timedelta(0)

    The class tries to do the right thing with the sign
    of the time zone offset:

    &gt;&gt;&gt; FixedOffset(-9,30)
    &lt;UTC-09:30&gt;
    &gt;&gt;&gt; FixedOffset(-9,-30)
    Traceback (most recent call last):
    ...
    ValueError: minutes must not be negative

    Offsets must thus be normalized so that the minute value is positive:

    &gt;&gt;&gt; FixedOffset(-8,30)
    &lt;UTC-08:30&gt;

    '''

    def __init__(self, hours, minutes):
        '''
        Create a new FixedOffset instance with the given offset.

        '''
        tzinfo.__init__(self)
        if minutes &lt; 0:
            raise ValueError("minutes must not be negative")
        if hours &lt; 0:
            minutes *= -1
        self.__offset = timedelta(hours=hours,
                                  minutes=minutes)
        self.__name = "UTC" + timezone(timedelta_seconds(self.__offset))

    def dst(self, dt):
        '''
        Return offset for DST.  Always returns timedelta(0).

        '''
        return timedelta(0)

    def utcoffset(self, dt):
        '''
        Return offset from UTC.

        '''
        return self.__offset

    def tzname(self, dt):
        '''
        Return name of timezone.

        '''
        return self.__name

    def __repr__(self):
        return "&lt;{0}&gt;".format(self.tzname(None))

    def __deepcopy__(self, memo):
        cls = self.__class__
        result = cls.__new__(cls)
        memo[id(self)] = result
        for k, v in self.__dict__.items():
            setattr(result, k, deepcopy(v, memo))
        return result


def timedelta_seconds(td):
    '''
    Return the offset stored by a :class:`datetime.timedelta` object as an
    integer number of seconds.  Microseconds, if present, are rounded to
    the nearest second.

    Delegates to
    :meth:`timedelta.total_seconds() &lt;datetime.timedelta.total_seconds()&gt;`
    if available.

    &gt;&gt;&gt; timedelta_seconds(timedelta(hours=1))
    3600
    &gt;&gt;&gt; timedelta_seconds(timedelta(hours=-1))
    -3600
    &gt;&gt;&gt; timedelta_seconds(timedelta(hours=1, minutes=30))
    5400
    &gt;&gt;&gt; timedelta_seconds(timedelta(hours=1, minutes=30,
    ... microseconds=300000))
    5400
    &gt;&gt;&gt; timedelta_seconds(timedelta(hours=1, minutes=30,
    ...	microseconds=900000))
    5401

    '''

    try:
        return int(round(td.total_seconds()))
    except AttributeError:
        days = td.days
        seconds = td.seconds
        microseconds = td.microseconds

        return int(round((days * 86400) + seconds + (microseconds / 1000000)))


def timezone(utcoffset):
    '''
    Return a string representing the timezone offset.
    Remaining seconds are rounded to the nearest minute.

    &gt;&gt;&gt; timezone(3600)
    '+01:00'
    &gt;&gt;&gt; timezone(5400)
    '+01:30'
    &gt;&gt;&gt; timezone(-28800)
    '-08:00'

    '''

    hours, seconds = divmod(abs(utcoffset), 3600)
    minutes = round(float(seconds) / 60)

    if utcoffset &gt;= 0:
        sign = '+'
    else:
        sign = '-'
    return '{0}{1:02d}:{2:02d}'.format(sign, int(hours), int(minutes))
</pre></body></html>