Formatting time delta - Code Review Stack Exchange most recent 30 from codereview.stackexchange.com 2020-01-20T07:48:58Z https://codereview.stackexchange.com/feeds/question/214268 https://creativecommons.org/licenses/by-sa/4.0/rdf https://codereview.stackexchange.com/q/214268 3 Formatting time delta Mantas Kandratavicius https://codereview.stackexchange.com/users/190246 2019-02-25T20:01:06Z 2019-02-26T17:58:58Z <p>Quite often, I find myself measuring how long some part of my code takes to complete. I normally do that by storing current time using <code>time.time()</code> and then subtracting time after the code is done.</p> <p>This normally gives me a float that I can then format and print for debugging purposes. This is the function that I have for time formatting:</p> <pre><code>def time_format(delta: float) -&gt; str: output = [] decimal, integer = math.modf(delta) if integer: minutes, seconds = divmod(int(integer), 60) if minutes: output.append("%sm" % minutes) if seconds: output.append("%ss" % seconds) decimal, integer = math.modf(decimal * 1000) if integer: output.append("%sms" % int(integer)) decimal, integer = math.modf(decimal * 1000) if integer: output.append("%sμs" % int(integer)) decimal, integer = math.modf(decimal * 1000) if integer: output.append("%sns" % int(integer)) return ", ".join(output) </code></pre> <p>I have also been told that the time module has most precision when it comes to time measuring so that's why I'm using it, instead of something like datetime which has nice formatting tools built in.</p> <p>How could I improve my time formatting function? Are there any built in formatting tools that I'm not aware of? (Searching stack overflow leads me only to questions about datetime.timedelta)</p> https://codereview.stackexchange.com/questions/214268/-/214276#214276 2 Answer by Benoît Pilatte for Formatting time delta Benoît Pilatte https://codereview.stackexchange.com/users/193138 2019-02-25T21:53:15Z 2019-02-26T17:58:58Z <p>There is indeed a function for that.</p> <pre><code>&gt;&gt;&gt; from datetime import timedelta &gt;&gt;&gt; print(timedelta(seconds=1239.123456)) 0:20:39.123456 </code></pre> <p>Now, if I understand you correctly, you want a divider for the millisecond.</p> <pre><code>from datetime import timedelta def f(secs): t=str(timedelta(seconds=secs)) index = t.find('.') + 4 return t[:index] + ' ' + t[index:] print(f(1239.123456)) # 0:20:39.123 456 </code></pre> <p>I don't like that everything is hardcoded, if you want to use it for different applications (or even languages), you might want to generalize your bases and names. </p> <p>Here is a generic way of doing any formatting you want:</p> <pre><code>def prod(f): total = 1 l =  for i in range(len(f)-1, 0, -1): total *= f[i] l.append(total) return reversed(l) def format_time(number, f=((24, ':'), (60, ':'), (60, '.'), (1000, ' '), (1000, ''))): return ''.join( (f"{(number//div)%base:0&gt;{len(str(base-1))}}" + delimiter) if number//div else '' for div, (base, delimiter) in zip(prod(f), f) ) </code></pre> <pre><code>formatting = ( (24, ' hours '), (60, ' minutes '), (60, ' seconds '), (1000, ' milliseconds '), (1000, ' nanoseconds'), ) print( format_time(1551198373998173), format_time(1551198373998173, formatting), format_time(1551739, formatting), sep="\n" ) </code></pre> <p>The result is:</p> <pre><code>16:26:13.998 173 16 hours 26 minutes 13 seconds 998 milliseconds 173 nanoseconds 01 seconds 551 milliseconds 739 nanoseconds </code></pre> <p>What are it's advantages, you can do any formatting in any base, with any names. We could even do a base 2 converter.</p> <pre><code>binary_formatting = (((2, ' '),)+((2, ''),)*3)*10 + ((2, ''),) print( format_time(155933900, binary_formatting), format_time(3279, binary_formatting), sep="\n" ) </code></pre> <pre><code>1001 0100 1011 0101 1100 1100 1100 1100 1100 1111 </code></pre> <p>Other than that, if your code need to accomplish a single purpose and it does it well, good for you.</p>