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! 
Screenshot displaying krita's inbuilt work timer

However, i also program, and that doesn't really have a built in timer. so yesterday i buckled down and built one!


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:


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!


if [[ $1 == "init" ]] then
 echo "$(date) / 00:00:00" >> .worklog
 echo "Initalized Worklog and started work"
 exit 0

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"
   echo "No Previous Start Time"
elif [[ $1 == "milestone" ]] then
 echo "---" >> .worklog
 echo "$(date) / 00:00:00" >> .worklog
 echo "Added Milestone"
elif [[ $1 == "list" ]] then
 times=" "
 while read e; do
   if [[ $e == "---" ]] then
     times="$times $miletime"
     let secs=$(echo $e | cut -d '/' -f 2 | awk -F: '{ print ($1 * 3600) + ($2 * 60) + $3 }')
     let miletime=$(($miletime + $secs))
 done < ".worklog"
 times="$times $miletime"
 timearray=( $times )
 for t in ${timearray[@]}; do
   printf '%02d:%02d:%02d\n' $(($t/3600)) $(($t%3600/60)) $(($t%60))
   totaltime=$(($totaltime + $t))
 printf '———\ntotal:\n%02d:%02d:%02d\n' $(($totaltime/3600)) $(($totaltime%3600/60)) $(($totaltime%60))
 echo "Valid commands are: init, start, end, milestone, list"