diff --git a/TimeSeries.pm b/TimeSeries.pm index 8818f58..39edd64 100644 --- a/TimeSeries.pm +++ b/TimeSeries.pm @@ -31,8 +31,9 @@ use Time::Local; use Data::Dumper; use HTTP::Date qw(parse_date); use Time::Local qw(timegm_nocheck); +use POSIX qw(strftime); -our $VERSION = do { my @r=(q$Revision: 1.16 $=~/\d+/g);sprintf "%d."."%02d"x$#r,@r}; +our $VERSION = do { my @r=(q$Revision: 1.17 $=~/\d+/g);sprintf "%d."."%02d"x$#r,@r}; =head2 new(%opts) @@ -442,6 +443,9 @@ sub get_ticks { my @ticks = (); + my $label; + my $nexttime; + if ($lasttime - $firsttime > 3 * 365 * 24 * 3600) { # more than 3 years: 4 ticks/year @@ -450,16 +454,10 @@ sub get_ticks { $mday = 1; $mon = int($mon/3) * 3; $firsttime = timelocal($sec,$min,$hour,$mday,$mon,$year); - my $time; - for (;;) { - $time = timelocal($sec,$min,$hour,$mday,$mon,$year); - push @ticks, [$time, sprintf('%04d-%02d-%02d', $year+1900, $mon+1, $mday)]; - $mon += 3; - if ($mon >= 12) { - $mon -= 12; $year++; - } - if ($time > $lasttime) {last} - } + + $label = '%Y-%m-%d'; + + $nexttime = sub { return add_months($_[0], 3) }; } elsif ($lasttime - $firsttime > 3 * 30 * 24 * 3600) { # 3 to 36 months: 1 tick/month @@ -467,15 +465,10 @@ sub get_ticks { $sec = $min = $hour = 0; $mday = 1; $firsttime = timelocal($sec,$min,$hour,$mday,$mon,$year); - my $time; - for (;;) { - $time = timelocal($sec,$min,$hour,$mday,$mon,$year); - push @ticks, [$time, sprintf('%04d-%02d-%02d', $year+1900, $mon+1, $mday)]; - if (++$mon >= 12) { - $mon = 0; $year++; - } - if ($time > $lasttime) {last} - } + + $label = '%Y-%m-%d'; + + $nexttime = sub { return add_months($_[0], 1) }; } elsif ($lasttime - $firsttime > 30 * 24 * 3600) { # 30 ... 90 days: 1 tick/week. @@ -484,56 +477,42 @@ sub get_ticks { ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($firsttime); $sec = $min = $hour = 0; - my $time = $firsttime = timelocal($sec,$min,$hour,$mday,$mon,$year); - for (;;) { - ($sec,$min,$hour,$mday,$mon,$year) = localtime($time); - push @ticks, [$time, sprintf('%04d-%02d-%02d', $year+1900, $mon+1, $mday)]; - if ($time > $lasttime) {last} + $firsttime = timelocal($sec,$min,$hour,$mday,$mon,$year); - $time += 7 * 24 * 3600; - $time = dstcorr($time); - } + $label = '%Y-%m-%d'; + + $nexttime = sub { return dstcorr($_[0] + 7 * 24 * 3600) }; } elsif ($lasttime - $firsttime > 8 * 24 * 3600) { # 8 .. 30 days: 1 tick per day. my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($firsttime); $sec = $min = $hour = 0; - my $time = $firsttime = timelocal($sec,$min,$hour,$mday,$mon,$year); - for (;;) { - ($sec,$min,$hour,$mday,$mon,$year) = localtime($time); - push @ticks, [$time, sprintf('%04d-%02d-%02d', $year+1900, $mon+1, $mday)]; - if ($time > $lasttime) {last} + $firsttime = timelocal($sec,$min,$hour,$mday,$mon,$year); - $time += 24 * 3600; - $time = dstcorr($time); - } + $label = '%Y-%m-%d'; + + $nexttime = sub { return dstcorr($_[0] + 24 * 3600) }; } elsif ($lasttime - $firsttime > 2 * 24 * 3600) { # 2 .. 8 days: 1 tick/4 hours my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($firsttime); - $sec = $min = $hour = 0; - my $time = $firsttime = timelocal($sec,$min,$hour,$mday,$mon,$year); - for (;;) { - ($sec,$min,$hour,$mday,$mon,$year) = localtime($time); - push @ticks, [$time, sprintf('%04d-%02d-%02d %02d:%02d', $year+1900, $mon+1, $mday, $hour, $min)]; - if ($time > $lasttime) {last} + $sec = $min = 0; + $hour = int($hour / 4) * 4; + $firsttime = timelocal($sec,$min,$hour,$mday,$mon,$year); - $time += 4 * 3600; - $time = dstcorr($time, 4 * 3600); - } + $label = '%Y-%m-%d %H:%M'; + + $nexttime = sub { return dstcorr($_[0] + 4 * 3600, 4 * 3600) }; } elsif ($lasttime - $firsttime > 6 * 3600) { # 6 hours to 2 days: 1 tick per hour. my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($firsttime); $sec = $min = 0; - my $time = $firsttime = timelocal($sec,$min,$hour,$mday,$mon,$year); - for (;;) { - ($sec,$min,$hour,$mday,$mon,$year) = localtime($time); - push @ticks, [$time, sprintf('%04d-%02d-%02d %02d:%02d', $year+1900, $mon+1, $mday, $hour, $min)]; - if ($time > $lasttime) {last} + $firsttime = timelocal($sec,$min,$hour,$mday,$mon,$year); - $time += 3600; - } + $label = '%Y-%m-%d %H:%M'; + + $nexttime = sub { return $_[0] + 3600 }; } else { # less than 6 hours: 1 tick per minute. # (ok, that's too much - need to find some intermediate steps, @@ -542,15 +521,31 @@ sub get_ticks { my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($firsttime); $sec = 0; my $time = $firsttime = timelocal($sec,$min,$hour,$mday,$mon,$year); - for (;;) { - ($sec,$min,$hour,$mday,$mon,$year) = localtime($time); - push @ticks, [$time, sprintf('%04d-%02d-%02d %02d:%02d', $year+1900, $mon+1, $mday, $hour, $min)]; - if ($time > $lasttime) {last} - $time += 60; - } + $label = '%Y-%m-%d %H:%M'; + + $nexttime = sub { return $_[0] + 60 }; } + + my $time = $firsttime; + for (;;) { + push @ticks, [$time, strftime($label, localtime($time))]; + if ($time > $lasttime) {last} + $time = $nexttime->($time); + } + return @ticks; } +sub add_months { + my ($time, $d_mon) = @_; + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) + = localtime($time); + $mon += $d_mon; + if ($mon >= 12) { + $mon -= 12; $year++; + } + $time = timelocal($sec,$min,$hour,$mday,$mon,$year); +}; + 1;