timeutils
- datetime
additions
Python’s datetime
module provides some of the most complex
and powerful primitives in the Python standard library. Time is
nontrivial, but thankfully its support is first-class in
Python. dateutils
provides some additional tools for working with
time.
Additionally, timeutils provides a few basic utilities for working
with timezones in Python. The Python datetime
module’s
documentation describes how to create a
datetime
-compatible tzinfo
subtype. It even provides a few examples.
The following module defines usable forms of the timezones in those
docs, as well as a couple other useful ones, UTC
(aka GMT) and
LocalTZ
(representing the local timezone as configured in the
operating system). For timezones beyond these, as well as a higher
degree of accuracy in corner cases, check out pytz and `dateutil`_.
- boltons.timeutils.daterange(start, stop, step=1, inclusive=False)[source]
In the spirit of
range()
andxrange()
, the daterange generator that yields a sequence ofdate
objects, starting at start, incrementing by step, until stop is reached.When inclusive is True, the final date may be stop, if step falls evenly on it. By default, step is one day. See details below for many more details.
- Parameters:
start (datetime.date) – The starting date The first value in the sequence.
stop (datetime.date) – The stopping date. By default not included in return. Can be None to yield an infinite sequence.
step (int) – The value to increment start by to reach stop. Can be an
int
number of days, adatetime.timedelta
, or atuple
of integers, (year, month, day). Positive and negative step values are supported.inclusive (bool) – Whether or not the stop date can be returned. stop is only returned when a step falls evenly on it.
>>> christmas = date(year=2015, month=12, day=25) >>> boxing_day = date(year=2015, month=12, day=26) >>> new_year = date(year=2016, month=1, day=1) >>> for day in daterange(christmas, new_year): ... print(repr(day)) datetime.date(2015, 12, 25) datetime.date(2015, 12, 26) datetime.date(2015, 12, 27) datetime.date(2015, 12, 28) datetime.date(2015, 12, 29) datetime.date(2015, 12, 30) datetime.date(2015, 12, 31) >>> for day in daterange(christmas, boxing_day): ... print(repr(day)) datetime.date(2015, 12, 25) >>> for day in daterange(date(2017, 5, 1), date(2017, 8, 1), ... step=(0, 1, 0), inclusive=True): ... print(repr(day)) datetime.date(2017, 5, 1) datetime.date(2017, 6, 1) datetime.date(2017, 7, 1) datetime.date(2017, 8, 1)
Be careful when using stop=None, as this will yield an infinite sequence of dates.
- boltons.timeutils.isoparse(iso_str)[source]
Parses the limited subset of ISO8601-formatted time strings as returned by
datetime.datetime.isoformat()
.>>> epoch_dt = datetime.utcfromtimestamp(0) >>> iso_str = epoch_dt.isoformat() >>> print(iso_str) 1970-01-01T00:00:00 >>> isoparse(iso_str) datetime.datetime(1970, 1, 1, 0, 0)
>>> utcnow = datetime.utcnow() >>> utcnow == isoparse(utcnow.isoformat()) True
For further datetime parsing, see the iso8601 package for strict ISO parsing and `dateutil`_ package for loose parsing and more.
- boltons.timeutils.parse_timedelta(text)[source]
Robustly parses a short text description of a time period into a
datetime.timedelta
. Supports weeks, days, hours, minutes, and seconds, with or without decimal points:- Parameters:
text (str) – Text to parse.
- Returns:
datetime.timedelta
- Raises:
ValueError – on parse failure.
>>> parse_td('1d 2h 3.5m 0s') == timedelta(days=1, seconds=7410) True
Also supports full words and whitespace.
>>> parse_td('2 weeks 1 day') == timedelta(days=15) True
Negative times are supported, too:
>>> parse_td('-1.5 weeks 3m 20s') == timedelta(days=-11, seconds=43400) True
- boltons.timeutils.strpdate(string, format)[source]
Parse the date string according to the format in format. Returns a
date
object. Internally,datetime.strptime()
is used to parse the string and thus conversion specifiers for time fields (e.g. %H) may be provided; these will be parsed but ignored.- Parameters:
- Returns:
datetime.date
>>> strpdate('2016-02-14', '%Y-%m-%d') datetime.date(2016, 2, 14) >>> strpdate('26/12 (2015)', '%d/%m (%Y)') datetime.date(2015, 12, 26) >>> strpdate('20151231 23:59:59', '%Y%m%d %H:%M:%S') datetime.date(2015, 12, 31) >>> strpdate('20160101 00:00:00.001', '%Y%m%d %H:%M:%S.%f') datetime.date(2016, 1, 1)
- boltons.timeutils.total_seconds()
Total seconds in the duration.
- boltons.timeutils.dt_to_timestamp(dt)[source]
Converts from a
datetime
object to an integer timestamp, suitable interoperation withtime.time()
and other Epoch-based timestamps.>>> timestamp = int(time.time()) >>> utc_dt = datetime.fromtimestamp(timestamp, timezone.utc) >>> timestamp - dt_to_timestamp(utc_dt) 0.0
dt_to_timestamp
supports both timezone-aware and naïvedatetime
objects. Note that it assumes naïve datetime objects are implied UTC, such as those generated withdatetime.datetime.utcnow()
. If your datetime objects are local time, such as those generated withdatetime.datetime.now()
, first convert it using thedatetime.datetime.replace()
method withtzinfo=
LocalTZ
object in this module, then pass the result of that todt_to_timestamp
.
- boltons.timeutils.relative_time(d, other=None, ndigits=0)[source]
Get a string representation of the difference between two
datetime
objects or onedatetime
and the current time. Handles past and future times.- Parameters:
d (datetime) – The first datetime object.
other (datetime) – An optional second datetime object. If unset, defaults to the current time as determined
datetime.utcnow()
.ndigits (int) – The number of decimal digits to round to, defaults to
0
.
- Returns:
A short English-language string.
>>> now = datetime.utcnow() >>> relative_time(now, ndigits=1) '0 seconds ago' >>> relative_time(now - timedelta(days=1, seconds=36000), ndigits=1) '1.4 days ago' >>> relative_time(now + timedelta(days=7), now, ndigits=1) '1 week from now'
- boltons.timeutils.decimal_relative_time(d, other=None, ndigits=0, cardinalize=True)[source]
Get a tuple representing the relative time difference between two
datetime
objects or onedatetime
and now.- Parameters:
d (datetime) – The first datetime object.
other (datetime) – An optional second datetime object. If unset, defaults to the current time as determined
datetime.utcnow()
.ndigits (int) – The number of decimal digits to round to, defaults to
0
.cardinalize (bool) – Whether to pluralize the time unit if appropriate, defaults to
True
.
- Returns:
- A tuple of the
float
difference and respective unit of time, pluralized if appropriate and cardinalize is set to
True
.
- A tuple of the
- Return type:
Unlike
relative_time()
, this method’s return is amenable to localization into other languages and custom phrasing and formatting.>>> now = datetime.utcnow() >>> decimal_relative_time(now - timedelta(days=1, seconds=3600), now) (1.0, 'day') >>> decimal_relative_time(now - timedelta(seconds=0.002), now, ndigits=5) (0.002, 'seconds') >>> decimal_relative_time(now, now - timedelta(days=900), ndigits=1) (-2.5, 'years')
General timezones
By default, datetime.datetime
objects are “naïve”, meaning
they lack attached timezone information. These objects can be useful
for many operations, but many operations require timezone-aware
datetimes.
The two most important timezones in programming are Coordinated
Universal Time (UTC) and the local timezone of the host running
your code. Boltons provides two datetime.tzinfo
subtypes for
working with them:
Note
These days, Python has a built-in UTC, and the UTC tzinfo here, while equivalent, is just for backwards compat.
- timeutils.UTC = ConstantTZInfo(name='UTC', offset=datetime.timedelta(0))
- boltons.timeutils.LocalTZ = LocalTZInfo()
The
LocalTZInfo
type takes data available in the time module about the local timezone and makes a practicaldatetime.tzinfo
to represent the timezone settings of the operating system.For a more in-depth integration with the operating system, check out tzlocal. It builds on pytz and implements heuristics for many versions of major operating systems to provide the official
pytz
tzinfo, instead of the LocalTZ generalization.
- class boltons.timeutils.ConstantTZInfo(name='ConstantTZ', offset=datetime.timedelta(0))[source]
A
tzinfo
subtype whose offset remains constant (no daylight savings).- Parameters:
name (str) – Name of the timezone.
offset (datetime.timedelta) – Offset of the timezone.
US timezones
These four US timezones were implemented in the datetime
documentation and have been reproduced here in boltons for
convenience. More in-depth support is provided by `dateutil`_ and pytz.
- timeutils.Eastern = Eastern
- timeutils.Central = Central
- timeutils.Mountain = Mountain
- timeutils.Pacific = Pacific