I'm submitting this as a solution for the FAQ. Anyone who wants to make it more elegant is quite welcome! The question came up recently in an IRC channel.


Q. How do I work out how many hours have been worked from a timesheet?

This solution takes a file in the format
        ISO-Date, WhiteSpace, Name

It does not take into account people who forget to log in or out apart from making sure there's an even number of dates for each user.

[Note: this later could be partly solved by splitting into days and then checking for an even number of times. Flagging days for which data was not calculable]
#!/usr/bin/perl

use strict;
use warnings;

use DateTime;
use DateTime::Span;
use DateTime::SpanSet;
use DateTime::Format::Duration;
use DateTime::Format::ISO8601;

my $ISO = DateTime::Format::ISO8601->new();
my $DURATION = DateTime::Format::Duration->new(
        pattern => '%Y years, %m months, %e days, %H hours, %M minutes, %S 
seconds',
        normalize => 1,
);

my %users;
foreach (<DATA>) {
        chomp;
        my ($dt, $user) = split(/\s/,$_,2);
        next unless $dt and $user;
        push(@{$users{$user}}, $dt);
}
foreach my $user (keys %users) {
        printf(
                "%-20s : %s\n",
                $user, 
                $DURATION->format_duration( spanset_from_list( @{$users{$user}} 
)->duration )
        );
}



sub spanset_from_list {
        return undef if @_ % 2;
        my @dates = @_;
        my @spans;
        for( my $i=0; $i < scalar(@dates); $i+=2 ) {
                push(@spans, DateTime::Span->new(
                                start => $ISO->parse_datetime($dates[$i]),
                                end   => $ISO->parse_datetime($dates[$i+1]),
                ));
        }
        return DateTime::SpanSet->from_spans( spans => [EMAIL PROTECTED] );
}


__DATA__
2005-01-01T08:55 Mr Coffee
2005-01-01T08:58 BigLug
2005-01-01T12:01 BigLug
2005-01-01T13:01 BigLug
2005-01-01T17:23 Mr Coffee
2005-01-01T17:26 BigLug

Reply via email to