Skip to content

Instantly share code, notes, and snippets.

@jhargis
Last active March 2, 2020 20:43
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jhargis/7239063 to your computer and use it in GitHub Desktop.
Save jhargis/7239063 to your computer and use it in GitHub Desktop.
Python based timesheet report generation utility for toggl.com api This generates CSV and HTML files from an api call filtered on client and date range.
#!/usr/bin/env python
import os
import csv
import sys
import datetime
import string
import requests
# replace these: API_KEY, CLIENTNAME1, CLIENTNAME2 , CLIENT_ID1, CLIENT_ID2 , WORKSPACE_ID
if len(sys.argv) < 4 :
sys.stderr.write("usage: timesheet-processor.py <client name> <since date> <until date>\n" )
sys.stderr.write("produces to files. hours.csv and hours.html in current directory\n")
sys.stderr.write("Clients [CLIENTNAME1, CLIENTNAME2]. Date format [YYYY-MM-DD]\n" ) # replace here
sys.stderr.write("""example: pull-toggl-timesheet.py CLIENTNAME1 2013-10-14 2013-10-20\n""") # replace here
sys.exit()
CLIENT = sys.argv[1].lower()
if CLIENT == 'CLIENTNAME1': # replace here
CLIENT = 'CLIENT_ID1' # replace here
elif CLIENT == 'CLIENTNAME2': # replace here
CLIENT == 'CLIENT_ID2' # replace here
else:
sys.stderr.write("Unknown client; valid clients:(CLIENTNAME1, CLIENTNAME2)\n") # replace here
sys.exit()
SINCE = sys.argv[2] # 2013-10-28
UNTIL = sys.argv[3] # 2013-10-31
WORKSPACE_ID = 'XXXXXXX' # replace here
API_KEY = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' # replace here
API_URL = 'https://toggl.com/reports/api/v2/details?workspace_id=%s&since=%s&until=%s&user_agent=api_test&client_ids=%s,' % (WORKSPACE_ID, SINCE, UNTIL, CLIENT)
CWD = os.path.abspath(os.curdir)
out_file_csv = CWD + '/hours.csv'
out_file_html = CWD + '/hours.html'
def call_api(page=None):
url = API_URL
if page:
url = url + '&page=%s' % page
data = requests.get(url, auth=(API_KEY, 'api_token'))
if data.status_code != 200:
sys.stderr.write("API error status_code: %s" % data.status_code)
return data.json()
datadict = call_api()
# load multiple pages if necessary
total_count = int(datadict['total_count'])
if total_count > 50:
loop_count = total_count / 50
remainder = total_count % 50
if remainder > 0:
loop_count = loop_count + 1
for i in range(2, loop_count + 1):
dd = call_api(i)
datadict['data'].extend(dd['data'])
# reverse the data - oldest date first
line_list = []
for line in datadict['data']:
line_list.append(line)
line_list.reverse()
def humanize_secs(seconds=0, milliseconds=0):
td = datetime.timedelta(seconds=seconds, milliseconds=milliseconds)
total_seconds = int(td.total_seconds())
hours, remainder = divmod(total_seconds,60*60)
minutes, seconds = divmod(remainder,60)
hours = "%02d" % hours
minutes = "%02d" % minutes
seconds = "%02d" % seconds
return ':'.join([str(hours),str(minutes),str(seconds)])
# get total duration
total_duration = datetime.timedelta(seconds=0)
for row in line_list:
total_duration = total_duration + datetime.timedelta(milliseconds=int(row['dur']))
total_duration = humanize_secs(seconds=total_duration.total_seconds())
# write new csv format
with open(out_file_csv, 'wb') as f:
writer = csv.writer(f)
# write header line
writer.writerow(["Project Task", "Description", "Start Date", "End Date", "Duration"])
for row in line_list:
writer.writerow([row['project'], row['description'], row['start'], row['end'], humanize_secs(milliseconds=int(row['dur']))])
writer.writerow(["", "", "", "", ""])
writer.writerow(["", "", "", "", ""])
writer.writerow(["", "", "", "total:", total_duration])
# build html
with open(out_file_csv, 'rb') as csvfile:
table_string = """<html>
<head>
<style type="text/css">
html { font: 4px, Verdana, Arial, 'sans-serif'; }
table.myTable { border-collapse:collapse; }
table.myTable td, table.myTable th { border:1px solid #CCC; padding:5px; }
</style>
</head>
<body>
<table class="myTable" cellspacing="3">"""
reader = csv.reader(csvfile)
for row in reader:
table_string += "<tr>" + \
"<td>" + \
string.join( row, "</td><td>" ) + \
"</td>" + \
"</tr>\n"
table_string += "</table></body></html>"
with open(out_file_html, 'w') as fh:
fh.write(table_string)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment