[BACK]Return to report_time CVS log [TXT][DIR] Up to [local] / RT / Invoicing

File: [local] / RT / Invoicing / report_time (download)

Revision 1.6, Thu Aug 20 02:15:23 2020 UTC (3 years, 8 months ago) by afresh1
Branch: MAIN
CVS Tags: HEAD
Changes since 1.5: +15 -14 lines

Keep all time together instead of by type

We need to know when the last thing ended, even if it wasn't the same type,
so can't do the other without more work.

#!/usr/bin/perl
# $AFresh1: report_time,v 1.6 2020/08/20 02:15:23 afresh1 Exp $
use v5.16;
use warnings;

my $dir = "$ENV{HOME}/rt_invoicing/time";

my %conversions = (
	m  => "Misc",
	pc => "Phone Call",
);

# You can generate the files expected by this with this helpful script.
#
# #!/bin/sh
# action=$( basename $0 )
# realname=$( basename $( readlink -f $0 ) )
# [ "$action" = "$realname" ] && action=sta
# echo $( date ) $action "$@" >> ~/.time/$( date +%Y-%m-%d )
# 
# You will have to mkdir ~/.time yourself.
# Link it to both "sta" and "sto" in your path and then start working with
# `sta some work` then stop working with just `sto`.
# A second `sta something else` will stop working on "some work"
# and switch to "something else".

use Time::Piece;

my @files = do {
	opendir my $dh, $dir or die "Unable to opendir $dir: $!";
        map { "$dir/$_" } sort grep { /^\d{4}-\d{2}-\d{2}$/ } readdir $dh;
};

my @entries;
foreach my $file (@files) {
	open my $fh, '<', $file or die "Unable to open $file: $!";
	while (readline $fh) {
		my ($dt, $type, $description)
		    = /^ (.*) \s+ (st[ao])\b \s* (.*) \R$/x;

                my %entry = ( dt => $dt, type => $type );
		$entry{description} = $description if $description;

		push @entries, \%entry;
	}
	close $fh;
}

my %total;
{
	my $start;
	my $key = 'm';
	foreach my $entry (@entries) {

		# Sat Jul 11 11:56:06 PDT 2020
		$entry->{datetime} = Time::Piece->new->strptime(
		    $entry->{dt}, "%a %b %e %H:%M:%S %Z %Y");

		if ($start) {
                	$key = descr_to_key($start->{description})
			    if $start->{description};
			$total{ $entry->{datetime}->date }{$key}
			    += $entry->{datetime} - $start->{datetime};
		}

		$start = $entry->{type} eq 'sta' ? $entry : '';
	}

	# If we have a timer running, pretend it stops now.
	if ($start) {
                $key = descr_to_key($start->{description})
		    if $start->{description};
		my $now = localtime;
		$total{ $now->date }{$key} += $now - $start->{datetime}
	}
}

my $total = 0;
foreach my $date ( sort keys %total ) {
	my $subtotal = 0;
	foreach my $key ( sort keys %{ $total{$date} } ) {
		my $hours = $total{$date}{$key}->hours;

		# round to the quarter hour
		$hours = sprintf "%.02f",
		    25 * sprintf "%.02f", $hours / 25;

		say "$date $hours $key" if $hours != 0;

		$subtotal += $hours;
		$total    += $hours;
	}
	printf "# %s %.02f\n", $date, $subtotal;
}
printf "# Total %.02f\n", $total;

sub descr_to_key {
	my ($descr) = @_;

	my @key = split /\s+/, $descr;

	$key[-1] = $conversions{ lc $key[-1] }
	    if @key < 3 and $conversions{ lc $key[-1] };

	return "@key";
}