http://www.perlmonks.org?node_id=989991


in reply to Which DateTime:: module to use?

Here are 2 additional solutions. One uses DateTime and the other uses Date::Parse and POSIX. I don't know about speed, but you could try them out and see. Also, which is the most easy to read might be a consideration, (as you stated).
#!/usr/bin/perl use strict; use warnings; use DateTime::Format::Strptime; my $dt = DateTime::Format::Strptime->new( pattern => '%Y.%m.%d %H:%M') +; chomp(my @line = split /,/, <DATA>); my @data = \@line; my $beg = $dt->parse_datetime("@line[0,1]")->truncate( to => 'hour' ); my $end = $beg->clone->add(hours => 12); printf "%s -+- %s\n", map tr/T/ /r, $beg, $end; while (<DATA>) { chomp(my @line = split /,/); my $date = $dt->parse_datetime("@line[0,1]")->truncate( to => 'hou +r' ); if ($date < $end) { push @data, \@line; } else { process(@data); @data = \@line; $end = $date->clone->add(hours => 12); printf "%s -+- %s\n", map tr/T/ /r, $date, $end; } } process(@data); sub process { my @data = @_; # do somthing with data my @sum; my @idx = 2 .. 5; for my $line (@data) { for my $col (@idx) { $sum[$col] += $line->[$col]; } } printf "Avg of %d lines", scalar @data; print +(map {sprintf "%10.5f", $sum[$_] / @data} @idx), "\n"; }
The Date::Parse solution is nearly the same.
#!/usr/bin/perl use strict; use warnings; use Date::Parse qw/ str2time /; use POSIX qw/ strftime /; chomp(my @line = split /,/, <DATA>); my @data = \@line; my $beg = str2time("@line[0,1]"); $beg = int($beg / 3600) * 3600; # truncate minutes and seconds my $end = $beg + 12 * 60 * 60; # add 12 hours printf "%s -+- %s\n", map {strftime "%Y-%m-%d %H:%M:%S", localtime $_} $beg,$end; while (<DATA>) { chomp(my @line = split /,/); my $date = str2time("@line[0,1]"); $date = int($date / 3600) * 3600; # truncate minutes and seconds if ($date < $end) { push @data, \@line; } else { process(@data); @data = \@line; $end = $date + 12 * 60 * 60; printf "%s -+- %s\n", map {strftime "%Y-%m-%d %H:%M:%S", localtime $_} $date, $e +nd; } } process(@data); sub process { my @data = @_; # do somthing with data my @sum; my @idx = 2 .. 5; for my $line (@data) { for my $col (@idx) { $sum[$col] += $line->[$col]; } } printf "Avg of %d lines", scalar @data; print +(map {sprintf "%10.5f", $sum[$_] / @data} @idx), "\n"; } __DATA__ 2011.01.13,21:25,1.33508,1.33524,1.33470,1.33494,391 2011.01.13,21:30,1.33494,1.33506,1.33447,1.33453,318 2011.01.13,21:35,1.33453,1.33483,1.33417,1.33434,426 2011.01.13,21:40,1.33434,1.33468,1.33417,1.33467,309 2011.01.13,21:45,1.33471,1.33493,1.33465,1.33465,233 2011.01.13,21:50,1.33465,1.33475,1.33443,1.33463,184 2011.01.13,21:55,1.33463,1.33519,1.33463,1.33493,344 2011.01.13,22:00,1.33494,1.33563,1.33489,1.33524,318 2011.01.13,22:05,1.33524,1.33551,1.33512,1.33549,182 2011.01.14,22:05,1.33524,1.33551,1.33512,1.33549,182
These produced the output:
C:\Old_Data\perlp>perl t33.pl 2011-01-13 21:00:00 -+- 2011-01-14 09:00:00 Avg of 9 lines 1.33478 1.33509 1.33458 1.33482 2011-01-14 22:00:00 -+- 2011-01-15 10:00:00 Avg of 1 lines 1.33524 1.33551 1.33512 1.33549