""" Time formatting utilities. ISO-8601: http://www.cl.cam.ac.uk/~mgk25/iso-time.html """ import calendar, datetime, re, time from typing import Optional def format_time(t): return time.strftime("%Y-%m-%d %H:%M:%S", t) def iso_utc_date( now: Optional[float] = None, t=time.time ) -> str: if now is None: now = t() return datetime.datetime.utcfromtimestamp(now).isoformat()[:10] def iso_utc( now: Optional[float] = None, sep: str = '_', t=time.time ) -> str: if now is None: now = t() sep = str(sep) # should already be a str return datetime.datetime.utcfromtimestamp(now).isoformat(sep) def iso_utc_time_to_seconds(isotime, _conversion_re=re.compile(r"(?P\d{4})-(?P\d{2})-(?P\d{2})[T_ ](?P\d{2}):(?P\d{2}):(?P\d{2})(?P\.\d+)?")): """ The inverse of iso_utc(). Real ISO-8601 is "2003-01-08T06:30:59". We also accept the widely used variants "2003-01-08_06:30:59" and "2003-01-08 06:30:59". """ m = _conversion_re.match(isotime) if not m: raise ValueError(isotime, "not a complete ISO8601 timestamp") year, month, day = int(m.group('year')), int(m.group('month')), int(m.group('day')) hour, minute, second = int(m.group('hour')), int(m.group('minute')), int(m.group('second')) subsecstr = m.group('subsecond') if subsecstr: subsecfloat = float(subsecstr) else: subsecfloat = 0 return calendar.timegm( (year, month, day, hour, minute, second, 0, 1, 0) ) + subsecfloat def parse_duration(s): orig = s unit = None DAY = 24*60*60 MONTH = 31*DAY YEAR = 365*DAY if s.endswith("s"): s = s[:-1] if s.endswith("day"): unit = DAY s = s[:-len("day")] elif s.endswith("month"): unit = MONTH s = s[:-len("month")] elif s.endswith("mo"): unit = MONTH s = s[:-len("mo")] elif s.endswith("year"): unit = YEAR s = s[:-len("YEAR")] else: raise ValueError("no unit (like day, month, or year) in '%s'" % orig) s = s.strip() return int(s) * unit def parse_date(s): # return seconds-since-epoch for the UTC midnight that starts the given # day return int(iso_utc_time_to_seconds(s + "T00:00:00")) def format_delta(time_1, time_2): if time_1 is None: return "N/A" if time_1 > time_2: return '-' delta = int(time_2 - time_1) seconds = delta % 60 delta -= seconds minutes = (delta // 60) % 60 delta -= minutes * 60 hours = delta // (60*60) % 24 delta -= hours * 24 days = delta // (24*60*60) if not days: if not hours: if not minutes: return "%ss" % (seconds) else: return "%sm %ss" % (minutes, seconds) else: return "%sh %sm %ss" % (hours, minutes, seconds) else: return "%sd %sh %sm %ss" % (days, hours, minutes, seconds)