tags:

views:

672

answers:

4

I'm looking for an easy way to track time I work on a project using the command line. I do

echo "$(date) : Start" >>worktime.txt

When I start working and

echo "$(date) : End" >>worktime.txt

When I stop working. The result is a file of the form:

kent@rat:~/work$ cat worktime.txt 
Fri Jan  2 19:17:13 CET 2009 : Start
Fri Jan  2 19:47:18 CET 2009 : End
Fri Jan  2 21:41:07 CET 2009 : Start
Fri Jan  2 22:39:24 CET 2009 : End

"Start" and "End" are meant as descriptions and could have been any other text. It is certain that every odd line contains a start date and time before : and every even line contains an end date and time.

What I would like to do is sum up my worked time by parsing the text file using bash, tr, sed, awk and the other common Unix/Linux tools. I prefer using this approach instead of using Python, Perl, Haskell, Java etc.

All ideas welcome!

+2  A: 

Assuming you're using the GNU coreutils, run date +%s instead.

echo $(date +%s) : Start

The %s placeholder is non-POSIX compliant and is specific to GNU date. It is replaced by the number of seconds passed since epoch. Next write a script that takes the differences and sums them up. You'll do something like

#!/bin/bash

total=0
while read LINE; do
  t1=$(echo $LINE |cut -d' ' -f1)
  read LINE
  t2=$(echo $LINE |cut -d' ' -f1)
  total=$(($total+$t2-$t1))
done
echo "$(echo "scale=2; $total/(60*60)" |bc -l)" hours

If you call the script sum_time.sh then you can invoke the script with

~$ ./sum_time.sh <worktime.txt

wilhelmtell
DeletedAccount
+1  A: 

The following awk script should do it (not tested though):

BEGIN {
    total_secs = 0
    FS = OFS = ":"
}

function snip_it() {
    $NF = ""; $0 = substr($0, 1, length($0)-1);
}

!(NR % 2) {
    snip_it();
    ("date -d \"" $0 "\" +%s") | getline start_secs
}

NR % 2 {
    snip_it();
    ("date -d \"" $0 "\" +%s") | getline end_secs
    total_secs += (end_secs - start_secs)
}

END {
    print "Total work time of " total_secs " seconds"
}

The key is that date +%s returns the amount of seconds since 1970, and -d specifies an alternative time/date, instead of now.

Johannes Schaub - litb
Is this awk? I think that should be mentioned. At first it looked like Bash, then I realized it was probably awk.
strager
You do get my vote up, nice script. However I think the solution in pure bash was nice as well, so I'm putting it as my accepted answer (as it doesn't require awk and is of equal complexity level).
DeletedAccount
+1  A: 

wilhelmtell has a great script, if you need to use a slightly modified version so that you can continue to use $(date) instead of $(date +%s) this will work in an identical fashion, just with an added line to reformat the times using +%s

#!/bin/bash                                                                                                                                                                                    

total=0
while read LINE; do
  d1=$(echo $LINE |cut -c1-28);
  t1=$(date -d "$d1" +%s);
  read LINE
  d2=$(echo $LINE |cut -c1-28);
  t2=$(date -d "$d2" +%s);
  total=$(($total+$t2-$t1));
done
echo $(($total/(60*60))) hours
Jehiah
Nice improvement. Keeping the date and time information the way they were was important to me.
DeletedAccount
A: 

Or you could use something that already exists:

http://www.sourcefiles.org/Productivity_Tools/Timers/tt-1.0.tar.gz

hop
Thanks for the suggestion. If I have time some day I'll look into it, presently I'm satisfied with this simple (and "guaranteed" bug free [it's so simple that I don't expect any bugs]) solution. :-)
DeletedAccount
somehow this isn't the tt i know anyhow :(
hop
i changed the link to the one i meant
hop