Python - datetime
Jump to navigation
Jump to search
References
- http://seehuhn.de/pages/pdate#sec:1.6.0
- http://www.tutorialspoint.com/python/time_strptime.htm - A good summary of codes/directives...
Precision
Here's a simple two-liner to calculate roughly how many YEARS you can squeeze into what's left of the 53 bits of precsion in an IEEE754 64-bit float:
>>> import math >>> 10 ** (math.log10(2 ** 53) - math.log10(60 * 60 * 24) - 6) / 365.25 285.42092094268787 >>>
Watch out for round-off; add the smallest non-zero numbers first:
return timedelta.seconds + timedelta.microseconds / 1E6 + timedelta.days * 86400
Examples
Simple Example
#!/usr/bin/env python
import datetime
start_date = datetime.datetime(2007,01,01)
end_date = datetime.datetime(2008,03,11)
print start_date
print end_date
date = start_date
print 'Date'
while date < end_date:
print date.strftime('%Y-%m-%d')
date += datetime.timedelta(days=1)
Examples of Range of Functions
#!/usr/bin/env python
#
# $Id:$
#
#---------------------------------------------------------------------
import sys
import getopt
from datetime import datetime, timedelta
#---------------------------------------------------------------------
"""
From datetime documentation...
def astimezone(self, tz):
if self.tzinfo is tz:
return self
# Convert self to UTC, and attach the new time zone object.
utc = (self - self.utcoffset()).replace(tzinfo=tz)
# Convert from UTC to tz's local time.
return tz.fromutc(utc)
"""
#---------------------------------------------------------------------
def display(dt):
print " timetuple() -> %s" % dt.timetuple()
print " strftime() -> %s" % dt.strftime("%Y-%m-%d %H:%M:%S")
print "isocalendar() -> %s" % str(dt.isocalendar())
print " weekday() -> %d" % dt.weekday()
print " isoweekday() -> %d" % dt.isoweekday()
print " isoformat() -> %s" % dt.isoformat()
print " __str__() -> %s" % dt.__str__()
print " ctime() -> %s" % dt.ctime()
print " tzname() -> %s" % dt.tzname()
print " dst() -> %s" % dt.dst()
print " timetz() -> %s" % dt.timetz()
#---------------------------------------------------------------------
def test():
now = datetime.now()
print "now():"
display(now)
utcnow = datetime.utcnow()
print "utcnow():"
display(utcnow)
plus_1_day = now + timedelta(days=1)
print "plus_1_day():"
display(plus_1_day)
plus_2_day = now + timedelta(days=2)
print "plus_2_day():"
display(plus_2_day)
#---------------------------------------------------------------------
def usage():
USAGE = """
Usage:
$ dt.py
"""
sys.stderr.write(USAGE)
#---------------------------------------------------------------------
def main(argv):
global logfile, verbose_flg
#----- Process command line arguments ----------------------------
try:
opts, args = getopt.getopt(argv, "hl:u:t", ["help", "logfile=", "verbose"])
except getopt.GetoptError:
usage()
sys.exit(2)
else:
for opt, arg in opts:
if opt in ("-h", "--help"):
usage()
sys.exit(0)
elif opt in ("-l", "--logfile"):
logfile = arg
elif opt in ("-v", "--verbose"):
verbose_flg = True
test()
#---------------------------------------------------------------------
if __name__ == "__main__":
main(sys.argv[1:])
#---------------------------------------------------------------------
Exploring datetime and time Modules
#!/usr/bin/env python import time import datetime import pprint print datetime.datetime.now() print datetime.datetime.now().date() print datetime.datetime.now().date().isoformat() print datetime.datetime.now().time() print datetime.__doc__ print print print "time.time() -> ", time.time() print pp = pprint pp.pprint(time.__dict__) print time.__doc__
Timezone Examples
>>> import datetime >>> from dateutil import tz # python dateutil offers loads of convenience: http://labix.org/python-dateutil >>> dt = datetime.datetime(2008, 8, 21, 12, 51, 0, 0, tz.tzlocal()) >>> print repr(dt), ":", dt datetime.datetime(2008, 8, 21, 12, 51, tzinfo=tzlocal()) : 2008-08-21 12:51:00+02:00 >>> dt_utc = dt.astimezone(tz.tzutc()) >>> print repr(dt_utc), ":", dt datetime.datetime(2008, 8, 21, 10, 51, tzinfo=tzutc()) : 2008-08-21 12:51:00+02:00 >>> dt == dt_utc
Using strptime() and strftime()
from datetime import datetime
dt = datetime.strptime('10:13:15 2006-03-07', '%H:%M:%S %Y-%m-%d')
ts = datetime.now().strftime('%Y%m%d%H%M%S')
rdt = task.fields.ReminderDateTime
if rdt:
ctx.locals.ReminderDate = rdt.strftime('%Y-%m-%d')
ctx.locals.ReminderTime = rdt.hour * 60 + rdt.minute
else:
ctx.locals.ReminderDate = ctx.locals.Today
ctx.locals.ReminderTime = 630
from time import strptime
...
'ReminderDateTime' : datetime(*strptime(ctx.locals.ReminderDateTime, '%Y-%m-%d')[0:6]) + timedelta(minutes=int(ctx.locals.ReminderTime)),
Python Documentation
Timezone
from datetime import tzinfo, timedelta, datetime
ZERO = timedelta(0)
HOUR = timedelta(hours=1)
# A UTC class.
class UTC(tzinfo):
"""UTC"""
def utcoffset(self, dt):
return ZERO
def tzname(self, dt):
return "UTC"
def dst(self, dt):
return ZERO
utc = UTC()
# A class building tzinfo objects for fixed-offset time zones.
# Note that FixedOffset(0, "UTC") is a different way to build a
# UTC tzinfo object.
class FixedOffset(tzinfo):
"""Fixed offset in minutes east from UTC."""
def __init__(self, offset, name):
self.__offset = timedelta(minutes = offset)
self.__name = name
def utcoffset(self, dt):
return self.__offset
def tzname(self, dt):
return self.__name
def dst(self, dt):
return ZERO
# A class capturing the platform's idea of local time.
import time as _time
STDOFFSET = timedelta(seconds = -_time.timezone)
if _time.daylight:
DSTOFFSET = timedelta(seconds = -_time.altzone)
else:
DSTOFFSET = STDOFFSET
DSTDIFF = DSTOFFSET - STDOFFSET
class LocalTimezone(tzinfo):
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()
# A complete implementation of current DST rules for major US time zones.
def first_sunday_on_or_after(dt):
days_to_go = 6 - dt.weekday()
if days_to_go:
dt += timedelta(days_to_go)
return dt
# In the US, DST starts at 2am (standard time) on the first Sunday in April.
DSTSTART = datetime(1, 4, 1, 2)
# and ends at 2am (DST time; 1am standard time) on the last Sunday of Oct.
# which is the first Sunday on or after Oct 25.
DSTEND = datetime(1, 10, 25, 1)
class USTimeZone(tzinfo):
def __init__(self, hours, reprname, stdname, dstname):
self.stdoffset = timedelta(hours=hours)
self.reprname = reprname
self.stdname = stdname
self.dstname = dstname
def __repr__(self):
return self.reprname
def tzname(self, dt):
if self.dst(dt):
return self.dstname
else:
return self.stdname
def utcoffset(self, dt):
return self.stdoffset + self.dst(dt)
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
Eastern = USTimeZone(-5, "Eastern", "EST", "EDT")
Central = USTimeZone(-6, "Central", "CST", "CDT")
Mountain = USTimeZone(-7, "Mountain", "MST", "MDT")
Pacific = USTimeZone(-8, "Pacific", "PST", "PDT")
Datetime Woes
# Copyright (c) 2008, Red Innovation Ltd., Finland
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of Red Innovation nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY RED INNOVATION ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL RED INNOVATION BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
__doc__ = """
This module provides monkey-patched Python datetime class
that fully supports different time zones and conversions
between them.
See the source for licensing terms.
"""
__author__ = 'Antti Haapala <antti@redinnovation.com>'
__date__ = '24 Jun 2008'
__version__ = '$Revision$'
__copyright__ = '2008 Red Innovation Ltd.'
__license__ = '3-clause BSD'
from datetime import datetime as _datetime, tzinfo as _tzinfo
from pytz import timezone as _timezone
import time as _time
import pytz as _pytz
import math as _math
import re as _re
from pytz import utc, UTC, HOUR, ZERO
_utc = _pytz.utc
_default_tz = _utc
def set_default_timezone(new_tz):
"""Sets the default time zone used by the objects
contained in this module. new_tz may be either
a pytz-compatible tzinfo (requires normalize
and localize methods), or a time zone name known
to pytz.
"""
global _default_tz
if type(new_tz) is str or type(new_tz) is unicode:
new_tz = _pytz.timezone(new_tz)
_default_tz = new_tz
class FixedOffset(_tzinfo):
"""Fixed offset in minutes east from UTC. Based on
the python tutorial and pytz test code."""
def __init__(self, offset, name):
"""Constructor. Create a new tzinfo object
with given offset in minutes and name."""
self.__offset = timedelta(minutes = offset)
self.__name = name
def utcoffset(self, dt):
return self.__offset
def tzname(self, dt):
return self.__name
def dst(self, dt):
return ZERO
def localize(self, dt, is_dst=False):
"""Convert naive time to local time. Copied
from pytz tzinfo classes"""
if dt.tzinfo is not None:
raise ValueError, 'Not naive datetime (tzinfo is already set)'
return dt.replace(tzinfo=self)
def normalize(self, dt, is_dst=False):
"""Correct the timezone information on the
given datetime. Copied from pytz tzinfo classes."""
if dt.tzinfo is None:
raise ValueError, 'Naive time - no tzinfo set'
return dt.replace(tzinfo=self)
def __str__(self):
return self.__name
def __repr__(self):
return '<%s>' % self.__name
_fixed_offset_tzs = { }
def _get_fixed_offset_tz(offsetmins):
"""For internal use only: Returns a tzinfo with
the given fixed offset. This creates only one instance
for each offset; the zones are kept in a dictionary"""
if offsetmins == 0:
return _utc
if not _fixed_offset_tzs.has_key(offsetmins):
if offsetmins < 0:
sign = '-'
absoff = -offsetmins
else:
sign = '+'
absoff = offsetmins
name = "UTC%s%02d:%02d" % (sign, int(absoff / 60), absoff % 60)
inst = FixedOffset(offsetmins, name)
_fixed_offset_tzs[offsetmins] = inst
return _fixed_offset_tzs[offsetmins]
_iso8601_parser = _re.compile("""
^
(?P<year> [0-9]{4})(?P<ymdsep>-?)
(?P<month>[0-9]{2})(?P=ymdsep)
(?P<day> [0-9]{2})
(?: # time part... optional... at least hour must be specified
(?:T|\s+)
(?P<hour>[0-9]{2})
(?:
# minutes, separated with :, or none, from hours
(?P<hmssep>[:]?)
(?P<minute>[0-9]{2})
(?:
# same for seconds, separated with :, or none, from hours
(?P=hmssep)
(?P<second>[0-9]{2})
)?
)?
# fractions
(?: [,.] (?P<frac>[0-9]{1,10}))?
# timezone, Z, +-hh or +-hh:?mm. MUST BE, but complain if not there.
(
(?P<tzempty>Z)
|
(?P<tzh>[+-][0-9]{2})
(?: :? # optional separator
(?P<tzm>[0-9]{2})
)?
)?
)?
$
""", _re.X) # """
def _parse_iso(timestamp):
"""Internal function for parsing a timestamp in
ISO 8601 format"""
timestamp = timestamp.strip()
m = _iso8601_parser.match(timestamp)
if not m:
raise ValueError("Not a proper ISO 8601 timestamp!")
year = int(m.group('year'))
month = int(m.group('month'))
day = int(m.group('day'))
h, min, s, us = None, None, None, 0
frac = 0
if m.group('tzempty') == None and m.group('tzh') == None:
raise ValueError("Not a proper ISO 8601 timestamp: " +
"missing timezone (Z or +hh[:mm])!")
if m.group('frac'):
frac = m.group('frac')
power = len(frac)
frac = long(frac) / 10.0 ** power
if m.group('hour'):
h = int(m.group('hour'))
if m.group('minute'):
min = int(m.group('minute'))
if m.group('second'):
s = int(m.group('second'))
if frac != None:
# ok, fractions of hour?
if min == None:
frac, min = _math.modf(frac * 60.0)
min = int(min)
# fractions of second?
if s == None:
frac, s = _math.modf(frac * 60.0)
s = int(s)
# and extract microseconds...
us = int(frac * 1000000)
if m.group('tzempty') == 'Z':
offsetmins = 0
else:
# timezone: hour diff with sign
offsetmins = int(m.group('tzh')) * 60
tzm = m.group('tzm')
# add optional minutes
if tzm != None:
tzm = long(tzm)
offsetmins += tzm if offsetmins > 0 else -tzm
tz = _get_fixed_offset_tz(offsetmins)
return datetime(year, month, day, h, min, s, us, tz)
class datetime(_datetime):
"""Time zone aware subclass of Python datetime.datetime"""
__name__ = 'fixed_datetime.datetime'
def __new__(cls, year, month, day, hour=0, minute=0, second=0, microsecond=0, tzinfo=None, is_dst=False):
"""Creates a localized timestamp with the given parameters.
If tzinfo is omitted, the default time zone will be used."""
if tzinfo == None:
tzinfo = _default_tz
dt = _datetime(year, month, day, hour, minute, second, microsecond)
dt = tzinfo.localize(dt, is_dst=is_dst)
return _datetime.__new__(
cls, dt.year, dt.month, dt.day,
dt.hour, dt.minute, dt.second,
dt.microsecond, dt.tzinfo)
def __radd__(self, addend):
"""Autonormalized addition of datetimes and timedeltas."""
added = _datetime.__radd__(self, addend)
added = self.tzinfo.normalize(added)
return datetime.__from_datetime_with_tz(added)
def __add__(self, addend):
"""Autonormalized addition of datetimes and timedeltas."""
added = _datetime.__add__(self, addend)
added = self.tzinfo.normalize(added)
return datetime.__from_datetime_with_tz(added)
def utctimetuple(self):
"""Return UTC time tuple, compatible with time.gmtime().
Notice: the original datetime documentation is misleading:
Calling utctimetuple() on a timezone-aware datetime will
return the tuple in UTC, not in local time."""
return _datetime.utctimetuple(self)
def astimezone(self, tzinfo):
"""Convert to local time in new timezone tz.
The result is normalized across DST boundaries."""
dt = _datetime.astimezone(self, tzinfo)
dt = tzinfo.normalize(dt)
return datetime.__from_datetime_with_tz(dt)
@staticmethod
def __from_datetime_with_tz(dt):
"""Internal: create a datetime instance from
a timezone-aware instance of the builtin datetime type."""
if dt.tzinfo == None:
raise ValueError("The given datetime.datetime is not timezone-aware!")
return datetime(dt.year, dt.month, dt.day,
dt.hour, dt.minute, dt.second, dt.microsecond,
dt.tzinfo)
@staticmethod
def fromtimestamp(timestamp, tz=None):
"""Tz's local time from POSIX timestamp."""
bd = _time.gmtime(long(timestamp))
us = 0
if isinstance(timestamp, float):
us = timestamp % 1.0
us *= 1000000
args = list(bd[:6])
args += [ int(us), _utc ]
_tmp = datetime(*args)
if tz == None:
tz = _default_tz
rv = _tmp.astimezone(tz)
return datetime.__from_datetime_with_tz(rv)
@staticmethod
def today(tz=None):
"""New datetime with tz's local day and time
If tz is not specified, use the default timezone"""
return datetime.fromtimestamp(long(_time.time()), tz)
@staticmethod
def now(tz=None):
"""New datetime with tz's local day and time
If tz is not specified, use the default timezone"""
return datetime.fromtimestamp(_time.time(), tz)
@staticmethod
def utcnow():
"""Return a new datetime representing UTC day and time."""
return datetime.now(tz=_utc)
@staticmethod
def utcfromtimestamp():
"""Return a new UTC datetime from a POSIX timestamp (like time.time())."""
return datetime.utcfromtimestamp(tz=_utc)
@staticmethod
def parseisoformat(timestamp):
"""Parses the given ISO 8601 compatible timestamp string
and converts it to fixed_datetime.datetime. The timestamp
must conform to following formats:
- the format is DATE SEP TIME TIMEZONE without
any intervening spaces.
- the date must be in format YYYY-MM-DD
- the time may be either
* HH:MM:SS,FFFF
* HH:MM,FFFF
* HH,FFFF
FFFF is the fractional part. Decimal point can be
used too.
- the time zone must be either Z, -HH:MM or +HH:MM
- the date and time must be separated either by
whitespace or single T letter
- the separators - and : may all be omitted, or
must all be present.
Examples (Unix Epoch):
1970-01-01T00:00:00Z
1970-01-01T00Z
1969-12-31 19,5-04:30
19700101T030000+0300
"""
return _parse_iso(timestamp)
def isoformat(self, sep='T', short=False):
"""Returns the date represented by this instance
in ISO 8601 conforming format. The separator
is used to separate the date and time, and defaults
to 'T'. This method supports both long and short
formats. The long format is
YYYY-MM-DD HH:MM:SS[.FFFFFF]=HH:MM
and short is
YYYYMMDDTHHMMSS[.FFFFFF]=HHMM
The fractional part is separated with decimal point and
is omitted if microseconds stored in this datetime are
0.
"""
if not short:
return _datetime.isoformat(self, sep)
args = [ self.year, self.month, self.day, self.hour, self.minute, self.second ]
fmt = "%04d%02d%02dT%02d%02d%02d"
tz = "%s%02d%02d"
if self.microsecond != 0:
fmt += ".%06d"
args += [ self.microsecond ]
offset = self.tzinfo.utcoffset(self)
tzseconds = offset.seconds + offset.days * 24 * 60 * 60
sign = '+' if tzseconds >= 0 else '-'
tzseconds = abs(tzseconds)
tzout = tz % (sign, int(tzseconds / 3600), int((tzseconds / 60) % 60))
dtout = fmt % tuple(args)
return dtout + tzout
from datetime import date, timedelta, time, tzinfo, MAXYEAR, MINYEAR