123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- """tzinfo implementations for psycopg2
- This module holds two different tzinfo implementations that can be used as
- the 'tzinfo' argument to datetime constructors, directly passed to psycopg
- functions or used to set the .tzinfo_factory attribute in cursors.
- """
- # psycopg/tz.py - tzinfo implementation
- #
- # Copyright (C) 2003-2019 Federico Di Gregorio <fog@debian.org>
- # Copyright (C) 2020-2021 The Psycopg Team
- #
- # psycopg2 is free software: you can redistribute it and/or modify it
- # under the terms of the GNU Lesser General Public License as published
- # by the Free Software Foundation, either version 3 of the License, or
- # (at your option) any later version.
- #
- # In addition, as a special exception, the copyright holders give
- # permission to link this program with the OpenSSL library (or with
- # modified versions of OpenSSL that use the same license as OpenSSL),
- # and distribute linked combinations including the two.
- #
- # You must obey the GNU Lesser General Public License in all respects for
- # all of the code used other than OpenSSL.
- #
- # psycopg2 is distributed in the hope that it will be useful, but WITHOUT
- # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
- # License for more details.
- import datetime
- import time
- ZERO = datetime.timedelta(0)
- class FixedOffsetTimezone(datetime.tzinfo):
- """Fixed offset in minutes east from UTC.
- This is exactly the implementation__ found in Python 2.3.x documentation,
- with a small change to the `!__init__()` method to allow for pickling
- and a default name in the form ``sHH:MM`` (``s`` is the sign.).
- The implementation also caches instances. During creation, if a
- FixedOffsetTimezone instance has previously been created with the same
- offset and name that instance will be returned. This saves memory and
- improves comparability.
- .. versionchanged:: 2.9
- The constructor can take either a timedelta or a number of minutes of
- offset. Previously only minutes were supported.
- .. __: https://docs.python.org/library/datetime.html
- """
- _name = None
- _offset = ZERO
- _cache = {}
- def __init__(self, offset=None, name=None):
- if offset is not None:
- if not isinstance(offset, datetime.timedelta):
- offset = datetime.timedelta(minutes=offset)
- self._offset = offset
- if name is not None:
- self._name = name
- def __new__(cls, offset=None, name=None):
- """Return a suitable instance created earlier if it exists
- """
- key = (offset, name)
- try:
- return cls._cache[key]
- except KeyError:
- tz = super().__new__(cls, offset, name)
- cls._cache[key] = tz
- return tz
- def __repr__(self):
- return "psycopg2.tz.FixedOffsetTimezone(offset=%r, name=%r)" \
- % (self._offset, self._name)
- def __eq__(self, other):
- if isinstance(other, FixedOffsetTimezone):
- return self._offset == other._offset
- else:
- return NotImplemented
- def __ne__(self, other):
- if isinstance(other, FixedOffsetTimezone):
- return self._offset != other._offset
- else:
- return NotImplemented
- def __getinitargs__(self):
- return self._offset, self._name
- def utcoffset(self, dt):
- return self._offset
- def tzname(self, dt):
- if self._name is not None:
- return self._name
- minutes, seconds = divmod(self._offset.total_seconds(), 60)
- hours, minutes = divmod(minutes, 60)
- rv = "%+03d" % hours
- if minutes or seconds:
- rv += ":%02d" % minutes
- if seconds:
- rv += ":%02d" % seconds
- return rv
- def dst(self, dt):
- return ZERO
- STDOFFSET = datetime.timedelta(seconds=-time.timezone)
- if time.daylight:
- DSTOFFSET = datetime.timedelta(seconds=-time.altzone)
- else:
- DSTOFFSET = STDOFFSET
- DSTDIFF = DSTOFFSET - STDOFFSET
- class LocalTimezone(datetime.tzinfo):
- """Platform idea of local timezone.
- This is the exact implementation from the Python 2.3 documentation.
- """
- def utcoffset(self, dt):
- if self._isdst(dt):
- return DSTOFFSET
- else:
- return STDOFFSET
- def dst(self, dt):
- if self._isdst(dt):
- return DSTDIFF
- else:
- return ZERO
- def tzname(self, dt):
- return time.tzname[self._isdst(dt)]
- def _isdst(self, dt):
- tt = (dt.year, dt.month, dt.day,
- dt.hour, dt.minute, dt.second,
- dt.weekday(), 0, -1)
- stamp = time.mktime(tt)
- tt = time.localtime(stamp)
- return tt.tm_isdst > 0
- LOCAL = LocalTimezone()
- # TODO: pre-generate some interesting time zones?
|