worklog
A simple work hours logger
So, i do commissions in several media forms, and i usually charge an estimate based on hourly pay.
For art, thats very easy, as krita happily records time worked on a project!
However, i also program, and that doesn't really have a built in timer. so yesterday i buckled down and built one!
Worklog
Worklog is a simple cli program that logs your time worked, with five simple commands. init
start
stop
milestone
and list
. One of the big design ethos i decided on for the program is i wanted the log file itself to be human readable, partly because i believe that most software should store data agnostically to the software that created it, and also because i wished to have an easy time to edit it so that i could correct issues.
As a result, the work log can look like this*:
Thu 01 Jun 2023 17:41:03 AEDT / 05:00:00
---
Thu 27 Jul 2023 17:41:03 AEDT / 03:00:00
---
Fri 06 Oct 2023 17:41:03 AEDT / 00:15:00
Fri 06 Oct 2023 18:41:03 AEDT / 00:20:00
---
Wed 18 Oct 2023 17:47:21 AEDT / 00:10:00
* This log was created after the project it is logging was completed, so the times are genetic and innacurate
Each line either has a date and duration, split by a forward slash, or three dashes representing a milestone.
Milestones, I decided, were to be a way to have subtotals of time in your project, for example running worklog list
with the above worklog provides this output:
05:00:00
03:00:00
00:35:00
00:10:00
———
total:
08:45:00
This allows me to, for example, return to the same project on multiple commissions in order to log the total amount of time as well as the time for each commission of the project. (I love my returning customers AND the ability to say how long i have worked on something in total!)
The start
command appends the current date and time to the file, while the end
command calculates how long it has been between the last logged start, and the current time. This means if you run end
multiple times, it will update the time accordingly.
Finally, the milestone
command appends both ---
and a new date/time combo (so that ending after a milestone can work to show how long since that milestone.)
init
is there too
It isn't a perfect program, its a little weird, but im proud of it and happy it is done and something that i will find useful!
In the end, this is what my code came to be!
#!/bin/bash
if [[ $1 == "init" ]] then
echo "$(date) / 00:00:00" >> .worklog
echo "Initalized Worklog and started work"
exit 0
fi
if ! [[ -f ".worklog" ]] then
echo "No Worklog Exists"
exit 1
elif [[ $1 == "start" ]] then
echo "$(date) / 00:00:00" >> .worklog
echo "Started Work Segment"
elif [[ $1 == "end" || $1 == "stop" ]] then
if [[ $(tail -n 1 .worklog) != "---" ]] then
let D1=$(date +%s -d "$(tail -n 1 .worklog | cut -d '/' -f 1)")
let D2=$(date +%s)
DDiff=$(( $D2 - $D1 ))
SDiff=$(printf '%02d:%02d:%02d\n' $(($DDiff/3600)) $(($DDiff%3600/60)) $(($DDiff%60)))
sed -i "\$s/[0-9]*:[0-9][0-9]:[0-9][0-9]\$/$SDiff/" .worklog
echo "Ended Work Segment: $SDiff"
else
echo "No Previous Start Time"
fi
elif [[ $1 == "milestone" ]] then
echo "---" >> .worklog
echo "$(date) / 00:00:00" >> .worklog
echo "Added Milestone"
elif [[ $1 == "list" ]] then
times=" "
miletime=0
while read e; do
if [[ $e == "---" ]] then
times="$times $miletime"
miletime=0
else
let secs=$(echo $e | cut -d '/' -f 2 | awk -F: '{ print ($1 * 3600) + ($2 * 60) + $3 }')
let miletime=$(($miletime + $secs))
fi
done < ".worklog"
times="$times $miletime"
timearray=( $times )
totaltime=0
for t in ${timearray[@]}; do
printf '%02d:%02d:%02d\n' $(($t/3600)) $(($t%3600/60)) $(($t%60))
totaltime=$(($totaltime + $t))
done
printf '———\ntotal:\n%02d:%02d:%02d\n' $(($totaltime/3600)) $(($totaltime%3600/60)) $(($totaltime%60))
else
echo "Valid commands are: init, start, end, milestone, list"
fi