""" ``datetime`` module.
"""
from time import localtime
from time import mktime
from wheezy.core.comp import parsedate
from wheezy.core.introspection import import_name
# The lines below are equivalent to:
# from datetime import timedelta
# However it is not used due module name confict
# since the use of relative imports by default.
# absolute imports are available since python 2.5,
# however we want keep compatibility with python 2.4
datetime = import_name('datetime.datetime')
time = import_name('datetime.time')
timedelta = import_name('datetime.timedelta')
tzinfo = import_name('datetime.tzinfo')
ZERO = timedelta(0)
WEEKDAYS = ("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun")
MONTHS = (
None, "Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec")
def format_http_datetime(stamp):
[docs] """ 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 format_iso_datetime(stamp):
[docs] """ Return a string representing the date and time in ISO 8601 format.
If the time is in UTC, adds a 'Z' directly after the time without
a space.
see http://en.wikipedia.org/wiki/ISO_8601.
>>> class EET(tzinfo):
... def utcoffset(self, dt):
... return timedelta(minutes=120)
... def dst(self, dt):
... return timedelta()
>>> format_iso_datetime(datetime(2012, 2, 22, 12, 52, 29, 300))
'2012-02-22T12:52:29'
>>> format_iso_datetime(datetime(2012, 2, 22, 12, 52, 29, 300,
... tzinfo=UTC))
'2012-02-22T12:52:29Z'
>>> format_iso_datetime(datetime(2012, 2, 22, 12, 52, 29, 300,
... tzinfo=EET()))
'2012-02-22T12:52:29+02:00'
"""
if stamp.tzinfo:
if stamp.utcoffset() == ZERO:
return datetime(*stamp.timetuple()[:6]).isoformat() + 'Z'
if stamp.microsecond:
stamp = stamp.replace(microsecond=0)
return stamp.isoformat()
def format_iso_time(stamp):
[docs] """ Return a string representing the time in ISO 8601 format.
If the time is in UTC, adds a 'Z' directly after the time without
a space.
see http://en.wikipedia.org/wiki/ISO_8601.
>>> class EET(tzinfo):
... def utcoffset(self, dt):
... return timedelta(minutes=120)
... def dst(self, dt):
... return timedelta()
>>> format_iso_time(time(12, 52, 29, 300))
'12:52:29'
>>> format_iso_time(time(12, 52, 29, 300,
... tzinfo=UTC))
'12:52:29Z'
>>> format_iso_time(time(12, 52, 29, 300,
... tzinfo=EET()))
'12:52:29+02:00'
"""
if stamp.microsecond:
stamp = stamp.replace(microsecond=0)
if stamp.tzinfo:
if stamp.utcoffset() == ZERO:
return stamp.replace(tzinfo=None).isoformat() + 'Z'
else:
return stamp.isoformat()
else:
return stamp.isoformat()
def parse_http_datetime(stamp):
[docs] """ Parses a string in rfc1123 format to ``datetime``.
>>> parse_http_datetime('Mon, 19 Sep 2011 10:45:30 GMT')
datetime.datetime(2011, 9, 19, 10, 45, 30)
"""
return datetime.fromtimestamp(mktime(parsedate(stamp)))
def total_seconds(delta):
[docs] """ Returns a total number of seconds for the given delta.
``delta`` can be ``datetime.timedelta``.
>>> total_seconds(timedelta(hours=2))
7200
or int:
>>> total_seconds(100)
100
otherwise raise ``TypeError``.
>>> total_seconds('100') # doctest: +ELLIPSIS
Traceback (most recent call last):
...
TypeError: ...
"""
if isinstance(delta, int):
return delta
elif isinstance(delta, timedelta):
return delta.seconds + delta.days * 86400
else:
raise TypeError('Expecting type datetime.timedelta '
'or int for seconds')
class utc(tzinfo):
[docs] """ UTC timezone.
"""
__slots__ = ('name')
def __init__(self, name):
self.name = name
def tzname(self, dt):
[docs] """ Name of time zone.
>>> GMT.tzname(None)
'GMT'
>>> UTC.tzname(None)
'UTC'
"""
return self.name
def utcoffset(self, dt):
[docs] """ Offset from UTC.
>>> UTC.utcoffset(None)
datetime.timedelta(0)
"""
return ZERO
def dst(self, dt):
[docs] """ DST is not in effect.
>>> UTC.dst(None)
datetime.timedelta(0)
"""
return ZERO
GMT = utc('GMT')
UTC = utc('UTC')