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)
python类tzinfo()的实例源码
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