taskwarrior-daily-timetrack.../taskwarrior_daily_timetracking_hook/__init__.py

111 lines
3.3 KiB
Python
Raw Permalink Normal View History

2018-03-26 17:41:04 +00:00
#!/usr/bin/env python
import datetime
import json
import re
import sys
import subprocess
from taskw import TaskWarrior
TIME_FORMAT = '%Y%m%dT%H%M%SZ'
UDA_KEY = 'dailyactivetime'
w = TaskWarrior()
config = w.load_config()
if ('max_active_tasks' in config):
MAX_ACTIVE = int(config['max_active_tasks'])
else:
MAX_ACTIVE = 1
ISO8601DURATION = re.compile(
"P((\d*)Y)?((\d*)M)?((\d*)D)?T((\d*)H)?((\d*)M)?((\d*)S)?")
# Convert duration string into a timedelta object.
# Valid formats for duration_str include
# - int (in seconds)
# - string ending in seconds e.g "123seconds"
# - ISO-8601: e.g. "PT1H10M31S"
def duration_str_to_time_delta(duration_str):
if (duration_str.startswith("P")):
match = ISO8601DURATION.match(duration_str)
if (match):
year = match.group(2)
month = match.group(4)
day = match.group(6)
hour = match.group(8)
minute = match.group(10)
second = match.group(12)
value = 0
if (second):
value += int(second)
if (minute):
value += int(minute)*60
if (hour):
value += int(hour)*3600
if (day):
value += int(day)*3600*24
if (month):
# Assume a month is 30 days for now.
value += int(month)*3600*24*30
if (year):
# Assume a year is 365 days for now.
value += int(year)*3600*24*365
else:
value = int(duration_str)
elif (duration_str.endswith("seconds")):
value = int(duration_str.rstrip("seconds"))
else:
value = int(duration_str)
return datetime.timedelta(seconds=value)
def main():
original = json.loads(sys.stdin.readline())
modified = json.loads(sys.stdin.readline())
# An inactive task has just been started.
if 'start' in modified and 'start' not in original:
# Check if `task +ACTIVE count` is greater than MAX_ACTIVE. If so
# prevent this task from starting.
p = subprocess.Popen(
['task', '+ACTIVE', 'status:pending', 'count', 'rc.verbose:off'],
stdout=subprocess.PIPE)
out, err = p.communicate()
count = int(out.rstrip())
if count >= MAX_ACTIVE:
print("Only %d task(s) can be active at a time. "
"See 'max_active_tasks' in .taskrc." % (MAX_ACTIVE))
sys.exit(1)
# An active task has just been stopped.
if 'start' in original and 'start' not in modified:
# Let's see how much time has elapsed
start = datetime.datetime.strptime(original['start'], TIME_FORMAT)
end = datetime.datetime.utcnow()
if UDA_KEY not in modified:
modified[UDA_KEY] = 0
this_duration = (end - start)
total_duration = (
this_duration
+ duration_str_to_time_delta(str(modified[UDA_KEY]))
)
print(
"Daily Time Tracked: %s (%s in this instance)" % (
total_duration,
this_duration,
)
)
modified[UDA_KEY] = str(int(
total_duration.days * (60 * 60 * 24) + total_duration.seconds
)) + "seconds"
return json.dumps(modified, separators=(',',':'))
def cmdline():
sys.stdout.write(main())
if __name__ == '__main__':
cmdline()