Re: Website FAQ - Calculating TimeSheets
Flavio S. Glock wrote: print $ical->format_duration( reduce { $a + $b } @duration ), " $_\n" This line should be: print $ical->format_duration( reduce { $a + $b } @duration ), " $user\n" - Flavio S. Glock
Re: Website FAQ - Calculating TimeSheets
Rick Measham wrote: 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] I changed the date format to ICal. Unfortunately, the durations are now printed as seconds. I turned off warnings because it was complaining that $a and $b were used only once. - #!/usr/bin/perl use strict; use DateTime::Format::ICal; use List::Util qw(reduce); my %users; my $ical = 'DateTime::Format::ICal'; while () { chomp; my ($dt, $user) = split(/\s/,$_,2); push( @{$users{$user}}, $dt ) if $dt && $user; } for my $user ( keys %users ) { my @duration; my @dt = @{$users{$user}}; push @duration, $ical->parse_period( shift(@dt) . "/" . shift(@dt) )->duration while scalar @dt; print $ical->format_duration( reduce { $a + $b } @duration ), " $_\n" } __DATA__ 20050101T085500 Mr Coffee 20050101T085800 BigLug 20050101T120100 BigLug 20050101T130100 BigLug 20050101T172300 Mr Coffee 20050101T172600 BigLug
Website FAQ - Calculating TimeSheets
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 () { 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