1 | """ |
---|
2 | Time formatting utilities. |
---|
3 | |
---|
4 | ISO-8601: |
---|
5 | http://www.cl.cam.ac.uk/~mgk25/iso-time.html |
---|
6 | """ |
---|
7 | |
---|
8 | from future.utils import native_str |
---|
9 | |
---|
10 | import calendar, datetime, re, time |
---|
11 | |
---|
12 | def format_time(t): |
---|
13 | return time.strftime("%Y-%m-%d %H:%M:%S", t) |
---|
14 | |
---|
15 | def iso_utc_date(now=None, t=time.time): |
---|
16 | if now is None: |
---|
17 | now = t() |
---|
18 | return datetime.datetime.utcfromtimestamp(now).isoformat()[:10] |
---|
19 | |
---|
20 | def iso_utc(now=None, sep='_', t=time.time): |
---|
21 | if now is None: |
---|
22 | now = t() |
---|
23 | sep = native_str(sep) # Python 2 doesn't allow unicode input to isoformat |
---|
24 | return datetime.datetime.utcfromtimestamp(now).isoformat(sep) |
---|
25 | |
---|
26 | def iso_utc_time_to_seconds(isotime, _conversion_re=re.compile(r"(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})[T_ ](?P<hour>\d{2}):(?P<minute>\d{2}):(?P<second>\d{2})(?P<subsecond>\.\d+)?")): |
---|
27 | """ |
---|
28 | The inverse of iso_utc(). |
---|
29 | |
---|
30 | Real ISO-8601 is "2003-01-08T06:30:59". We also accept the widely |
---|
31 | used variants "2003-01-08_06:30:59" and "2003-01-08 06:30:59". |
---|
32 | """ |
---|
33 | m = _conversion_re.match(isotime) |
---|
34 | if not m: |
---|
35 | raise ValueError(isotime, "not a complete ISO8601 timestamp") |
---|
36 | year, month, day = int(m.group('year')), int(m.group('month')), int(m.group('day')) |
---|
37 | hour, minute, second = int(m.group('hour')), int(m.group('minute')), int(m.group('second')) |
---|
38 | subsecstr = m.group('subsecond') |
---|
39 | if subsecstr: |
---|
40 | subsecfloat = float(subsecstr) |
---|
41 | else: |
---|
42 | subsecfloat = 0 |
---|
43 | |
---|
44 | return calendar.timegm( (year, month, day, hour, minute, second, 0, 1, 0) ) + subsecfloat |
---|
45 | |
---|
46 | def parse_duration(s): |
---|
47 | orig = s |
---|
48 | unit = None |
---|
49 | DAY = 24*60*60 |
---|
50 | MONTH = 31*DAY |
---|
51 | YEAR = 365*DAY |
---|
52 | if s.endswith("s"): |
---|
53 | s = s[:-1] |
---|
54 | if s.endswith("day"): |
---|
55 | unit = DAY |
---|
56 | s = s[:-len("day")] |
---|
57 | elif s.endswith("month"): |
---|
58 | unit = MONTH |
---|
59 | s = s[:-len("month")] |
---|
60 | elif s.endswith("mo"): |
---|
61 | unit = MONTH |
---|
62 | s = s[:-len("mo")] |
---|
63 | elif s.endswith("year"): |
---|
64 | unit = YEAR |
---|
65 | s = s[:-len("YEAR")] |
---|
66 | else: |
---|
67 | raise ValueError("no unit (like day, month, or year) in '%s'" % orig) |
---|
68 | s = s.strip() |
---|
69 | return int(s) * unit |
---|
70 | |
---|
71 | def parse_date(s): |
---|
72 | # return seconds-since-epoch for the UTC midnight that starts the given |
---|
73 | # day |
---|
74 | return int(iso_utc_time_to_seconds(s + "T00:00:00")) |
---|
75 | |
---|
76 | def format_delta(time_1, time_2): |
---|
77 | if time_1 is None: |
---|
78 | return "N/A" |
---|
79 | if time_1 > time_2: |
---|
80 | return '-' |
---|
81 | delta = int(time_2 - time_1) |
---|
82 | seconds = delta % 60 |
---|
83 | delta -= seconds |
---|
84 | minutes = (delta // 60) % 60 |
---|
85 | delta -= minutes * 60 |
---|
86 | hours = delta // (60*60) % 24 |
---|
87 | delta -= hours * 24 |
---|
88 | days = delta // (24*60*60) |
---|
89 | if not days: |
---|
90 | if not hours: |
---|
91 | if not minutes: |
---|
92 | return "%ss" % (seconds) |
---|
93 | else: |
---|
94 | return "%sm %ss" % (minutes, seconds) |
---|
95 | else: |
---|
96 | return "%sh %sm %ss" % (hours, minutes, seconds) |
---|
97 | else: |
---|
98 | return "%sd %sh %sm %ss" % (days, hours, minutes, seconds) |
---|
99 | |
---|