how to display calculated timedelta as time in python

366 views Asked by At

I'm calculating time stored in timewarrior via timew-report python library.

I'm adding up the time, which I'm able to do. And I'm trying get the total to display in just a number of hours:minutes:seconds, without days.

My script....

#!/usr/bin/python
import sys
import datetime
from datetime import timedelta
from timewreport.parser import TimeWarriorParser #https://github.com/lauft/timew-report

parser = TimeWarriorParser(sys.stdin)

total = datetime.datetime(1, 1, 1, 0, 0)
for interval in parser.get_intervals():
    duration = interval.get_duration()
    print(duration)
    total = total + duration
print(total)

...works properly, returning:

0:01:09
0:06:03
7:00:00
0:12:52
20:00:00
0001-01-02 03:20:04

...but instead of showing 0001-01-02 03:20:04 I'd like it to say 27:20:04.

How do I get it to be formatted like that?

Am I taking the wrong approach by initializing total like datetime.datetime(1, 1, 1, 0, 0)?

3

There are 3 answers

5
alani On BEST ANSWER

On the assumption that interval.get_duration is returning a datetime.timedelta object each time, you can just add these to an existing datetime.timedelta object, and then do the arithmetic to convert to HH:MM:SS format at the end. (You will need to do your own arithmetic because the default string representation for timedelta will use days and HH:MM:SS if the value exceeds 24 hours, which you don't want.)

For example:

import datetime

total = datetime.timedelta(0)
for interval in parser.get_intervals():
    duration = interval.get_duration()
    total += duration

total_secs = int(total.total_seconds())
secs = total_secs % 60
mins = (total_secs // 60) % 60
hours = (total_secs // 3600)

print("{hours}:{mins:02}:{secs:02}".format(hours=hours, mins=mins, secs=secs))
2
ahmadgh74 On

Pass total seconds to timedelta function from datetime like below:

total = your_total.timestamp()
total_time = datetime.timedelta(seconds=total) 
str(total_time) 
0
alec On

For anyone interested in this timewarrior report, here's my final working code. Put this in scriptname located in timewarrior extensions directory then invoke like timew scriptname tagname to see a timereport showing annotations and total uninvoiced time for a given tag (it can also be used without a tag to display all time entries).

#!/usr/bin/python
import sys
import datetime
from datetime import timedelta
from timewreport.parser import TimeWarriorParser #https://github.com/lauft/timew-report

parser = TimeWarriorParser(sys.stdin)

total = datetime.timedelta()
tags = ''
for interval in parser.get_intervals():
    tags = interval.get_tags()
    # this report shows only un-invoiced time, so we ignore "invoiced" time entries
    if 'invoiced' not in tags:
        # hide 'client' and 'work' tags since they clutter this report
        if 'clients' in tags:
            tags.remove('clients')
        if 'work' in tags:
            tags.remove('work')
        date = interval.get_start()
        duration = interval.get_duration()
        ant = interval.get_annotation()
        sep = ', '
        taglist = sep.join(tags)
        output = str(date.date()) + ' - ' + str(duration) + ' - ' + taglist
        if ant:
            output += ' ||| ' + str(ant)
        print(output)
        total = total + duration

print('----------------')

# We calculate the time out like this manually because we don't want numbers of hours greater than 24 to be presented as days
total_secs = int(total.total_seconds())
secs = total_secs % 60
mins = (total_secs // 60) % 60
hours = (total_secs // 3600)

# for new versions of python 3.6 and up the following could work
# print(f"{hours}:{mins:02}:{secs:02}")
# but for older python this works...
print("total = {hours}:{mins:02}:{secs:02}".format(hours=hours, mins=mins, secs=secs))