Python datetime 模块,tzinfo() 实例源码
我们从Python开源项目中,提取了以下50个代码示例,用于说明如何使用datetime.tzinfo()。
def timezone_tag(parser, token):
"""
Enables a given time zone just for this block.
The ``timezone`` argument must be an instance of a ``tzinfo`` subclass, a
time zone name, or ``None``. If is it a time zone name, pytz is required.
If it is ``None``, the default time zone is used within the block.
Sample usage::
{% timezone "Europe/Paris" %}
It is {{ now }} in Paris.
{% endtimezone %}
"""
bits = token.split_contents()
if len(bits) != 2:
raise TemplateSyntaxError("'%s' takes one argument (timezone)" %
bits[0])
tz = parser.compile_filter(bits[1])
nodelist = parser.parse(('endtimezone',))
parser.delete_first_token()
return TimezoneNode(nodelist, tz)
def ensure_timezone(func, argname, arg):
"""Argument preprocessor that converts the input into a tzinfo object.
Usage
-----
>>> from zipline.utils.preprocess import preprocess
>>> @preprocess(tz=ensure_timezone)
... def foo(tz):
... return tz
>>> foo('utc')
<UTC>
"""
if isinstance(arg, tzinfo):
return arg
if isinstance(arg, string_types):
return timezone(arg)
raise TypeError(
"{func}() couldn't convert argument "
"{argname}={arg!r} to a timezone.".format(
func=_qualified_name(func),
argname=argname,
arg=arg,
),
)
def dst(self, dt):
if dt is None or dt.tzinfo is None:
# An exception may be sensible here, in one or both cases.
# It depends on how you want to treat them. The default
# fromutc() implementation (called by the default astimezone()
# implementation) passes a datetime with dt.tzinfo is self.
return ZERO
assert dt.tzinfo is self
# Find first Sunday in April & the last in October.
start = first_sunday_on_or_after(DSTSTART.replace(year=dt.year))
end = first_sunday_on_or_after(DSTEND.replace(year=dt.year))
# Can't compare naive to aware objects, so strip the timezone from
# dt first.
if start <= dt.replace(tzinfo=None) < end:
return HOUR
else:
return ZERO
def parse_timezone(tzstring, default_timezone=UTC):
"""Parses ISO 8601 time zone specs into tzinfo offsets
"""
if tzstring == "Z":
return default_timezone
# This isn't strictly correct, but it's common to encounter dates without
# timezones so I'll assume the default (which defaults to UTC).
# Addresses issue 4.
if tzstring is None:
return default_timezone
m = TIMEZONE_REGEX.match(tzstring)
prefix, hours, minutes = m.groups()
hours, minutes = int(hours), int(minutes)
if prefix == "-":
hours = -hours
minutes = -minutes
return FixedOffset(hours, minutes, tzstring)
def local(class_):
"""Returns the local time zone as defined by the operating system in the
registry.
>>> localTZ = TimeZoneInfo.local()
>>> now_local = datetime.datetime.now(localTZ)
>>> now_UTC = datetime.datetime.utcnow()
>>> (now_UTC - now_local) < datetime.timedelta(seconds = 5)
Traceback (most recent call last):
...
TypeError: can't subtract offset-naive and offset-aware datetimes
>>> now_UTC = now_UTC.replace(tzinfo = TimeZoneInfo('GMT Standard Time', True))
Now one can compare the results of the two offset aware values
>>> (now_UTC - now_local) < datetime.timedelta(seconds = 5)
True
"""
code, info = TimeZoneDefinition.current()
# code is 0 if daylight savings is disabled or not defined
# code is 1 or 2 if daylight savings is enabled, 2 if currently active
fix_standard_time = not code
# note that although the given information is sufficient to construct a WinTZI object, it's
# not sufficient to represent the time zone in which the current user is operating due
# to dynamic time zones.
return class_(info, fix_standard_time)
def dst(self, dt):
if dt is None or dt.tzinfo is None:
# An exception may be sensible here, in one or both cases.
# It depends on how you want to treat them. The default
# fromutc() implementation (called by the default astimezone()
# implementation) passes a datetime with dt.tzinfo is self.
return ZERO
assert dt.tzinfo is self
# Find first Sunday in April & the last in October.
start = first_sunday_on_or_after(DSTSTART.replace(year=dt.year))
end = first_sunday_on_or_after(DSTEND.replace(year=dt.year))
# Can't compare naive to aware objects, so strip the timezone from
# dt first.
if start <= dt.replace(tzinfo=None) < end:
return HOUR
else:
return ZERO
def testFoldPositiveUTCOffset(self):
# Test that we can resolve ambiguous times
tzname = self._get_tzname('Australia/Sydney')
with self._gettz_context(tzname):
SYD0 = self.gettz(tzname)
SYD1 = self.gettz(tzname)
t0_u = datetime(2012, 3, 31, 15, 30, tzinfo=tz.tzutc()) # AEST
t1_u = datetime(2012, 3, 31, 16, 30, tzinfo=tz.tzutc()) # AEDT
# Using fresh tzfiles
t0_syd0 = t0_u.astimezone(SYD0)
t1_syd1 = t1_u.astimezone(SYD1)
self.assertEqual(t0_syd0.replace(tzinfo=None),
datetime(2012, 4, 1, 2, 30))
self.assertEqual(t1_syd1.replace(tzinfo=None),
datetime(2012, 4, 1, 2, 30))
self.assertEqual(t0_syd0.utcoffset(), timedelta(hours=11))
self.assertEqual(t1_syd1.utcoffset(), timedelta(hours=10))
def testGapPositiveUTCOffset(self):
# Test that we don't have a problem around gaps.
tzname = self._get_tzname('Australia/Sydney')
with self._gettz_context(tzname):
SYD0 = self.gettz(tzname)
SYD1 = self.gettz(tzname)
t0_u = datetime(2012, 10, 6, 15, 30, tzinfo=tz.tzutc()) # AEST
t1_u = datetime(2012, 10, 6, 16, 30, tzinfo=tz.tzutc()) # AEDT
# Using fresh tzfiles
t0 = t0_u.astimezone(SYD0)
t1 = t1_u.astimezone(SYD1)
self.assertEqual(t0.replace(tzinfo=None),
datetime(2012, 10, 7, 1, 30))
self.assertEqual(t1.replace(tzinfo=None),
datetime(2012, 10, 7, 3, 30))
self.assertEqual(t0.utcoffset(), timedelta(hours=10))
self.assertEqual(t1.utcoffset(), timedelta(hours=11))
def testFoldNegativeUTCOffset(self):
# Test that we can resolve ambiguous times
tzname = self._get_tzname('America/Toronto')
with self._gettz_context(tzname):
# Calling fromutc() alters the tzfile object
TOR0 = self.gettz(tzname)
TOR1 = self.gettz(tzname)
t0_u = datetime(2011, 11, 6, 5, 30, tzinfo=tz.tzutc())
t1_u = datetime(2011, 11, 6, 6, 30, tzinfo=tz.tzutc())
# Using fresh tzfiles
t0_tor0 = t0_u.astimezone(TOR0)
t1_tor1 = t1_u.astimezone(TOR1)
self.assertEqual(t0_tor0.replace(tzinfo=None),
datetime(2011, 11, 6, 1, 30))
self.assertEqual(t1_tor1.replace(tzinfo=None),
datetime(2011, 11, 6, 1, 30))
self.assertEqual(t0_tor0.utcoffset(), timedelta(hours=-4.0))
self.assertEqual(t1_tor1.utcoffset(), timedelta(hours=-5.0))
def testGapNegativeUTCOffset(self):
# Test that we don't have a problem around gaps.
tzname = self._get_tzname('America/Toronto')
with self._gettz_context(tzname):
# Calling fromutc() alters the tzfile object
TOR0 = self.gettz(tzname)
TOR1 = self.gettz(tzname)
t0_u = datetime(2011, 3, 13, 6, 30, tzinfo=tz.tzutc())
t1_u = datetime(2011, 3, 13, 7, 30, tzinfo=tz.tzutc())
# Using fresh tzfiles
t0 = t0_u.astimezone(TOR0)
t1 = t1_u.astimezone(TOR1)
self.assertEqual(t0.replace(tzinfo=None),
datetime(2011, 3, 13, 1, 30))
self.assertEqual(t1.replace(tzinfo=None),
datetime(2011, 3, 13, 3, 30))
self.assertNotEqual(t0, t1)
self.assertEqual(t0.utcoffset(), timedelta(hours=-5.0))
self.assertEqual(t1.utcoffset(), timedelta(hours=-4.0))
def get_utc_transitions(self, tzi, year, gap):
dston, dstoff = tzi.transitions(year)
if gap:
t_n = dston - timedelta(minutes=30)
t0_u = t_n.replace(tzinfo=tzi).astimezone(tz.tzutc())
t1_u = t0_u + timedelta(hours=1)
else:
# Get 1 hour before the first ambiguous date
t_n = dstoff - timedelta(minutes=30)
t0_u = t_n.replace(tzinfo=tzi).astimezone(tz.tzutc())
t_n += timedelta(hours=1) # Naive ambiguous date
t0_u = t0_u + timedelta(hours=1) # First ambiguous date
t1_u = t0_u + timedelta(hours=1) # Second ambiguous date
return t_n, t0_u, t1_u
def testGapPositiveUTCOffset(self):
# Test that we don't have a problem around gaps.
tzname = 'AUS Eastern Standard Time'
args = self.get_args(tzname)
with self.context(tzname):
# Calling fromutc() alters the tzfile object
SYD = self.tzclass(*args)
SYD0 = self.tzclass(*args)
SYD1 = self.tzclass(*args)
self.assertIsNot(SYD0, SYD1)
t_n, t0_u, t1_u = self.get_utc_transitions(SYD, 2012, True)
# Using fresh tzfiles
t0 = t0_u.astimezone(SYD0)
t1 = t1_u.astimezone(SYD1)
self.assertEqual(t0.replace(tzinfo=None), t_n)
self.assertEqual(t1.replace(tzinfo=None), t_n + timedelta(hours=2))
self.assertEqual(t0.utcoffset(), timedelta(hours=10))
self.assertEqual(t1.utcoffset(), timedelta(hours=11))
def testTzwinName(self):
# https://github.com/dateutil/dateutil/issues/143
tw = tz.tzwin('Eastern Standard Time')
# Cover the transitions for at least two years.
ESTs = 'Eastern Standard Time'
EDTs = 'Eastern Daylight Time'
transition_dates = [(datetime(2015, 3, 8, 0, 59), ESTs),
(datetime(2015, 3, 8, 3, 1), EDTs),
(datetime(2015, 11, 1, 0, 59), EDTs),
(datetime(2015, 11, 1, 3, 1), ESTs),
(datetime(2016, 3, 13, 0, 59), ESTs),
(datetime(2016, 3, 13, 3, 1), EDTs),
(datetime(2016, 11, 6, 0, 59), EDTs),
(datetime(2016, 11, 6, 3, 1), ESTs)]
for t_date, expected in transition_dates:
self.assertEqual(t_date.replace(tzinfo=tw).tzname(), expected)
def testTzwinLocalName(self):
# https://github.com/dateutil/dateutil/issues/143
ESTs = 'Eastern Standard Time'
EDTs = 'Eastern Daylight Time'
transition_dates = [(datetime(2015, 3, 8, 0, 59), ESTs),
(datetime(2015, 3, 8, 3, 1), EDTs),
(datetime(2015, 11, 1, 0, 59), EDTs),
(datetime(2015, 11, 1, 3, 1), ESTs),
(datetime(2016, 3, 13, 0, 59), ESTs),
(datetime(2016, 3, 13, 3, 1), EDTs),
(datetime(2016, 11, 6, 0, 59), EDTs),
(datetime(2016, 11, 6, 3, 1), ESTs)]
with TZWinContext('Eastern Standard Time'):
tw = tz.tzwinlocal()
for t_date, expected in transition_dates:
self.assertEqual(t_date.replace(tzinfo=tw).tzname(), expected)
def _get_no_support_tzinfo_class(self, dt_start, dt_end, dst_only=False):
# Generates a class of tzinfo with no support for is_ambiguous
# where dates between dt_start and dt_end are ambiguous.
class FoldingTzInfo(tzinfo):
def utcoffset(self, dt):
if not dst_only:
dt_n = dt.replace(tzinfo=None)
if dt_start <= dt_n < dt_end and getattr(dt_n, 'fold', 0):
return timedelta(hours=-1)
return timedelta(hours=0)
def dst(self, dt):
dt_n = dt.replace(tzinfo=None)
if dt_start <= dt_n < dt_end and getattr(dt_n, 'fold', 0):
return timedelta(hours=1)
else:
return timedelta(0)
return FoldingTzInfo
def is_ambiguous(self, dt):
"""
Whether or not the "wall time" of a given datetime is ambiguous in this
zone.
:param dt:
A :py:class:`datetime.datetime`, naive or time zone aware.
:return:
Returns ``True`` if ambiguous, ``False`` otherwise.
..versionadded:: 2.6.0
"""
dt = dt.replace(tzinfo=self)
wall_0 = enfold(dt, fold=0)
wall_1 = enfold(dt, fold=1)
same_offset = wall_0.utcoffset() == wall_1.utcoffset()
same_dt = wall_0.replace(tzinfo=None) == wall_1.replace(tzinfo=None)
return same_dt and not same_offset
def _fold_status(self, dt_utc, dt_wall):
"""
Determine the fold status of a "wall" datetime, given a representation
of the same datetime as a (naive) UTC datetime. This is calculated based
on the assumption that ``dt.utcoffset() - dt.dst()`` is constant for all
datetimes, and that this offset is the actual number of hours separating
``dt_utc`` and ``dt_wall``.
:param dt_utc:
Representation of the datetime as UTC
:param dt_wall:
Representation of the datetime as "wall time". This parameter must
either have a `fold` attribute or have a fold-naive
:class:`datetime.tzinfo` attached, otherwise the calculation may
fail.
"""
if self.is_ambiguous(dt_wall):
delta_wall = dt_wall - dt_utc
_fold = int(delta_wall == (dt_utc.utcoffset() - dt_utc.dst()))
else:
_fold = 0
return _fold
def _isdst(self, dt):
if not self.hasdst:
return False
elif dt is None:
return None
transitions = self.transitions(dt.year)
if transitions is None:
return False
dt = dt.replace(tzinfo=None)
isdst = self._naive_isdst(dt, transitions)
# Handle ambiguous dates
if not isdst and self.is_ambiguous(dt):
return not self._fold(dt)
else:
return isdst
def is_ambiguous(self, dt):
"""
Whether or not the "wall time" of a given datetime is ambiguous in this
zone.
:param dt:
A :py:class:`datetime.datetime`, naive or time zone aware.
:return:
Returns ``True`` if ambiguous, ``False`` otherwise.
..versionadded:: 2.6.0
"""
dt = dt.replace(tzinfo=self)
wall_0 = enfold(dt, fold=0)
wall_1 = enfold(dt, fold=1)
same_offset = wall_0.utcoffset() == wall_1.utcoffset()
same_dt = wall_0.replace(tzinfo=None) == wall_1.replace(tzinfo=None)
return same_dt and not same_offset
def _fold_status(self, dt_utc, dt_wall):
"""
Determine the fold status of a "wall" datetime, given a representation
of the same datetime as a (naive) UTC datetime. This is calculated based
on the assumption that ``dt.utcoffset() - dt.dst()`` is constant for all
datetimes, and that this offset is the actual number of hours separating
``dt_utc`` and ``dt_wall``.
:param dt_utc:
Representation of the datetime as UTC
:param dt_wall:
Representation of the datetime as "wall time". This parameter must
either have a `fold` attribute or have a fold-naive
:class:`datetime.tzinfo` attached, otherwise the calculation may
fail.
"""
if self.is_ambiguous(dt_wall):
delta_wall = dt_wall - dt_utc
_fold = int(delta_wall == (dt_utc.utcoffset() - dt_utc.dst()))
else:
_fold = 0
return _fold
def is_ambiguous(self, dt):
"""
Whether or not the "wall time" of a given datetime is ambiguous in this
zone.
:param dt:
A :py:class:`datetime.datetime`, naive or time zone aware.
:return:
Returns ``True`` if ambiguous, ``False`` otherwise.
.. versionadded:: 2.6.0
"""
if not self.hasdst:
return False
start, end = self.transitions(dt.year)
dt = dt.replace(tzinfo=None)
return (end <= dt < end + self._dst_base_offset)
def _isdst(self, dt):
if not self.hasdst:
return False
elif dt is None:
return None
transitions = self.transitions(dt.year)
if transitions is None:
return False
dt = dt.replace(tzinfo=None)
isdst = self._naive_isdst(dt, transitions)
# Handle ambiguous dates
if not isdst and self.is_ambiguous(dt):
return not self._fold(dt)
else:
return isdst
def dst(self, dt):
if dt is None or dt.tzinfo is None:
# An exception may be sensible here, in one or both cases.
# It depends on how you want to treat them. The default
# fromutc() implementation (called by the default astimezone()
# implementation) passes a datetime with dt.tzinfo is self.
return ZERO
assert dt.tzinfo is self
# Find first Sunday in April & the last in October.
start = first_sunday_on_or_after(DSTSTART.replace(year=dt.year))
end = first_sunday_on_or_after(DSTEND.replace(year=dt.year))
# Can't compare naive to aware objects, so strip the timezone from
# dt first.
if start <= dt.replace(tzinfo=None) < end:
return HOUR
else:
return ZERO
def main(repo_names, since, until, format, filename):
"""Console script for contributors"""
# If the filename is not provided, build a default using the format
if filename is None:
filename = 'output.{}'.format(format)
# If the file extension of the filename provided by the user does
# not match the format provided, warn the user and continue.
if filename.rsplit('.', 1)[1] != format:
click.echo('Warning: file extension does not match output format')
if since is None:
since = datetime(2012, 6, 2, tzinfo=EST())
if until is None:
until = datetime.now(EST())
output = get_contribitors(repo_names, since=since, until=until, format=format)
click.echo('\nSaving results to %s' % filename)
with open(filename, 'w') as f:
f.write(output)
def start(self):
global TIME_TO_FREEZE
global TZ_OFFSET
self.previous_time_to_freeze = TIME_TO_FREEZE
self.previous_tz_offset = TZ_OFFSET
if isinstance(self.time_to_freeze, original_date):
TIME_TO_FREEZE = self.time_to_freeze
# Convert to a naive UTC datetime if necessary
if TIME_TO_FREEZE.tzinfo:
TIME_TO_FREEZE = TIME_TO_FREEZE.astimezone(utc).replace(tzinfo=None)
else:
TIME_TO_FREEZE = parser.parse(self.time_to_freeze)
TZ_OFFSET = self.tz_offset
return self.time_to_freeze
def set_timezone(self, timezone = None):
with self.tree_lock:
if isinstance(timezone, datetime.tzinfo):
self.timezone = timezone
else:
if timezone == None:
timezone = self.data_value(["timezone"], str, default='utc')
try:
oldtz = self.timezone
self.timezone = pytz.timezone(timezone)
except:
if isinstance(oldtz, datetime.tzinfo):
self.warn('Invalid timezone "%s" suplied. Falling back to the old timezone "%s"' \
% (timezone, oldtz.tzname), dtdata_defWarning, 2)
self.timezone = oldtz
else:
self.warn('Invalid timezone "%s" suplied. Falling back to UTC' % (timezone, ), dtdata_defWarning, 2)
self.timezone = pytz.utc
self.set_current_date()
self.set_current_weekdays()
def set_current_date(self, cdate = None):
with self.tree_lock:
if isinstance(cdate, datetime.datetime):
if cdate.tzinfo == None:
self.current_date = self.timezone.localize(cdate).date()
else:
self.current_date = self.timezone.normalize(cdate.astimezone(self.timezone)).date()
self.current_ordinal = self.current_date.toordinal()
elif isinstance(cdate, datetime.date):
self.current_date = cdate
self.current_ordinal = self.current_date.toordinal()
elif isinstance(cdate, int):
self.current_ordinal = cdate
datetime.datetime.fromordinal(cdate)
else:
if cdate != None:
self.warn('Invalid or no current_date "%s" suplied. Falling back to NOW' % (cdate, ), dtdata_defWarning, 2)
self.current_date = self.timezone.normalize(datetime.datetime.now(pytz.utc).astimezone(self.timezone)).date()
self.current_ordinal = self.current_date.toordinal()
def adjust_from_utc_fields(*args, **kwargs):
"""Constructs a timestamp from UTC fields adjusted to the local offset if given."""
raw_ts = Timestamp(*args, **kwargs)
offset = raw_ts.utcoffset()
if offset is None or offset == timedelta():
return raw_ts
# XXX This returns a datetime, not a Timestamp (which has our precision if defined)
adjusted = raw_ts + offset
if raw_ts.precision is None:
# No precision means we can just return a regular datetime
return adjusted
return Timestamp(
adjusted.year,
adjusted.month,
adjusted.day,
adjusted.hour,
adjusted.minute,
adjusted.second,
adjusted.microsecond,
raw_ts.tzinfo,
precision=raw_ts.precision,
fractional_precision=raw_ts.fractional_precision
)
def convert_to_local_time(dt):
if dt.tzinfo:
return dt.astimezone(LOCAL_TIMEZONE)
else:
return dt.replace(tzinfo=UTC_TIMEZONE).astimezone(LOCAL_TIMEZONE)
def parse_time(time_string):
try:
dt = datetime.strptime(time_string, TIME_FORMAT).replace(tzinfo=LOCAL_TIMEZONE).astimezone(UTC_TIMEZONE).replace(tzinfo=None)
return dt if dt.year >= 1900 else None # the datetime strftime() method requires year >= 1900
except Exception:
return None
def sitemap_time_format(dt):
if dt.tzinfo:
dt = dt.astimezone(UTC_TIMEZONE)
return dt.strftime('%Y-%m-%dT%H:%M:%S+00:00')
def iso_time_format(dt):
if dt.tzinfo:
return convert_to_local_time(dt).strftime(ISO_TIME_FORMAT)
else:
return dt.strftime(ISO_TIME_FORMAT)
def string_as_datetime(time_str):
"""Expects timestamps inline with '2017-06-05T22:45:24.423+0000'"""
# split the utc offset part
naive_time_str, offset_str = time_str[:-5], time_str[-5:]
# parse the naive date/time part
naive_dt = datetime.strptime(naive_time_str, '%Y-%m-%dT%H:%M:%S.%f')
# parse the utc offset
offset = int(offset_str[-4:-2]) * 60 + int(offset_str[-2:])
if offset_str[0] == "-":
offset = -offset
dt = naive_dt.replace(tzinfo=FixedOffset(offset))
return dt
def datetimes_in_range(allow_naive=None, timezones=None, start_date=None, end_date=None, start_inclusive=True, end_inclusive=True):
"""Return a strategy for generating datetimes.
allow_naive=True will cause the values to sometimes be naive.
timezones is the set of permissible timezones. If set to an empty
collection all timezones must be naive. If set to None all available
timezones will be used.
"""
if timezones is None:
timezones = list(pytz.all_timezones)
timezones.remove(u'UTC')
timezones.insert(0, u'UTC')
timezones = [
tz if isinstance(tz, dt.tzinfo) else pytz.timezone(tz)
for tz in timezones
]
if allow_naive is None:
allow_naive = not timezones
if not (timezones or allow_naive):
raise InvalidArgument(
u'Cannot create non-naive datetimes with no timezones allowed'
)
return DatetimeStrategy(
allow_naive=allow_naive, timezones=timezones,
start_date=start_date,
end_date=end_date,
start_inclusive=start_inclusive,
end_inclusive=end_inclusive
)
def format_http_datetime(stamp):
""" Formats datetime to a string following rfc1123 pattern.
>>> now = datetime(2011, 9, 19, 10, 45, 30, 0, UTC)
>>> format_http_datetime(now)
'Mon, 19 Sep 2011 10:45:30 GMT'
if timezone is not set in datetime instance the ``stamp``
is assumed to be in UTC (``datetime.utcnow``).
>>> now = datetime(2011, 9, 19, 10, 45, 30, 0)
>>> format_http_datetime(now)
'Mon, 19 Sep 2011 10:45:30 GMT'
>>> now = datetime.utcnow()
>>> assert format_http_datetime(now)
if ``stamp`` is a string just return it
>>> format_http_datetime('x')
'x'
>>> format_http_datetime(100) # doctest: +ELLIPSIS
Traceback (most recent call last):
...
TypeError: ...
"""
if isinstance(stamp, datetime):
if stamp.tzinfo:
stamp = stamp.astimezone(UTC).timetuple()
else:
stamp = localtime(mktime(stamp.timetuple()))
elif isinstance(stamp, str):
return stamp
else:
raise TypeError('Expecting type ``datetime.datetime``.')
year, month, day, hh, mm, ss, wd, y, z = stamp
return "%s, %02d %3s %4d %02d:%02d:%02d GMT" % (
WEEKDAYS[wd], day, MONTHS[month], year, hh, mm, ss
)
def __new__(cls, document_class=dict,
tz_aware=False, uuid_representation=PYTHON_LEGACY,
unicode_decode_error_handler="strict",
tzinfo=None):
if not (issubclass(document_class, MutableMapping) or
_raw_document_class(document_class)):
raise TypeError("document_class must be dict, bson.son.SON, "
"bson.raw_bson_document.RawBSONDocument, or a "
"sublass of collections.MutableMapping")
if not isinstance(tz_aware, bool):
raise TypeError("tz_aware must be True or False")
if uuid_representation not in ALL_UUID_REPRESENTATIONS:
raise ValueError("uuid_representation must be a value "
"from bson.binary.ALL_UUID_REPRESENTATIONS")
if not isinstance(unicode_decode_error_handler, (string_type, None)):
raise ValueError("unicode_decode_error_handler must be a string "
"or None")
if tzinfo is not None:
if not isinstance(tzinfo, datetime.tzinfo):
raise TypeError(
"tzinfo must be an instance of datetime.tzinfo")
if not tz_aware:
raise ValueError(
"cannot specify tzinfo without also setting tz_aware=True")
return tuple.__new__(
cls, (document_class, tz_aware, uuid_representation,
unicode_decode_error_handler, tzinfo))
def __repr__(self):
document_class_repr = (
'dict' if self.document_class is dict
else repr(self.document_class))
uuid_rep_repr = UUID_REPRESENTATION_NAMES.get(self.uuid_representation,
self.uuid_representation)
return (
'CodecOptions(document_class=%s, tz_aware=%r, uuid_representation='
'%s, unicode_decode_error_handler=%r, tzinfo=%r)' %
(document_class_repr, self.tz_aware, uuid_rep_repr,
self.unicode_decode_error_handler,
self.tzinfo))
def _parse_codec_options(options):
"""Parse BSON codec options."""
return CodecOptions(
document_class=options.get(
'document_class', DEFAULT_CODEC_OPTIONS.document_class),
tz_aware=options.get(
'tz_aware', DEFAULT_CODEC_OPTIONS.tz_aware),
uuid_representation=options.get(
'uuidrepresentation', DEFAULT_CODEC_OPTIONS.uuid_representation),
unicode_decode_error_handler=options.get(
'unicode_decode_error_handler',
DEFAULT_CODEC_OPTIONS.unicode_decode_error_handler),
tzinfo=options.get('tzinfo', DEFAULT_CODEC_OPTIONS.tzinfo))
def test_datetime_tzinfo_io(self):
class TZ(tzinfo):
def utcoffset(self, date_time):
return timedelta(hours=-1)
def dst(self, date_time):
return None
now = datetime(1982, 1, 1, tzinfo=TZ())
dt = self.DatetimeTest.objects.create(test_id=1, created_at=now)
dt2 = self.DatetimeTest.objects(test_id=1).first()
self.assertEqual(dt2.created_at.timetuple()[:6], (now + timedelta(hours=1)).timetuple()[:6])
def timestamp(x):
"""Get a timestamp from a date in python 3 and python 2"""
if x.tzinfo is None:
# Naive dates to utc
x = x.replace(tzinfo=utc)
if hasattr(x, 'timestamp'):
return x.timestamp()
else:
return (x - datetime(1970, 1, 1, tzinfo=utc)).total_seconds()
def _isdst(self, dt):
# We can't use mktime here. It is unstable when deciding if
# the hour near to a change is DST or not.
#
# timestamp = time.mktime((dt.year, dt.month, dt.day, dt.hour,
# dt.minute, dt.second, dt.weekday(), 0, -1))
# return time.localtime(timestamp).tm_isdst
#
# The code above yields the following result:
#
# >>> import tz, datetime
# >>> t = tz.tzlocal()
# >>> datetime.datetime(2003,2,15,23,tzinfo=t).tzname()
# 'BRDT'
# >>> datetime.datetime(2003,2,16,0,tzinfo=t).tzname()
# 'BRST'
# >>> datetime.datetime(2003,2,15,23,tzinfo=t).tzname()
# 'BRST'
# >>> datetime.datetime(2003,2,15,22,tzinfo=t).tzname()
# 'BRDT'
# >>> datetime.datetime(2003,2,15,23,tzinfo=t).tzname()
# 'BRDT'
#
# Here is a more stable implementation:
#
timestamp = ((dt.toordinal() - EPOCHORDINAL) * 86400
+ dt.hour * 3600
+ dt.minute * 60
+ dt.second)
return time.localtime(timestamp+time.timezone).tm_isdst
def _isdst(self, dt):
if not self._start_delta:
return False
year = datetime.datetime(dt.year, 1, 1)
start = year+self._start_delta
end = year+self._end_delta
dt = dt.replace(tzinfo=None)
if start < end:
return dt >= start and dt < end
else:
return dt >= start or dt < end
def _delta(self, x, isend=0):
kwargs = {}
if x.month is not None:
kwargs["month"] = x.month
if x.weekday is not None:
kwargs["weekday"] = relativedelta.weekday(x.weekday, x.week)
if x.week > 0:
kwargs["day"] = 1
else:
kwargs["day"] = 31
elif x.day:
kwargs["day"] = x.day
elif x.yday is not None:
kwargs["yearday"] = x.yday
elif x.jyday is not None:
kwargs["nlyearday"] = x.jyday
if not kwargs:
# Default is to start on first sunday of april, and end
# on last sunday of october.
if not isend:
kwargs["month"] = 4
kwargs["day"] = 1
kwargs["weekday"] = relativedelta.SU(+1)
else:
kwargs["month"] = 10
kwargs["day"] = 31
kwargs["weekday"] = relativedelta.SU(-1)
if x.time is not None:
kwargs["seconds"] = x.time
else:
# Default is 2AM.
kwargs["seconds"] = 7200
if isend:
# Convert to standard time, to follow the documented way
# of working with the extra hour. See the documentation
# of the tzinfo class.
delta = self._dst_offset-self._std_offset
kwargs["seconds"] -= delta.seconds+delta.days*86400
return relativedelta.relativedelta(**kwargs)
def _find_comp(self, dt):
if len(self._comps) == 1:
return self._comps[0]
dt = dt.replace(tzinfo=None)
try:
return self._cachecomp[self._cachedate.index(dt)]
except ValueError:
pass
lastcomp = None
lastcompdt = None
for comp in self._comps:
if not comp.isdst:
# Handle the extra hour in DST -> STD
compdt = comp.rrule.before(dt-comp.tzoffsetdiff, inc=True)
else:
compdt = comp.rrule.before(dt, inc=True)
if compdt and (not lastcompdt or lastcompdt < compdt):
lastcompdt = compdt
lastcomp = comp
if not lastcomp:
# RFC says nothing about what to do when a given
# time is before the first onset date. We'll look for the
# first standard component, or the first component, if
# none is found.
for comp in self._comps:
if not comp.isdst:
lastcomp = comp
break
else:
lastcomp = comp[0]
self._cachedate.insert(0, dt)
self._cachecomp.insert(0, lastcomp)
if len(self._cachedate) > 10:
self._cachedate.pop()
self._cachecomp.pop()
return lastcomp
def _isdst(self, dt):
if not self._dstmonth:
# dstmonth == 0 signals the zone has no daylight saving time
return False
dston = picknthweekday(dt.year, self._dstmonth, self._dstdayofweek,
self._dsthour, self._dstminute,
self._dstweeknumber)
dstoff = picknthweekday(dt.year, self._stdmonth, self._stddayofweek,
self._stdhour, self._stdminute,
self._stdweeknumber)
if dston < dstoff:
return dston <= dt.replace(tzinfo=None) < dstoff
else:
return not dstoff <= dt.replace(tzinfo=None) < dston
def is_aware(value):
"""
Determines if a given datetime.datetime is aware.
The concept is defined in Python's docs:
http://docs.python.org/library/datetime.html#datetime.tzinfo
Assuming value.tzinfo is either None or a proper datetime.tzinfo,
value.utcoffset() implements the appropriate logic.
"""
return value.utcoffset() is not None
# add from https://github.com/angelbot/geoincentives/blob/7b156fc0d223a1e9376e83651c7c8ad5deaa2b0f/coffin/template/defaultfilters.py
def timesince(d):
time1 = datetime.datetime.utcnow()
format = '%Y-%m-%d %H:%M:%S'
delta = time1 - d.replace(tzinfo=None)
before = delta.days * 24 * 60 * 60 + delta.seconds
if before <= 60:
return 'just now'
else:
return datetime.timedelta(seconds=before)
def date(value, fmt=None):
date = dateutil.parser.parse(str(value))
native = date.replace(tzinfo=None)
format='%b %d, %Y'
return native.strftime(format)
def dst(self, dt):
if dt is None or dt.tzinfo is None:
# An exception may be sensible here, in one or both cases.
# It depends on how you want to treat them. The default
# fromutc() implementation (called by the default astimezone()
# implementation) passes a datetime with dt.tzinfo is self.
return ZERO
assert dt.tzinfo is self
# Find start and end times for US DST. For years before 1967, return
# ZERO for no DST.
if 2006 < dt.year:
dststart, dstend = DSTSTART_2007, DSTEND_2007
elif 1986 < dt.year < 2007:
dststart, dstend = DSTSTART_1987_2006, DSTEND_1987_2006
elif 1966 < dt.year < 1987:
dststart, dstend = DSTSTART_1967_1986, DSTEND_1967_1986
else:
return ZERO
start = first_sunday_on_or_after(dststart.replace(year=dt.year))
end = first_sunday_on_or_after(dstend.replace(year=dt.year))
# Can't compare naive to aware objects, so strip the timezone from
# dt first.
if start <= dt.replace(tzinfo=None) < end:
return HOUR
else:
return ZERO
def is_aware(value):
"""
Determines if a given datetime.datetime is aware.
The concept is defined in Python's docs:
http://docs.python.org/library/datetime.html#datetime.tzinfo
Assuming value.tzinfo is either None or a proper datetime.tzinfo,
value.utcoffset() implements the appropriate logic.
"""
return value.utcoffset() is not None