remove the footer saying that vim is the best editor -- anyone knows anyway
[pingcheck] / test / strftimedelta.py
1 #!/usr/bin/env python3
2
3 """ give a nice string representation for a duration
4
5 Christian Herdtweck, Intra2net, November 2014
6 Licensed under GPL
7 """
8
9 from datetime import timedelta
10
11 # Version History
12 # 24/11/14 Christian Herdtweck: started creation by copying strftimedelta
13
14
15 def strftimedelta(delta, max_parts=2, only_up_to_hours=False):
16     """ nice and length-adjustable text representation of a timespan 
17
18     will output the most significant non-zero time units, e.g.
19     '2h23m50s' or '3d50s12ms' (skipping 0 minutes), or '3y63d12h'
20     or for max_parts=2: '2h23m' / '3d50s' / '3y63d'
21
22     Assumes that each year has 365 days, every day 24h, every hour 60 mins, ...
23       not accounting for leap years / leap days, changes of timezones, etc
24     
25     @delta:timedelta or anything that can be converted to float;
26        if numeric, this is interpreted as number of seconds
27     @param max_parts: precision (i.e., length) of output (default: 2)
28        set to None if always want precision down to microseconds
29     @param only_up_to_hours: set to True to never give number of days/years
30       (e.g. to get '40h' instead of '1d16h')
31       default: False
32
33     returns a string
34     """
35
36     units = '\u00B5s', 'ms', 's', 'm', 'h', 'd', 'y'
37
38     if (max_parts is None) or (max_parts < 1):
39         max_parts = 100
40
41     # get number of seconds and sign
42     if isinstance(delta, timedelta):
43         seconds = delta.total_seconds()
44     else:
45         seconds = float(delta)
46     negative = False
47     if seconds < 0:
48         negative = True
49         seconds = abs(seconds)
50
51     # split sub-second part
52     seconds, second_part = divmod(seconds, 1)
53     milliseconds, milli_part = divmod(second_part*1000, 1)
54     microseconds = int(round(milli_part*1000))
55     seconds = int(seconds)   # convert to int here --> all other variables will be int
56     vals = [microseconds, int(milliseconds), ]
57
58     # split longer units
59     minutes = hours = days = years = 0
60     if seconds > 0:
61         minutes, seconds = divmod(seconds, 60)
62     if minutes > 0:
63         hours, minutes = divmod(minutes, 60)
64     if hours > 0 and not only_up_to_hours:
65         days, hours = divmod(hours, 24)
66     if days > 0:
67         years, days = divmod(days, 365)
68     vals.append(seconds)
69     vals.append(minutes)
70     vals.append(hours)
71     vals.append(days)
72     vals.append(years)
73
74     # build string
75     str_parts = []
76     if negative:
77         str_parts.append('-')
78
79     n_used = 0
80     for val,unit in zip( reversed(vals), reversed(units) ):
81         if val == 0:
82             continue
83         str_parts.append(str(val))
84         str_parts.append(unit)
85         n_used += 1
86         if n_used >= max_parts:
87             break
88     return ''.join(str_parts)
89
90 #end: strftimedelta
91
92
93
94 def main():
95     """ Main function, called when running file as script; currently raises a NotImplementedError 
96     """
97     raise NotImplementedError('nothing to run here -- only a lib!')
98 #end: function main
99
100
101 if __name__ == '__main__':
102     main()
103