ubelt.util_time module¶
This is util_time, it contains functions for handling time related code.
The timestamp()
function returns an iso8601 timestamp without much fuss.
The timeparse()
is the inverse of timestamp, and makes use of
dateutil
if it is available.
The Timer
class is a context manager that times a block of indented
code. It includes tic and toc methods a more matlab like feel.
Timerit is gone! Use the standalone and separate module timerit
.
See also
tempora
- https://github.com/jaraco/tempora - time related utility functions from Jaraco
pendulum
- https://github.com/sdispater/pendulum - drop in replacement for datetime
arrow
- https://github.com/arrow-py/arrow
kwutil.util_time
- https://kwutil.readthedocs.io/en/latest/auto/kwutil.util_time.html
- ubelt.util_time.timestamp(datetime=None, precision=0, default_timezone='local', allow_dateutil=True)[source]¶
Make a concise iso8601 timestamp suitable for use in filenames.
- Parameters:
datetime (datetime.datetime | datetime.date | None) – A datetime to format into a timestamp. If unspecified, the current local time is used. If given as a date, the time 00:00 is used.
precision (int) – if non-zero, adds up to 6 digits of sub-second precision.
default_timezone (str | datetime.timezone) – if the input does not specify a timezone, assume this one. Can be “local” or “utc”, or a standardized code if dateutil is installed.
allow_dateutil (bool) – if True, will use dateutil to lookup the default timezone if needed
- Returns:
The timestamp, which will always contain a date, time, and timezone.
- Return type:
Note
For more info see [WikiISO8601], [PyStrptime], [PyTime].
References
Example
>>> import ubelt as ub >>> stamp = ub.timestamp() >>> print('stamp = {!r}'.format(stamp)) stamp = ...-...-...T...
Example
>>> import ubelt as ub >>> import datetime as datetime_mod >>> from datetime import datetime as datetime_cls >>> # Create a datetime object with timezone information >>> ast_tzinfo = datetime_mod.timezone(datetime_mod.timedelta(hours=-4), 'AST') >>> datetime = datetime_cls.utcfromtimestamp(123456789.123456789).replace(tzinfo=ast_tzinfo) >>> stamp = ub.timestamp(datetime, precision=2) >>> print('stamp = {!r}'.format(stamp)) stamp = '1973-11-29T213309.12-4'
>>> # Demo with a fractional hour timezone >>> act_tzinfo = datetime_mod.timezone(datetime_mod.timedelta(hours=+9.5), 'ACT') >>> datetime = datetime_cls.utcfromtimestamp(123456789.123456789).replace(tzinfo=act_tzinfo) >>> stamp = ub.timestamp(datetime, precision=2) >>> print('stamp = {!r}'.format(stamp)) stamp = '1973-11-29T213309.12+0930'
>>> # Can accept datetime or date objects with local, utc, or custom default timezones >>> act_tzinfo = datetime_mod.timezone(datetime_mod.timedelta(hours=+9.5), 'ACT') >>> datetime_utc = ub.timeparse('2020-03-05T112233', default_timezone='utc') >>> datetime_act = ub.timeparse('2020-03-05T112233', default_timezone=act_tzinfo) >>> datetime_notz = datetime_utc.replace(tzinfo=None) >>> date = datetime_utc.date() >>> stamp_utc = ub.timestamp(datetime_utc) >>> stamp_act = ub.timestamp(datetime_act) >>> stamp_date_utc = ub.timestamp(date, default_timezone='utc') >>> print(f'stamp_utc = {stamp_utc}') >>> print(f'stamp_act = {stamp_act}') >>> print(f'stamp_date_utc = {stamp_date_utc}') stamp_utc = 2020-03-05T112233+0 stamp_act = 2020-03-05T112233+0930 stamp_date_utc = 2020-03-05T000000+0
Example
>>> # xdoctest: +REQUIRES(module:dateutil) >>> # Make sure we are compatible with dateutil >>> import ubelt as ub >>> from dateutil.tz import tzlocal >>> import datetime as datetime_mod >>> from datetime import datetime as datetime_cls >>> tz_act = datetime_mod.timezone(datetime_mod.timedelta(hours=+9.5), 'ACT') >>> tzinfo_list = [ >>> tz_act, >>> datetime_mod.timezone(datetime_mod.timedelta(hours=-4), 'AST'), >>> datetime_mod.timezone(datetime_mod.timedelta(hours=0), 'UTC'), >>> datetime_mod.timezone.utc, >>> None, >>> tzlocal() >>> ] >>> # Note: there is a win32 bug here >>> # https://bugs.python.org/issue37 that means we cant use >>> # dates close to the epoch >>> datetime_list = [ >>> datetime_cls.utcfromtimestamp(123456789.123456789 + 315360000), >>> datetime_cls.utcfromtimestamp(0 + 315360000), >>> ] >>> basis = { >>> 'precision': [0, 3, 9], >>> 'tzinfo': tzinfo_list, >>> 'datetime': datetime_list, >>> 'default_timezone': ['local', 'utc', tz_act], >>> } >>> for params in ub.named_product(basis): >>> dtime = params['datetime'].replace(tzinfo=params['tzinfo']) >>> precision = params.get('precision', 0) >>> stamp = ub.timestamp(datetime=dtime, precision=precision) >>> recon = ub.timeparse(stamp) >>> alt = recon.strftime('%Y-%m-%dT%H%M%S.%f%z') >>> print('---') >>> print('params = {}'.format(ub.repr2(params, nl=1))) >>> print(f'dtime={dtime}') >>> print(f'stamp={stamp}') >>> print(f'recon={recon}') >>> print(f'alt ={alt}') >>> shift = 10 ** precision >>> a = int(dtime.timestamp() * shift) >>> b = int(recon.timestamp() * shift) >>> assert a == b, f'{a} != {b}'
- ubelt.util_time.timeparse(stamp, default_timezone='local', allow_dateutil=True)[source]¶
Create a
datetime.datetime
object from a string timestamp.Without any extra dependencies this will parse the output of
ubelt.util_time.timestamp()
into a datetime object. In the case where the format differs,dateutil.parser.parse()
will be used if thepython-dateutil
package is installed.- Parameters:
stamp (str) – a string encoded timestamp
default_timezone (str) – if the input does not specify a timezone, assume this one. Can be “local” or “utc”.
allow_dateutil (bool) – if False we only use the minimal parsing and do not allow a fallback to dateutil.
- Returns:
the parsed datetime
- Return type:
- Raises:
ValueError – if if parsing fails.
Todo
[ ] Allow defaulting to local or utm timezone (currently default is local)
Example
>>> import ubelt as ub >>> # Demonstrate a round trip of timestamp and timeparse >>> stamp = ub.timestamp() >>> datetime = ub.timeparse(stamp) >>> assert ub.timestamp(datetime) == stamp >>> # Round trip with precision >>> stamp = ub.timestamp(precision=4) >>> datetime = ub.timeparse(stamp) >>> assert ub.timestamp(datetime, precision=4) == stamp
Example
>>> import ubelt as ub >>> # We should always be able to parse these >>> good_stamps = [ >>> '2000-11-22', >>> '2000-11-22T111111.44444Z', >>> '2000-11-22T111111.44444+5', >>> '2000-11-22T111111.44444-05', >>> '2000-11-22T111111.44444-0500', >>> '2000-11-22T111111.44444+0530', >>> '2000-11-22T111111Z', >>> '2000-11-22T111111+5', >>> '2000-11-22T111111+0530', >>> ] >>> for stamp in good_stamps: >>> print(f'----') >>> print(f'stamp={stamp}') >>> result = ub.timeparse(stamp, allow_dateutil=0) >>> print(f'result={result!r}') >>> recon = ub.timestamp(result) >>> print(f'recon={recon}')
Example
>>> import ubelt as ub >>> # We require dateutil to handle these types of stamps >>> import pytest >>> conditional_stamps = [ >>> '2000-01-02T11:23:58.12345+5:30', >>> '09/25/2003', >>> 'Thu Sep 25 10:36:28 2003', >>> ] >>> for stamp in conditional_stamps: >>> with pytest.raises(ValueError): >>> result = ub.timeparse(stamp, allow_dateutil=False) >>> have_dateutil = bool(ub.modname_to_modpath('dateutil')) >>> if have_dateutil: >>> for stamp in conditional_stamps: >>> result = ub.timeparse(stamp)
- class ubelt.util_time.Timer(label='', verbose=None, newline=True, ns=False)[source]¶
Bases:
object
Measures time elapsed between a start and end point. Can be used as a with-statement context manager, or using the tic/toc api.
- Variables:
Example
>>> # Create and start the timer using the context manager >>> import math >>> import ubelt as ub >>> timer = ub.Timer('Timer test!', verbose=1) >>> with timer: >>> math.factorial(10) >>> assert timer.elapsed > 0 tic('Timer test!') ...toc('Timer test!')=...
Example
>>> # Create and start the timer using the tic/toc interface >>> import ubelt as ub >>> timer = ub.Timer().tic() >>> elapsed1 = timer.toc() >>> elapsed2 = timer.toc() >>> elapsed3 = timer.toc() >>> assert elapsed1 <= elapsed2 >>> assert elapsed2 <= elapsed3
Example
>>> # In Python 3.7+ nanosecond resolution can be enabled >>> import ubelt as ub >>> import sys >>> if sys.version_info[0:2] <= (3, 6): >>> import pytest >>> pytest.skip() >>> # xdoctest +REQUIRES(Python>=3.7) # fixme directive doesnt exist yet >>> timer = ub.Timer(label='perf_counter_ns', ns=True).tic() >>> elapsed1 = timer.toc() >>> elapsed2 = timer.toc() >>> assert elapsed1 <= elapsed2 >>> assert isinstance(elapsed1, int)
- Parameters:
label (str) – identifier for printing. Default to ‘’.
verbose (int | None) – verbosity flag, defaults to True if label is given, otherwise 0.
newline (bool) – if False and verbose, print tic and toc on the same line. Defaults to True.
ns (bool) – if True, a nano-second resolution timer to avoid precision loss caused by the float type. Defaults to False.
- _default_time()¶
perf_counter() -> float
Performance counter for benchmarking.