| 1 | """ |
|---|
| 2 | Convert timestamps to abbreviated English text. |
|---|
| 3 | |
|---|
| 4 | Ported to Python 3. |
|---|
| 5 | """ |
|---|
| 6 | |
|---|
| 7 | import re |
|---|
| 8 | from datetime import timedelta |
|---|
| 9 | |
|---|
| 10 | HOUR = 3600 |
|---|
| 11 | DAY = 24*3600 |
|---|
| 12 | WEEK = 7*DAY |
|---|
| 13 | MONTH = 30*DAY |
|---|
| 14 | YEAR = 365*DAY |
|---|
| 15 | |
|---|
| 16 | def abbreviate_time(s): |
|---|
| 17 | """ |
|---|
| 18 | Given time in seconds (float or int) or timedelta, summarize as English by |
|---|
| 19 | returning unicode string. |
|---|
| 20 | """ |
|---|
| 21 | postfix = '' |
|---|
| 22 | if isinstance(s, timedelta): |
|---|
| 23 | # this feels counter-intuitive that positive numbers in a |
|---|
| 24 | # time-delta are "the past"; but if you "do math" on two |
|---|
| 25 | # datetime instances as below, you get a "positve seconds" |
|---|
| 26 | # timedelta instance: |
|---|
| 27 | # a = datetime.utcnow() |
|---|
| 28 | # time.sleep(1) |
|---|
| 29 | # b = datetime.utcnow() |
|---|
| 30 | # print(b - a) # 0:00:01.001203 |
|---|
| 31 | s = s.total_seconds() |
|---|
| 32 | if s >= 0.0: |
|---|
| 33 | postfix = ' ago' |
|---|
| 34 | else: |
|---|
| 35 | postfix = ' in the future' |
|---|
| 36 | s = -s |
|---|
| 37 | def _plural(count, unit): |
|---|
| 38 | count = int(count) |
|---|
| 39 | if count == 1: |
|---|
| 40 | return "%d %s%s" % (count, unit, postfix) |
|---|
| 41 | return "%d %ss%s" % (count, unit, postfix) |
|---|
| 42 | if s is None: |
|---|
| 43 | return "unknown" |
|---|
| 44 | if s < 120: |
|---|
| 45 | return _plural(s, "second") |
|---|
| 46 | if s < 3*HOUR: |
|---|
| 47 | return _plural(s / 60, "minute") |
|---|
| 48 | if s < 2*DAY: |
|---|
| 49 | return _plural(s / HOUR, "hour") |
|---|
| 50 | if s < 2*MONTH: |
|---|
| 51 | return _plural(s / DAY, "day") |
|---|
| 52 | if s < 4*YEAR: |
|---|
| 53 | return _plural(s / MONTH, "month") |
|---|
| 54 | return _plural(s / YEAR, "year") |
|---|
| 55 | |
|---|
| 56 | def abbreviate_space(s, SI=True): |
|---|
| 57 | """ |
|---|
| 58 | Given size in bytes summarize as English by returning unicode string. |
|---|
| 59 | """ |
|---|
| 60 | if s is None: |
|---|
| 61 | return "unknown" |
|---|
| 62 | if SI: |
|---|
| 63 | U = 1000.0 |
|---|
| 64 | isuffix = "B" |
|---|
| 65 | else: |
|---|
| 66 | U = 1024.0 |
|---|
| 67 | isuffix = "iB" |
|---|
| 68 | def r(count, suffix): |
|---|
| 69 | return "%.2f %s%s" % (count, suffix, isuffix) |
|---|
| 70 | |
|---|
| 71 | if s < 1024: # 1000-1023 get emitted as bytes, even in SI mode |
|---|
| 72 | return "%d B" % s |
|---|
| 73 | if s < U*U: |
|---|
| 74 | return r(s/U, "k") |
|---|
| 75 | if s < U*U*U: |
|---|
| 76 | return r(s/(U*U), "M") |
|---|
| 77 | if s < U*U*U*U: |
|---|
| 78 | return r(s/(U*U*U), "G") |
|---|
| 79 | if s < U*U*U*U*U: |
|---|
| 80 | return r(s/(U*U*U*U), "T") |
|---|
| 81 | if s < U*U*U*U*U*U: |
|---|
| 82 | return r(s/(U*U*U*U*U), "P") |
|---|
| 83 | return r(s/(U*U*U*U*U*U), "E") |
|---|
| 84 | |
|---|
| 85 | def abbreviate_space_both(s): |
|---|
| 86 | return "(%s, %s)" % (abbreviate_space(s, True), |
|---|
| 87 | abbreviate_space(s, False)) |
|---|
| 88 | |
|---|
| 89 | def parse_abbreviated_size(s): |
|---|
| 90 | if s is None or s == "": |
|---|
| 91 | return None |
|---|
| 92 | m = re.match(r"^(\d+)([KMGTPE]?[I]?[B]?)$", s.upper()) |
|---|
| 93 | if not m: |
|---|
| 94 | raise ValueError("unparseable value %s" % s) |
|---|
| 95 | number, suffix = m.groups() |
|---|
| 96 | if suffix.endswith("B"): |
|---|
| 97 | suffix = suffix[:-1] |
|---|
| 98 | multiplier = {"": 1, |
|---|
| 99 | "I": 1, |
|---|
| 100 | "K": 1000, |
|---|
| 101 | "M": 1000 * 1000, |
|---|
| 102 | "G": 1000 * 1000 * 1000, |
|---|
| 103 | "T": 1000 * 1000 * 1000 * 1000, |
|---|
| 104 | "P": 1000 * 1000 * 1000 * 1000 * 1000, |
|---|
| 105 | "E": 1000 * 1000 * 1000 * 1000 * 1000 * 1000, |
|---|
| 106 | "KI": 1024, |
|---|
| 107 | "MI": 1024 * 1024, |
|---|
| 108 | "GI": 1024 * 1024 * 1024, |
|---|
| 109 | "TI": 1024 * 1024 * 1024 * 1024, |
|---|
| 110 | "PI": 1024 * 1024 * 1024 * 1024 * 1024, |
|---|
| 111 | "EI": 1024 * 1024 * 1024 * 1024 * 1024 * 1024, |
|---|
| 112 | }[suffix] |
|---|
| 113 | return int(number) * multiplier |
|---|