18 from datetime
import timedelta
20 from .normalizing
import normalize
21 from .misc
import plural_or_not
22 from .robottypes
import is_number, is_string
28 _timer_re = re.compile(
r'^([+-])?(\d+:)?(\d+):(\d+)(\.\d+)?$')
32 if epoch_secs
is None:
33 epoch_secs = time.time()
35 timetuple = time.localtime(secs)[:6]
36 return timetuple + (millis,)
41 millis = round((secs - isecs) * 1000)
42 return (isecs, millis)
if millis < 1000
else (isecs+1, 0)
57 if accept_plain_values:
58 converters = [_number_to_secs, _timer_to_secs, _time_string_to_secs]
60 converters = [_timer_to_secs, _time_string_to_secs]
61 for converter
in converters:
62 secs = converter(timestr)
64 return secs
if round_to
is None else round(secs, round_to)
65 if isinstance(timestr, timedelta):
66 return timestr.total_seconds()
67 raise ValueError(
"Invalid time string '%s'." % timestr)
78 match = _timer_re.match(number)
81 prefix, hours, minutes, seconds, millis = match.groups()
82 seconds = float(minutes) * 60 + float(seconds)
84 seconds += float(hours[:-1]) * 60 * 60
86 seconds += float(millis[1:]) / 10**len(millis[1:])
96 nanos = micros = millis = secs = mins = hours = days = 0
105 if c ==
'n': nanos = float(
''.join(temp)); temp = []
106 elif c ==
'u': micros = float(
''.join(temp)); temp = []
107 elif c ==
'x': millis = float(
''.join(temp)); temp = []
108 elif c ==
's': secs = float(
''.join(temp)); temp = []
109 elif c ==
'm': mins = float(
''.join(temp)); temp = []
110 elif c ==
'h': hours = float(
''.join(temp)); temp = []
111 elif c ==
'd': days = float(
''.join(temp)); temp = []
117 return sign * (nanos/1E9 + micros/1E6 + millis/1000 + secs +
118 mins*60 + hours*60*60 + days*60*60*24)
123 for specifier, aliases
in [(
'n', [
'nanosecond',
'ns']),
124 (
'u', [
'microsecond',
'us',
'μs']),
125 (
'x', [
'millisecond',
'millisec',
'millis',
127 (
's', [
'second',
'sec']),
128 (
'm', [
'minute',
'min']),
131 plural_aliases = [a+
's' for a
in aliases
if not a.endswith(
's')]
132 for alias
in plural_aliases + aliases:
134 timestr = timestr.replace(alias, specifier)
160 self._sign, millis, secs, mins, hours, days \
162 self.
_add_item_add_item(days,
'd',
'day')
163 self.
_add_item_add_item(hours,
'h',
'hour')
164 self.
_add_item_add_item(mins,
'min',
'minute')
165 self.
_add_item_add_item(secs,
's',
'second')
166 self.
_add_item_add_item(millis,
'ms',
'millisecond')
169 if len(self.
_ret_ret) > 0:
170 return self._sign +
' '.join(self.
_ret_ret)
171 return '0s' if self.
_compact_compact
else '0 seconds'
173 def _add_item(self, value, compact_suffix, long_suffix):
177 suffix = compact_suffix
180 self.
_ret_ret.append(
'%d%s' % (value, suffix))
185 float_secs = abs(float_secs)
190 mins = int_secs // 60 % 60
191 hours = int_secs // (60 * 60) % 24
192 days = int_secs // (60 * 60 * 24)
193 return sign, millis, secs, mins, hours, days
207 def format_time(timetuple_or_epochsecs, daysep='', daytimesep=' ', timesep=':
',
212 timetuple = timetuple_or_epochsecs
213 daytimeparts = [
'%02d' % t
for t
in timetuple[:6]]
214 day = daysep.join(daytimeparts[:3])
215 time_ = timesep.join(daytimeparts[3:6])
216 millis = millissep
and '%s%03d' % (millissep, timetuple[6])
or ''
217 return day + daytimesep + time_ + millis
237 time_ = int(time.time()
if time_
is None else time_)
238 format = format.lower()
240 if 'epoch' in format:
242 timetuple = time.localtime(time_)
244 for i, match
in enumerate(
'year month day hour min sec'.split()):
246 parts.append(
'%.2d' % timetuple[i])
251 elif len(parts) == 1:
272 for method
in [_parse_time_epoch,
273 _parse_time_timestamp,
274 _parse_time_now_and_utc]:
275 seconds = method(timestr)
276 if seconds
is not None:
278 raise ValueError(
"Invalid time format '%s'." % timestr)
287 raise ValueError(
"Epoch time must be positive (got %s)." % timestr)
299 timestr = timestr.replace(
' ',
'').lower()
303 if extra
is not None:
313 zone = time.altzone
if time.localtime().tm_isdst
else time.timezone
321 if extra[0]
not in [
'+',
'-']:
327 time1_is_dst = time.localtime(time1).tm_isdst
328 time2_is_dst = time.localtime(time2).tm_isdst
329 if time1_is_dst
is time2_is_dst:
331 difference = time.timezone - time.altzone
332 return difference
if time1_is_dst
else -difference
336 return TIMESTAMP_CACHE.get_timestamp(daysep, daytimesep, timesep, millissep)
342 except (ValueError, OverflowError):
343 raise ValueError(
"Invalid timestamp '%s'." % timestamp)
345 return round(secs, 3)
350 seps = (
'',
' ',
':',
'.' if millis
else None)
351 ttuple = time.localtime(secs)[:6]
353 millis = (secs - int(secs)) * 1000
354 ttuple = ttuple + (round(millis),)
360 if start_time == end_time
or not (start_time
and end_time):
362 if start_time[:-4] == end_time[:-4]:
363 return int(end_time[-3:]) - int(start_time[-3:])
367 return int(end_millis - start_millis)
378 elapsed = abs(elapsed)
385 secs, millis = divmod(round(elapsed), 1000)
386 mins, secs = divmod(secs, 60)
387 hours, mins = divmod(mins, 60)
388 return '%02d:%02d:%02d.%03d' % (hours, mins, secs, millis)
392 secs = round(elapsed, ndigits=-3) // 1000
393 mins, secs = divmod(secs, 60)
394 hours, mins = divmod(mins, 60)
395 return '%02d:%02d:%02d' % (hours, mins, secs)
402 secs = time.mktime((Y, M, D, h, m, s, 0, 0, -1))
403 return round(1000*secs + millis)
409 ts = ts.replace(sep,
'')
410 ts = ts.ljust(17,
'0')
411 return f
'{ts[:8]} {ts[8:10]}:{ts[10:12]}:{ts[12:14]}.{ts[14:17]}'
415 years = int(timestamp[:4])
416 mons = int(timestamp[4:6])
417 days = int(timestamp[6:8])
418 hours = int(timestamp[9:11])
419 mins = int(timestamp[12:14])
420 secs = int(timestamp[15:17])
421 millis = int(timestamp[18:21])
422 return years, mons, days, hours, mins, secs, millis
432 def get_timestamp(self, daysep='', daytimesep=' ', timesep=':
', millissep='.
'):
435 if self.
_use_cache_use_cache(secs, daysep, daytimesep, timesep):
437 timestamp =
format_time(epoch, daysep, daytimesep, timesep, millissep)
438 self.
_cache_timestamp_cache_timestamp(secs, timestamp, daysep, daytimesep, timesep, millissep)
def get_timestamp(self, daysep='', daytimesep=' ', timesep=':', millissep='.')
def _use_cache(self, secs, *separators)
def _cached_timestamp(self, millis, millissep)
def _cache_timestamp(self, secs, timestamp, daysep, daytimesep, timesep, millissep)
def _add_item(self, value, compact_suffix, long_suffix)
def __init__(self, float_secs, compact)
def _secs_to_components(self, float_secs)
def normalize(string, ignore=(), caseless=True, spaceless=True)
Normalizes given string according to given spec.
def get_time(format='timestamp', time_=None)
Return the given or current time in requested format.
def _normalize_timestr(timestr)
def _parse_time_epoch(timestr)
def _timer_to_secs(number)
def _elapsed_time_to_string(elapsed)
def _time_string_to_secs(timestr)
def format_time(timetuple_or_epochsecs, daysep='', daytimesep=' ', timesep=':', millissep=None)
Returns a timestamp formatted from given time using separators.
def get_elapsed_time(start_time, end_time)
Returns the time between given timestamps in milliseconds.
def _parse_time_now_and_utc(timestr)
def get_timestamp(daysep='', daytimesep=' ', timesep=':', millissep='.')
def _normalize_timestamp(ts, seps)
def _timestamp_to_millis(timestamp, seps=None)
def _split_timestamp(timestamp)
def secs_to_timestamp(secs, seps=None, millis=False)
def timestamp_to_secs(timestamp, seps=None)
def _parse_time_now_and_utc_base(base)
def _get_dst_difference(time1, time2)
def _float_secs_to_secs_and_millis(secs)
def _elapsed_time_to_string_without_millis(elapsed)
def secs_to_timestr(secs, compact=False)
Converts time in seconds to a string representation.
def _get_timetuple(epoch_secs=None)
def parse_time(timestr)
Parses the time string and returns its value as seconds since epoch.
def timestr_to_secs(timestr, round_to=3, accept_plain_values=True)
Parses time strings like '1h 10s', '01:00:10' and '42' and returns seconds.
def _parse_time_timestamp(timestr)
def _number_to_secs(number)
def _parse_time_now_and_utc_extra(extra)
def elapsed_time_to_string(elapsed, include_millis=True)
Converts elapsed time in milliseconds to format 'hh:mm:ss.mil'.