Skip to content

Instantly share code, notes, and snippets.

@HokieGeek
Last active September 26, 2016 02:33
Show Gist options
  • Save HokieGeek/45e53bc3c90c77eaa5d47525cb9a8737 to your computer and use it in GitHub Desktop.
Save HokieGeek/45e53bc3c90c77eaa5d47525cb9a8737 to your computer and use it in GitHub Desktop.
silly little script for tracking hours worked
FROM alpine:latest
RUN apk add --no-cache bash tzdata
RUN rm -f /etc/localtime && ln -s /usr/share/zoneinfo/US/Eastern /etc/localtime
RUN echo "US/Eastern" > /etc/timezone
ADD hrs /usr/bin/hrs
ENTRYPOINT ["/usr/bin/hrs"]
#!/bin/bash
badOngoingEntryBytes="12"
log="$HOME/.hours"
cfg="$HOME/.hrs.conf"
if [ -f "${cfg}" ]; then
source <(awk -F'=' '
/^#/ { next }
NF > 1 && $2 !~ /^[[:space:]"'"'"']*$/ {
sub(/^ */, "", $2)
print $1 "=" $2
}
' "${cfg}")
fi
if [ ! -f "${log}" ]; then
if [ -z "${log}" ]; then
echo "ERROR: No log file defined"
exit 2
else
touch "${log}"
echo "Created new log file"
fi
fi
usage() {
{
if [ $# -gt 0 ]; then
echo $@
fi
echo "USAGE: $(basename $0) [-h|--help] [start|end|list|edit|watch|raw] [ENTRY COMMENT]"
cat <<-EOF
Using the 'list' command pretty-prints all log entries.
If no arguments are given, this is the default command.
The 'raw' command dumps the log's contents.
The 'edit' command opens the log in vim.
Using the 'start' command when there is an ongoing entry
will split that entry by ending it and starting a new one.
The 'ENTRY COMMENT' is added to the entry when the 'end'
command is called. The 'start' command only uses it when
splitting an entry. It's ignored by the other commands.
EOF
} >&2
}
fixOngoingEntry() {
last=`tail -1 "${log}"`
sed -i '$d' "${log}"
echo -n "${last}" >> "${log}"
}
getLastEntryBytes() {
[ ! -s "${log}" ] && echo "0"
echo "`tail -1 "${log}"| wc -c`"
}
if [ $# -gt 0 ]; then
case $1 in
start|s|st|sta|star)
if [ `getLastEntryBytes` -le ${badOngoingEntryBytes} ]; then
echo "Splitting ongoing entry..."
shift
"$0" end $@ || exit 3
fi
echo -n "`date +%s` " >> "${log}"
echo "Started entry at: `date +'%F %T'`"
;;
end|e|en)
ongoingEntryBytes=`getLastEntryBytes`
if [ ${ongoingEntryBytes} -le ${badOngoingEntryBytes} ]; then
[ ${ongoingEntryBytes} -eq ${badOngoingEntryBytes} ] && fixOngoingEntry
{
echo -n "`date +%s`"
if [ $# -gt 1 ]; then
shift
echo -n " $@"
fi
echo ""
} >> "${log}"
else
echo "ERROR: Did not find entry to end" >&2
exit 3
fi
echo "Ended entry at: `date +'%F %T'`"
echo -n "Ellapsed time: "
"$0" | awk '$1 ~ /^[0-9]{8}:/ { last=$2 } END { print last }'
;;
watch|w|wa|wat|watc)
exec watch -t "$0 | awk '\$0 ~ /ONGOING/ { print \$2 }'"
;;
edit|ed|edi)
vim "${log}"
[ `getLastEntryBytes` -eq ${badOngoingEntryBytes} ] && fixOngoingEntry
;;
raw|r|ra)
exec cat "${log}"
;;
list|l|li|lis)
exec "$0"
;;
-h|--help|help)
usage
;;
*)
usage "ERROR: Unrecognized command: $1"
exit 1
;;
esac
else
awk '
function printDailyTotal(DAY, dailySecs) {
dailySecs = daily[DAY]-68400;
printf(" \033[33mTotal: %s\033[0m\n", strftime("%H:%M", dailySecs))
}
# Ignore commented lines
/^#/ { next }
# Fake out the current session
NF == 1 {
$0 = $0 strftime("%s") " \033[1;32mONGOING\033[0m"
}
NF > 1 {
# Aggregate the daily hours
secs = $2-$1
day = strftime("%Y%m%d", $1)
daily[day] += secs
dailyCount[day] += 1
# Print a newline between the entries of a single day
if (prevDay != day) {
if (prevDay != "" && dailyCount[prevDay] > 1) {
printDailyTotal(prevDay)
}
printf("\n")
prevDay = day
}
# Ok, print the entry nicely
secs -= 68400;
printf("%s: %s", day, strftime("%H:%M", secs))
# Print anything else at the end as a "label"
if (NF > 2) {
$1 = ""
$2 = ""
sub(/^ */, "")
printf(" [%s]", $0)
}
printf("\n")
}
# Catch the last grouping that needs to be totaled
END {
if (dailyCount[day] > 1) {
printDailyTotal(day)
}
}
' "${log}"
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment