# -*- coding: utf-8 -*-
"""
TODO: This file seems to care about timezone
TODO: Use UTC/GMT time here for EVERYTHING
References:
http://www.timeanddate.com/time/aboututc.html
"""
from __future__ import absolute_import, division, print_function
import sys
import six
import time
import calendar
import datetime
from utool import util_inject
from utool import util_cplat
from utool import util_arg
print, rrr, profile = util_inject.inject2(__name__)
print_ = util_inject.make_module_write_func(__name__)
if util_cplat.WIN32:
# Use time.clock in win32
default_timer = time.clock
else:
default_timer = time.time
# --- Timing ---
[docs]def tic(msg=None):
"""
similar to matlab tic
SeeAlso:
ut.toc
"""
return (msg, default_timer())
[docs]def toc(tt, return_msg=False, write_msg=True, verbose=None):
"""
similar to matlab toc
SeeAlso:
ut.tic
"""
if verbose is not None:
write_msg = verbose
(msg, start_time) = tt
ellapsed = default_timer() - start_time
if (not return_msg) and write_msg and msg is not None:
sys.stdout.write('...toc(%.4fs, ' % ellapsed + '"' + str(msg) + '"' + ')\n')
if return_msg:
return msg
else:
return ellapsed
[docs]def get_timestamp(
format_='iso', use_second=False, delta_seconds=None, isutc=False, timezone=False
):
"""
get_timestamp
Args:
format_ (str): (tag, printable, filename, other)
use_second (bool):
delta_seconds (None):
Returns:
str: stamp
Example:
>>> # ENABLE_DOCTEST
>>> from utool.util_time import * # NOQA
>>> format_ = 'printable'
>>> use_second = False
>>> delta_seconds = None
>>> stamp = get_timestamp(format_, use_second, delta_seconds)
>>> print(stamp)
>>> assert len(stamp) == len('15:43:04 2015/02/24')
"""
# TODO: time.timezone
if format_ == 'int':
if isutc:
stamp = int(time.mktime(time.gmtime()))
else:
stamp = int(time.mktime(time.localtime()))
return stamp
if isutc:
now = datetime.datetime.utcnow()
else:
now = datetime.datetime.now()
if delta_seconds is not None:
now += datetime.timedelta(seconds=delta_seconds)
if format_ == 'iso':
# ISO 8601
# utcnow = datetime.datetime.utcnow()
# utcnow.isoformat()
localOffsetHour = time.timezone // 3600
utc_offset = (
'-' + str(localOffsetHour)
if localOffsetHour < 0
else '+' + str(localOffsetHour)
)
stamp = time.strftime('%Y-%m-%dT%H%M%S') + utc_offset
return stamp
if format_ == 'tag':
time_tup = (now.year - 2000, now.month, now.day)
stamp = '%02d%02d%02d' % time_tup
elif format_ == 'printable':
time_tup = (now.hour, now.minute, now.second, now.year, now.month, now.day)
time_format = '%02d:%02d:%02d %02d/%02d/%02d'
stamp = time_format % time_tup
else:
if use_second:
time_tup = (now.year, now.month, now.day, now.hour, now.minute, now.second)
time_formats = {
'filename': 'ymd_hms-%04d-%02d-%02d_%02d-%02d-%02d',
'comment': '# (yyyy-mm-dd hh:mm:ss) %04d-%02d-%02d %02d:%02d:%02d',
}
else:
time_tup = (now.year, now.month, now.day, now.hour, now.minute)
time_formats = {
'filename': 'ymd_hm-%04d-%02d-%02d_%02d-%02d',
'comment': '# (yyyy-mm-dd hh:mm) %04d-%02d-%02d %02d:%02d',
}
stamp = time_formats[format_] % time_tup
if timezone:
if isutc:
stamp += '_UTC'
else:
from pytz import reference
localtime = reference.LocalTimezone()
tzname = localtime.tzname(now)
stamp += '_' + tzname
return stamp
[docs]def get_datestamp(explicit=True, isutc=False):
if isutc:
now = datetime.datetime.utcnow()
else:
now = datetime.datetime.now()
stamp = '%04d-%02d-%02d' % (now.year, now.month, now.day)
if explicit:
return 'ymd-' + stamp + time.timezone[0]
else:
return stamp
# alias
timestamp = get_timestamp
[docs]class Timer(object):
"""
Timer with-statment context object.
Example:
>>> # ENABLE_DOCTEST
>>> import utool as ut
>>> timer = ut.Timer('Timer test!', verbose=1)
>>> with timer:
>>> prime = ut.get_nth_prime(400)
>>> assert timer.ellapsed > 0
"""
def __init__(self, msg='', verbose=True, newline=True):
self.msg = msg
self.verbose = verbose
self.newline = newline
self.tstart = -1
self.ellapsed = -1
[docs] def tic(self):
if self.verbose:
sys.stdout.flush()
print_('\ntic(%r)' % self.msg)
if self.newline:
print_('\n')
sys.stdout.flush()
self.tstart = default_timer()
[docs] def toc(self):
ellapsed = default_timer() - self.tstart
if self.verbose:
print_('...toc(%r)=%.4fs\n' % (self.msg, ellapsed))
sys.stdout.flush()
return ellapsed
start = tic
stop = toc
def __enter__(self):
self.tic()
return self
def __exit__(self, type_, value, trace):
self.ellapsed = self.toc()
if trace is not None:
return False # return a falsey value on error
[docs]class Timerit(object):
"""
Reports the average time to run a block of code.
Unlike `timeit`, `Timerit` can handle multiline blocks of code
Args:
num (int): number of times to run the loop
label (str): identifier for printing
unit (str): reporting unit of time (e.g. 'ms', 's', None)
CommandLine:
python -m utool.util_time Timerit
python -m utool.util_time Timerit:0
python -m utool.util_time Timerit:1
Notes:
>>> # Minimal syntax with less-precise timing
>>> import utool as ut
>>> for timer in ut.Timerit(100):
>>> # <write code to time here>
>>>
>>> # Full syntax with most-precise timing
>>> import utool as ut
>>> for timer in ut.Timerit(100):
>>> # <write untimed setup code here>
>>> with timer:
>>> # <write code to time here>
>>>
>>> # Can also keep track of the Timerit object for extra statistics
>>> import utool as ut
>>> t1 = ut.Timerit(100)
>>> for timer in t1:
>>> # <write untimed setup code here>
>>> with timer:
>>> # <write code to time here>
>>> # <you can now access Timerit attributes like t1.total_time>
Example:
>>> # ENABLE_DOCTEST
>>> import utool as ut
>>> num = 15
>>> t1 = ut.Timerit(num)
>>> for timer in t1:
>>> # <write untimed setup code here> this example has no setup
>>> with timer:
>>> # <write code to time here> for example...
>>> ut.get_nth_prime_bruteforce(100)
>>> # <you can now access Timerit attributes>
>>> print('t1.total_time = %r' % (t1.total_time,))
>>> assert t1.total_time > 0
>>> assert t1.n_loops == t1.num
>>> assert t1.n_loops == num
Example:
>>> # DISABLE_DOCTEST
>>> import utool as ut
>>> num = 10000
>>> n = 50
>>> # If the timer object is unused, time will still be recoreded,
>>> # but with less precision.
>>> for _ in ut.Timerit(num, 'inprecise'):
>>> ut.get_nth_prime_bruteforce(n)
>>> # Using the timer object results in the most precise timeings
>>> for timer in ut.Timerit(num, 'precise'):
>>> with timer:
>>> ut.get_nth_prime_bruteforce(n)
"""
def __init__(self, num, label=None, unit=None, verbose=1):
self.num = num
self.label = label
self.times = []
self.verbose = verbose
self.total_time = None
self.n_loops = None
self.unit = unit
def __iter__(self):
import utool as ut
if self.verbose > 1:
if self.label is None:
print('Timing for %d loops' % self.num)
else:
print('Timing %s for %d loops.' % (self.label, self.num))
self.n_loops = 0
self.total_time = 0
# Create a foreground and background timer
bg_timer = ut.Timer(verbose=0) # (ideally this is unused)
fg_timer = ut.Timer(verbose=0) # (used directly by user)
# Core timing loop
for i in range(self.num):
# Start background timer (in case the user doesnt use fg_timer)
# Yield foreground timer to let the user run a block of code
# When we return from yield the user code will have just finishec
# Then record background time + loop overhead
bg_timer.tic()
yield fg_timer
bg_time = bg_timer.toc()
# Check if the fg_timer object was used, but fallback on bg_timer
if fg_timer.ellapsed >= 0:
block_time = fg_timer.ellapsed # high precision
else:
block_time = bg_time # low precision
# record timeings
self.times.append(block_time)
self.total_time += block_time
self.n_loops += 1
# Timeing complete, print results
assert len(self.times) == self.num, 'incorrectly recorded times'
if self.verbose > 0:
self._print_report(self.verbose)
@property
def ave_secs(self):
return self.total_time / self.n_loops
def _print_report(self, verbose=1):
import utool as ut
ave_secs = self.ave_secs
if self.label is None:
print('Timing complete, %d loops' % (self.n_loops,))
else:
print('Timing complete for: %s, %d loops' % (self.label, self.n_loops))
if verbose > 2:
body = ut.second_str(self.total_time, unit=self.unit, precision=4)
print(' body took: %s' % body)
perloop = ut.second_str(ave_secs, unit=self.unit, precision=4)
print(' time per loop : %s' % (perloop,))
[docs]def local_timezone():
import time
return time.tzname
[docs]def utcnow_tz():
import pytz
dt = datetime.datetime.utcnow()
dt = dt.replace(tzinfo=pytz.timezone('UTC'))
return dt
[docs]def parse_timestamp(timestamp, zone='UTC', timestamp_format=None):
r"""
pip install delorean
Args:
timestamp (str): timestampe string
zone (bool): assumes input is zone (only if not specified) and gives
output in zone.
CommandLine:
python -m utool.util_time --test-parse_timestamp
python -m utool.util_time parse_timestamp
Example:
>>> # ENABLE_DOCTEST
>>> from utool.util_time import * # NOQA
>>> import utool as ut
>>> utc = True
>>> timestampe_format = None
>>> timestamps = [
>>> ('2015:04:01 00:00:00',),
>>> ('2005-10-27T14:35:20+02:00',),
>>> ('2000-01-01T09:00:00-05:00', 'UTC'),
>>> ('2000-01-01T09:00:00-05:00', 'EST'),
>>> ('2000-01-01T09:00:00', 'EST'),
>>> ('2000-01-01T09:00:00', 'UTC'),
>>> ('6:35:01\x002006:03:19 1',),
>>> ('2016/08/18 10:51:02 EST',),
>>> ('2016-08-18T10:51:02-05:00',),
>>> ]
>>> timestamp = timestamps[-1][0]
>>> dn_list = [parse_timestamp(*args) for args in timestamps]
>>> result = ut.NEWLINE.join([str(dn) for dn in dn_list])
>>> print(result)
2015-04-01 00:00:00+00:00
2005-10-27 12:35:20+00:00
2000-01-01 14:00:00+00:00
2000-01-01 09:00:00-05:00
2000-01-01 09:00:00-05:00
2000-01-01 09:00:00+00:00
2006-03-19 06:35:01+00:00
2016-08-18 15:51:02+00:00
2016-08-18 15:51:02+00:00
"""
if timestamp is None:
return None
use_delorean = True or six.PY2
if use_delorean:
import delorean
# # customize delorean string method
# def __str__(self):
# return str(self.datetime)
# #return str(self.datetime) + ' ' + str(self.timezone)
# delorean.Delorean.__str__ = __str__
# # method types must be injected into the class
# #ut.inject_func_as_method(dn, __str__, '__repr__', override=True)
if not isinstance(timestamp, six.string_types):
raise NotImplementedError('Unknown format: timestamp=%r' % (timestamp,))
# Normal format, or non-standard year first data
if timestamp_format is None:
# dont warn because we will take care of utc
timefmt = determine_timestamp_format(timestamp, warn=False)
else:
timefmt = timestamp_format
if timefmt is None or not isinstance(timefmt, six.string_types):
raise AssertionError('unknown timestamp_format=%r' % (timestamp_format,))
# Fixup timestamp
utc_offset = None
if len(timestamp) == 20 and '\x00' in timestamp:
timestamp_ = timestamp.replace('\x00', ' ').strip(';').strip()
elif use_delorean and len(timestamp) > 19:
timestamp_ = timestamp[:19].strip(';').strip()
utc_offset = timestamp[19:]
else:
timestamp_ = timestamp
dt_ = datetime.datetime.strptime(timestamp_, timefmt)
if use_delorean:
# if utc and utc_offset is not None:
# if utc:
# dn_ = delorean.Delorean(dt_, 'UTC')
# else:
if zone is None:
zone = time.tzname[0]
if zone == 'local':
zone = time.tzname[0]
dn_ = delorean.Delorean(dt_, zone)
else:
dn_ = dt_
if utc_offset is not None and zone == 'UTC':
if use_delorean:
# Python 2.7 does not account for timezones
if ':' in utc_offset:
sign = {' ': +1, '+': +1, '-': -1}[utc_offset[0]]
hours, seconds = utc_offset[1:].split(':')
delta_ = datetime.timedelta(hours=int(hours), seconds=int(seconds))
delta = sign * delta_
else:
import pytz
tzname = utc_offset.strip()
delta = pytz.timezone(tzname).utcoffset(dt_)
# Move back to utc
dn = dn_ - delta
else:
raise AssertionError('python3 should take care of timezone')
else:
dn = dn_
if use_delorean:
if not zone != 'UTC':
dn.shift(zone)
return dn.datetime
# return dn
[docs]def exiftime_to_unixtime(datetime_str, timestamp_format=None, strict=None):
r"""
converts a datetime string to posixtime (unixtime)
Use parse timestamp instead
Args:
datetime_str (str):
timestamp_format (int):
Returns:
int: unixtime seconds from 1970 (currently not UTC; this will change)
CommandLine:
python -m utool.util_time --test-exiftime_to_unixtime:2
Example:
>>> # ENABLE_DOCTEST
>>> from utool.util_time import * # NOQA
>>> datetime_str = '0000:00:00 00:00:00'
>>> timestamp_format = 1
>>> result = exiftime_to_unixtime(datetime_str, timestamp_format)
>>> print(result)
-1
Example:
>>> # ENABLE_DOCTEST
>>> from utool.util_time import * # NOQA
>>> datetime_str = '2015:04:01 00:00:00'
>>> timestamp_format = 1
>>> result = exiftime_to_unixtime(datetime_str, timestamp_format)
>>> print(result)
1427846400
Example:
>>> # ENABLE_DOCTEST
>>> from utool.util_time import * # NOQA
>>> datetime_str = '2005-10-27T14:35:20+02:00'
>>> timestamp_format = None
>>> result = exiftime_to_unixtime(datetime_str, timestamp_format)
>>> print(result)
1130423720
Example:
>>> # ENABLE_DOCTEST
>>> from utool.util_time import * # NOQA
>>> datetime_str = '6:35:01\x002006:03:19 1'
>>> timestamp_format = None
>>> result = exiftime_to_unixtime(datetime_str, timestamp_format)
>>> print(result)
1142750101
"""
invalid_value = -1
if isinstance(datetime_str, int):
if datetime_str == -1:
return invalid_value
elif datetime_str is None:
return None
# TODO: use parse_timestamp to reduce duplicate code
# try:
# dt = parse_timestamp(datetime_str)
# except TypeError:
# #if datetime_str is None:
# #return -1
# return -1
# except ValueError as ex:
# if strict is None:
# ...
if not isinstance(datetime_str, six.string_types):
raise NotImplementedError('Unknown format: datetime_str=%r' % (datetime_str,))
# Normal format, or non-standard year first data
if timestamp_format is None:
timefmt = determine_timestamp_format(datetime_str)
if timefmt is None:
return invalid_value
elif timestamp_format == 2:
timefmt = '%m/%d/%Y %H:%M:%S'
elif timestamp_format == 1:
timefmt = '%Y:%m:%d %H:%M:%S'
else:
assert isinstance(timestamp_format, six.string_types)
timefmt = timestamp_format
# raise AssertionError('unknown timestamp_format=%r' % (timestamp_format,))
try:
if len(datetime_str) == 20 and '\x00' in datetime_str:
datetime_str_ = datetime_str.replace('\x00', ' ').strip(';').strip()
elif len(datetime_str) > 19:
datetime_str_ = datetime_str[:19].strip(';').strip()
else:
datetime_str_ = datetime_str
# try:
dt = datetime.datetime.strptime(datetime_str_, timefmt)
# except ValueError as ex:
# import utool as ut
# ut.printex(ex, iswarning=True)
# return invalid_value
return calendar.timegm(dt.timetuple())
# return time.mktime(dt.timetuple())
except TypeError:
# if datetime_str is None:
# return -1
return -1
except ValueError as ex:
if strict is None:
strict = util_arg.SUPER_STRICT
# strict = False
# from utool.util_arg import STRICT
if isinstance(datetime_str, six.string_types):
if len(datetime_str_.strip()) == 0:
return invalid_value
if datetime_str_.find('No EXIF Data') == 0:
return invalid_value
if datetime_str_.find('Invalid') == 0:
return invalid_value
if datetime_str_ == '0000:00:00 00:00:00':
return invalid_value
print('<!!! ValueError !!!>')
print('[util_time] Caught Error: ' + repr(ex))
print('[util_time] type(datetime_str) = %r' % type(datetime_str))
print('[util_time] repr(datetime_str) = %r' % datetime_str)
print('[util_time] (datetime_str) = %s' % datetime_str)
print('[util_time] len(datetime_str) = %d' % len(datetime_str))
print('[util_time] repr(datetime_str_) = %r' % datetime_str_)
print('[util_time] len(datetime_str_) = %d' % len(datetime_str_))
print('</!!! ValueError !!!>')
debug = True
if debug:
def find_offending_part(datetime_str_, timefmt, splitchar=' '):
import utool as ut
parts_list = datetime_str_.split(splitchar)
fmt_list = timefmt.split(splitchar)
if len(parts_list) == 1:
return
for part, fmt in zip(parts_list, fmt_list):
print('Trying:')
with ut.Indenter(' '):
try:
print('fmt = %r' % (fmt,))
print('part = %r' % (part,))
datetime.datetime.strptime(part, fmt)
except ValueError:
find_offending_part(part, fmt, '/')
print('Failed')
else:
print('Passed')
find_offending_part(datetime_str_, timefmt)
# import utool as ut
# ut.embed()
if strict:
raise
else:
print('Supressed ValueError')
return invalid_value
[docs]def parse_timedelta_str(str_):
r"""
Args:
str_ (str):
Returns:
float: timedelta
CommandLine:
python -m utool.util_time --exec-parse_timedelta_str
Example:
>>> # ENABLE_DOCTEST
>>> from utool.util_time import * # NOQA
>>> str_ = '24h'
>>> timedelta = parse_timedelta_str(str_)
>>> result = ('timedelta = %s' % (str(timedelta),))
>>> print(result)
timedelta = 86400.0
"""
if str_.endswith('m'):
timedelta = float(str_[0:-1]) * 60
elif str_.endswith('h'):
timedelta = float(str_[0:-1]) * 60 * 60
elif str_.endswith('s'):
timedelta = float(str_[0:-1])
else:
raise NotImplementedError('Unknown timedelta format %r' % (str_))
return timedelta
[docs]def ensure_timedelta(str_or_num):
if isinstance(str_or_num, six.string_types):
return parse_timedelta_str(str_or_num)
else:
return str_or_num
[docs]def unixtime_to_datetimestr(unixtime, timefmt='%Y/%m/%d %H:%M:%S', isutc=True):
"""
TODO: ranme to datetimestr
"""
try:
unixtime = int(unixtime)
if unixtime == -1:
return 'NA'
if unixtime is None:
return None
if isutc:
return datetime.datetime.utcfromtimestamp(unixtime).strftime(timefmt)
else:
return datetime.datetime.fromtimestamp(unixtime).strftime(timefmt)
except ValueError:
raise
# return 'NA'
[docs]def unixtime_to_datetimeobj(unixtime, isutc=True):
try:
if unixtime == -1:
return 'NA'
if unixtime is None:
return None
if isutc:
return datetime.datetime.utcfromtimestamp(unixtime)
else:
return datetime.datetime.fromtimestamp(unixtime)
except ValueError:
raise
[docs]def unixtime_to_timedelta(unixtime_diff):
"""alias for get_unix_timedelta"""
return get_unix_timedelta(unixtime_diff)
[docs]def get_unix_timedelta(unixtime_diff):
timedelta = datetime.timedelta(seconds=abs(unixtime_diff))
return timedelta
[docs]def get_unix_timedelta_str(unixtime_diff):
"""
TODO: rectify this function with get_posix_timedelta_str
Args:
unixtime_diff (int): number of seconds
Returns:
timestr (str): formated time string
Args:
unixtime_diff (int):
Returns:
str: timestr
CommandLine:
python -m utool.util_time --test-get_unix_timedelta_str
Example:
>>> # ENABLE_DOCTEST
>>> from utool.util_time import * # NOQA
>>> import utool as ut
>>> unixtime_diff = 0
>>> timestr = get_unix_timedelta_str(unixtime_diff)
>>> timestr_list = [get_unix_timedelta_str(_) for _ in [-9001, -1, 0, 1, 9001]]
>>> result = ut.repr2(timestr_list)
>>> print(result)
['2 hours 30 minutes 1 second', '1 second', '0 seconds', '1 second', '2 hours 30 minutes 1 second']
"""
timedelta = get_unix_timedelta(unixtime_diff)
timestr = get_timedelta_str(timedelta)
return timestr
[docs]def get_timedelta_str(timedelta, exclude_zeros=False):
"""
get_timedelta_str
Returns:
str: timedelta_str, formated time string
References:
http://stackoverflow.com/questions/8906926/formatting-python-timedelta-objects
Example:
>>> # ENABLE_DOCTEST
>>> from utool.util_time import * # NOQA
>>> timedelta = get_unix_timedelta(10)
>>> timedelta_str = get_timedelta_str(timedelta)
>>> result = (timedelta_str)
>>> print(result)
10 seconds
"""
if timedelta == datetime.timedelta(0):
return '0 seconds'
days = timedelta.days
hours, rem = divmod(timedelta.seconds, 3600)
minutes, seconds = divmod(rem, 60)
fmtstr_list = []
fmtdict = {}
def append_cases(unit, fmtlbl):
if not exclude_zeros or unit != 0:
if unit == 1:
fmtstr_list.append('{%s} %s' % (fmtlbl, fmtlbl))
else:
fmtstr_list.append('{%s} %ss' % (fmtlbl, fmtlbl))
fmtdict[fmtlbl] = unit
if abs(days) > 0:
append_cases(days, 'day')
if len(fmtstr_list) > 0 or abs(hours) > 0:
append_cases(hours, 'hour')
if len(fmtstr_list) > 0 or abs(minutes) > 0:
append_cases(minutes, 'minute')
if len(fmtstr_list) > 0 or abs(seconds) > 0:
append_cases(seconds, 'second')
fmtstr = ' '.join(fmtstr_list)
timedelta_str = fmtstr.format(**fmtdict)
return timedelta_str
[docs]def get_posix_timedelta_str(posixtime, year=False, approx=True):
"""
get_timedelta_str
TODO: rectify this function with get_unix_timedelta_str (unix_timedelta_str probably has better implementation)
Returns:
str: timedelta_str, formated time string
CommandLine:
python -m utool.util_time --test-get_posix_timedelta_str
Example:
>>> # ENABLE_DOCTEST
>>> from utool.util_time import * # NOQA
>>> import utool as ut
>>> posixtime_list = [-13, 10.2, 10.2 ** 2, 10.2 ** 3, 10.2 ** 4, 10.2 ** 5, 10.2 ** 8, 60 * 60 * 60 * 24 * 7]
>>> posixtime = posixtime_list[-1]
>>> timedelta_str = [get_posix_timedelta_str(posixtime) for posixtime in posixtime_list]
>>> result = ut.repr2(timedelta_str)
>>> print(result)
['-00:00:13', '00:00:10', '00:01:44', '00:17:41', '03:00:24', '1 day', '193 weeks', '60 weeks']
Timeit:
import datetime
# Seems like like timedelta is just faster. must be because it is builtin
%timeit get_posix_timedelta_str(posixtime)
%timeit str(datetime.timedelta(seconds=posixtime))
"""
import numpy as np
if np.isnan(posixtime):
return 'NaN'
sign, posixtime_ = (1, posixtime) if posixtime >= 0 else (-1, -posixtime)
seconds_, subseconds = divmod(posixtime_, 1)
minutes_, seconds = divmod(int(seconds_), 60)
hours_, minutes = divmod(minutes_, 60)
days_, hours = divmod(hours_, 24)
weeks_, days = divmod(days_, 7)
if year:
years, weeks = divmod(weeks_, 52) # not accurate
else:
years = 0
weeks = weeks_
timedelta_parts = []
if subseconds > 0:
timedelta_parts += [('%.2f' % (subseconds,))[1:]]
timedelta_parts += [':'.join(['%02d' % _ for _ in (hours, minutes, seconds)])]
import utool as ut
if days > 0:
timedelta_parts += ['%d %s ' % (days, ut.pluralize('day', days))]
if weeks > 0:
timedelta_parts += ['%d %s ' % (weeks, ut.pluralize('week', weeks))]
if years > 0:
timedelta_parts += ['%d %s ' % (years, ut.pluralize('year', years))]
if sign == -1:
timedelta_parts += ['-']
else:
timedelta_parts += ['']
if approx is not False:
if approx is True:
approx = 1
timedelta_str = ''.join(timedelta_parts[::-1][0 : (approx + 1)]).strip()
else:
timedelta_str = ''.join(timedelta_parts[::-1])
return timedelta_str
[docs]def get_posix_timedelta_str2(posixtime):
try:
return get_posix_timedelta_str(posixtime)
except ValueError:
# handle nones and nans
return 'None'
# def get_simple_posix_timedelta_str(posixtime):
# """
# get_timedelta_str
# Returns:
# str: timedelta_str, formated time string
# CommandLine:
# python -m utool.util_time --test-get_posix_timedelta_str
# Example:
# >>> # ENABLE_DOCTEST
# >>> from utool.util_time import * # NOQA
# >>> posixtime_list = [13, 10.2, 10.2 ** 2, 10.2 ** 3, 10.2 ** 4, 10.2 ** 5, 10.2 ** 8]
# >>> posixtime = posixtime_list[1]
# >>> timedelta_str = [get_simple_posix_timedelta_str(posixtime) for posixtime in posixtime_list]
# >>> result = (timedelta_str)
# >>> print(result)
# Timeit:
# import datetime
# posixtime = 10.2 ** 8
# %timeit get_simple_posix_timedelta_str(posixtime)
# %timeit str(datetime.timedelta(seconds=posixtime))
# """
# seconds_ = int(posixtime)
# minutes_, seconds = divmod(seconds_, 60)
# hours_, minutes = divmod(minutes_, 60)
# days_, hours = divmod(hours_, 24)
# weeks_, days = divmod(days_, 7)
# timedelta_str = ':'.join(['%02d' % _ for _ in (hours, minutes, seconds)])
# #if days_ > 0:
# # timedelta_str = '%d days ' % (days,) + timedelta_str
# #if weeks_ > 0:
# # timedelta_str = '%d weeks ' % (weeks_,) + timedelta_str
# return timedelta_str
# def get_month():
# return datetime.datetime.now().month
# def get_day():
# return datetime.datetime.now().day
# def get_year():
# return datetime.datetime.now().year
[docs]def get_timestats_str(unixtime_list, newlines=1, full=True, isutc=True):
r"""
Args:
unixtime_list (list):
newlines (bool):
Returns:
str: timestat_str
CommandLine:
python -m utool.util_time --test-get_timestats_str
Example:
>>> # ENABLE_DOCTEST
>>> from utool.util_time import * # NOQA
>>> import utool as ut
>>> unixtime_list = [0, 0 + 60 * 60 * 5 , 10 + 60 * 60 * 5, 100 + 60 * 60 * 5, 1000 + 60 * 60 * 5]
>>> newlines = 1
>>> full = False
>>> timestat_str = get_timestats_str(unixtime_list, newlines, full=full, isutc=True)
>>> result = ut.align(str(timestat_str), ':')
>>> print(result)
{
'max' : '1970/01/01 05:16:40',
'mean' : '1970/01/01 04:03:42',
'min' : '1970/01/01 00:00:00',
'range': '5:16:40',
'std' : '2:02:01',
}
Example:
>>> # ENABLE_DOCTEST
>>> from utool.util_time import * # NOQA
>>> import utool as ut
>>> unixtime_list = [0, 0 + 60 * 60 * 5 , 10 + 60 * 60 * 5, 100 + 60 * 60 * 5, 1000 + 60 * 60 * 5, float('nan'), 0]
>>> newlines = 1
>>> timestat_str = get_timestats_str(unixtime_list, newlines, isutc=True)
>>> result = ut.align(str(timestat_str), ':')
>>> print(result)
{
'max' : '1970/01/01 05:16:40',
'mean' : '1970/01/01 03:23:05',
'min' : '1970/01/01 00:00:00',
'nMax' : 1,
'nMin' : 2,
'num_nan': 1,
'range' : '5:16:40',
'shape' : (7,),
'std' : '2:23:43',
}
"""
import utool as ut
datetime_stats = get_timestats_dict(unixtime_list, full=full, isutc=isutc)
timestat_str = ut.repr4(datetime_stats, newlines=newlines)
return timestat_str
[docs]def get_timestats_dict(unixtime_list, full=True, isutc=True):
import utool as ut
unixtime_stats = ut.get_stats(unixtime_list, use_nan=True)
datetime_stats = {}
if unixtime_stats.get('empty_list', False):
datetime_stats = unixtime_stats
return datetime_stats
# elif unixtime_stats.get('num_nan', 0) == unixtime_stats.get('shape')[0]:
# datetime_stats = unixtime_stats
# return datetime_stats
for key in ['max', 'min', 'mean']:
try:
datetime_stats[key] = ut.unixtime_to_datetimestr(
unixtime_stats[key], isutc=isutc
)
except KeyError:
pass
except (ValueError, OSError):
datetime_stats[key] = 'NA'
except Exception as ex:
ut.printex(ex, keys=['key', 'unixtime_stats'])
raise
for key in ['std']:
try:
datetime_stats[key] = str(
ut.get_unix_timedelta(int(round(unixtime_stats[key])))
)
except KeyError:
pass
except (ValueError, OSError):
datetime_stats[key] = 'NA'
try:
datetime_stats['range'] = str(
ut.get_unix_timedelta(
int(round(unixtime_stats['max'] - unixtime_stats['min']))
)
)
except KeyError:
pass
except (ValueError, OSError):
datetime_stats['range'] = 'NA'
if full:
# unused_keys = (set(unixtime_stats.keys()) - set(datetime_stats.keys())
for key in ['nMax', 'num_nan', 'shape', 'nMin']:
datetime_stats[key] = unixtime_stats[key]
# print('Unused keys = %r' % (set(unixtime_stats.keys()) - set(datetime_stats.keys()),))
return datetime_stats
[docs]def date_to_datetime(date, fraction=0.0):
"""
fraction is how much through the day you are. 0=start of the day, 1=end of the day.
"""
day_seconds = (60 * 60 * 24) - 1
total_seconds = int(day_seconds * fraction)
delta = datetime.timedelta(seconds=total_seconds)
time = datetime.time()
dt = datetime.datetime.combine(date, time) + delta
return dt
[docs]def datetime_to_posixtime(dt):
posixtime = time.mktime(dt.timetuple())
return posixtime
# def datetime_to_posixtime(dt):
# return dt.toordinal()
if __name__ == '__main__':
"""
CommandLine:
python -c "import utool, utool.util_time; utool.doctest_funcs(utool.util_time, allexamples=True)"
python -c "import utool, utool.util_time; utool.doctest_funcs(utool.util_time)"
python -m utool.util_time
python -m utool.util_time --allexamples
"""
import multiprocessing
multiprocessing.freeze_support() # for win32
import utool as ut # NOQA
ut.doctest_funcs()