Refactorization: moved computation of ticks into function get_ticks.
This commit is contained in:
parent
464d8c4233
commit
3d0b7f7cbe
330
TimeSeries.pm
330
TimeSeries.pm
|
@ -1,3 +1,5 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
|
||||||
package TimeSeries;
|
package TimeSeries;
|
||||||
|
|
||||||
=head1 NAME
|
=head1 NAME
|
||||||
|
@ -21,13 +23,16 @@ implemented.
|
||||||
|
|
||||||
=cut
|
=cut
|
||||||
|
|
||||||
|
use warnings;
|
||||||
|
use strict;
|
||||||
|
|
||||||
use File::Temp qw(tempfile);
|
use File::Temp qw(tempfile);
|
||||||
use Time::Local;
|
use Time::Local;
|
||||||
use Data::Dumper;
|
use Data::Dumper;
|
||||||
use HTTP::Date qw(parse_date);
|
use HTTP::Date qw(parse_date);
|
||||||
use Time::Local qw(timegm_nocheck);
|
use Time::Local qw(timegm_nocheck);
|
||||||
|
|
||||||
$VERSION = do { my @r=(q$Revision: 1.15 $=~/\d+/g);sprintf "%d."."%02d"x$#r,@r};
|
our $VERSION = do { my @r=(q$Revision: 1.16 $=~/\d+/g);sprintf "%d."."%02d"x$#r,@r};
|
||||||
|
|
||||||
=head2 new(%opts)
|
=head2 new(%opts)
|
||||||
|
|
||||||
|
@ -291,7 +296,7 @@ sub dstcorr {
|
||||||
my ($time, $period) = @_;
|
my ($time, $period) = @_;
|
||||||
$period = 24 * 3600 unless ($period);
|
$period = 24 * 3600 unless ($period);
|
||||||
|
|
||||||
($sec,$min,$hour,$mday,$mon,$year) = localtime($time);
|
my ($sec,$min,$hour,$mday,$mon,$year) = localtime($time);
|
||||||
my $toff = ($hour * 3600 + $min * 60 * $sec) % $period;
|
my $toff = ($hour * 3600 + $min * 60 * $sec) % $period;
|
||||||
if ($toff != 0) {
|
if ($toff != 0) {
|
||||||
if ($toff > $period/2) {
|
if ($toff > $period/2) {
|
||||||
|
@ -351,197 +356,22 @@ sub plot {
|
||||||
print $ctlfh "set key $self->{legend_position}\n" if ($self->{legend_position});
|
print $ctlfh "set key $self->{legend_position}\n" if ($self->{legend_position});
|
||||||
print $ctlfh "set datafile missing '?'\n";
|
print $ctlfh "set datafile missing '?'\n";
|
||||||
|
|
||||||
# compute ticks
|
|
||||||
|
|
||||||
# The spacing of the ticks a bit tricky: They should be related to
|
|
||||||
# common time units (1 hour, 1 day, 1 week, ...), which are
|
|
||||||
# irregular and not even of constant length (a day can be 23, 24 or
|
|
||||||
# 25 hours, a month 28 to 31 days, a year 365 or 366 days). Also the
|
|
||||||
# spacing shouldn't be too tight or too sparse. So there's quite a
|
|
||||||
# bit of special-case code below (but also much code duplication
|
|
||||||
# which should be cleaned up).
|
|
||||||
|
|
||||||
my $firsttime = $self->{data}[0][0];
|
my $firsttime = $self->{data}[0][0];
|
||||||
my $lasttime = $self->{data}[$#{$self->{data}}][0];
|
my $lasttime = $self->{data}[$#{$self->{data}}][0];
|
||||||
|
|
||||||
if ($lasttime - $firsttime > 3 * 365 * 24 * 3600) {
|
my @tics = get_ticks($firsttime, $lasttime);
|
||||||
# more than 3 years: 1 tick/year
|
|
||||||
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($firsttime);
|
|
||||||
$sec = $min = $hour = 0;
|
|
||||||
$mday = 1;
|
|
||||||
$mon = int($mon/3) * 3;
|
|
||||||
$firsttime = timelocal($sec,$min,$hour,$mday,$mon,$year);
|
|
||||||
print $ctlfh "set xtics rotate (";
|
|
||||||
my $comma = 0;
|
|
||||||
my $time;
|
|
||||||
for (;;) {
|
|
||||||
$time = timelocal($sec,$min,$hour,$mday,$mon,$year);
|
|
||||||
if ($comma) {
|
|
||||||
print $ctlfh ", ";
|
|
||||||
} else {
|
|
||||||
$comma = 1;
|
|
||||||
}
|
|
||||||
printf $ctlfh qq|"%04d-%02d-%02d" %d|, $year+1900, $mon+1, $mday, $time;
|
|
||||||
$mon += 3;
|
|
||||||
if ($mon >= 12) {
|
|
||||||
$mon -= 12; $year++;
|
|
||||||
}
|
|
||||||
if ($time > $lasttime) {last}
|
|
||||||
}
|
|
||||||
$lasttime = $time;
|
|
||||||
print $ctlfh ")\n";
|
|
||||||
} elsif ($lasttime - $firsttime > 3 * 30 * 24 * 3600) {
|
|
||||||
# 3 to 36 months: 1 tick/month
|
|
||||||
|
|
||||||
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($firsttime);
|
print $ctlfh "set xtics rotate (",
|
||||||
$sec = $min = $hour = 0;
|
join(", ", map sprintf(qq|"%s" %d|, $_->[1], $_->[0]), @tics),
|
||||||
$mday = 1;
|
")\n";
|
||||||
$firsttime = timelocal($sec,$min,$hour,$mday,$mon,$year);
|
|
||||||
print $ctlfh "set xtics rotate (";
|
|
||||||
my $comma = 0;
|
|
||||||
my $time;
|
|
||||||
for (;;) {
|
|
||||||
$time = timelocal($sec,$min,$hour,$mday,$mon,$year);
|
|
||||||
if ($comma) {
|
|
||||||
print $ctlfh ", ";
|
|
||||||
} else {
|
|
||||||
$comma = 1;
|
|
||||||
}
|
|
||||||
printf $ctlfh qq|"%04d-%02d-%02d" %d|, $year+1900, $mon+1, $mday, $time;
|
|
||||||
if (++$mon >= 12) {
|
|
||||||
$mon = 0; $year++;
|
|
||||||
}
|
|
||||||
if ($time > $lasttime) {last}
|
|
||||||
}
|
|
||||||
$lasttime = $time;
|
|
||||||
print $ctlfh ")\n";
|
|
||||||
} elsif ($lasttime - $firsttime > 30 * 24 * 3600) {
|
|
||||||
# 30 ... 90 days: 1 tick/week.
|
|
||||||
|
|
||||||
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($firsttime);
|
|
||||||
$firsttime -= 86400 * $wday;
|
|
||||||
|
|
||||||
($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);
|
|
||||||
print $ctlfh "set xtics rotate (";
|
|
||||||
my $comma = 0;
|
|
||||||
for (;;) {
|
|
||||||
($sec,$min,$hour,$mday,$mon,$year) = localtime($time);
|
|
||||||
if ($comma) {
|
|
||||||
print $ctlfh ", ";
|
|
||||||
} else {
|
|
||||||
$comma = 1;
|
|
||||||
}
|
|
||||||
printf $ctlfh qq|"%04d-%02d-%02d" %d|, $year+1900, $mon+1, $mday, $time;
|
|
||||||
if ($time > $lasttime) {last}
|
|
||||||
|
|
||||||
$time += 7 * 24 * 3600;
|
|
||||||
$time = dstcorr($time);
|
|
||||||
}
|
|
||||||
$lasttime = $time;
|
|
||||||
print $ctlfh ")\n";
|
|
||||||
} 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);
|
|
||||||
print $ctlfh "set xtics rotate (";
|
|
||||||
my $comma = 0;
|
|
||||||
for (;;) {
|
|
||||||
($sec,$min,$hour,$mday,$mon,$year) = localtime($time);
|
|
||||||
if ($comma) {
|
|
||||||
print $ctlfh ", ";
|
|
||||||
} else {
|
|
||||||
$comma = 1;
|
|
||||||
}
|
|
||||||
printf $ctlfh qq|"%04d-%02d-%02d" %d|, $year+1900, $mon+1, $mday, $time;
|
|
||||||
if ($time > $lasttime) {last}
|
|
||||||
|
|
||||||
$time += 24 * 3600;
|
|
||||||
$time = dstcorr($time);
|
|
||||||
}
|
|
||||||
$lasttime = $time;
|
|
||||||
print $ctlfh ")\n";
|
|
||||||
} 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);
|
|
||||||
print $ctlfh "set xtics rotate (";
|
|
||||||
my $comma = 0;
|
|
||||||
for (;;) {
|
|
||||||
($sec,$min,$hour,$mday,$mon,$year) = localtime($time);
|
|
||||||
if ($comma) {
|
|
||||||
print $ctlfh ", ";
|
|
||||||
} else {
|
|
||||||
$comma = 1;
|
|
||||||
}
|
|
||||||
printf $ctlfh qq|"%04d-%02d-%02d %02d:%02d" %d|, $year+1900, $mon+1, $mday, $hour, $min, $time;
|
|
||||||
if ($time > $lasttime) {last}
|
|
||||||
|
|
||||||
$time += 4 * 3600;
|
|
||||||
$time = dstcorr($time, 4 * 3600);
|
|
||||||
}
|
|
||||||
$lasttime = $time;
|
|
||||||
print $ctlfh ")\n";
|
|
||||||
} 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);
|
|
||||||
print $ctlfh "set xtics rotate (";
|
|
||||||
my $comma = 0;
|
|
||||||
for (;;) {
|
|
||||||
($sec,$min,$hour,$mday,$mon,$year) = localtime($time);
|
|
||||||
if ($comma) {
|
|
||||||
print $ctlfh ", ";
|
|
||||||
} else {
|
|
||||||
$comma = 1;
|
|
||||||
}
|
|
||||||
printf $ctlfh qq|"%04d-%02d-%02d %02d:%02d" %d|, $year+1900, $mon+1, $mday, $hour, $min, $time;
|
|
||||||
if ($time > $lasttime) {last}
|
|
||||||
|
|
||||||
$time += 3600;
|
|
||||||
}
|
|
||||||
$lasttime = $time;
|
|
||||||
print $ctlfh ")\n";
|
|
||||||
} else {
|
|
||||||
# less than 6 hours: 1 tick per minute.
|
|
||||||
# (ok, that's too much - need to find some intermediate steps,
|
|
||||||
# but for now I need graphs over a few minutes.
|
|
||||||
|
|
||||||
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($firsttime);
|
|
||||||
$sec = 0;
|
|
||||||
my $time = $firsttime = timelocal($sec,$min,$hour,$mday,$mon,$year);
|
|
||||||
print $ctlfh "set xtics rotate (";
|
|
||||||
my $comma = 0;
|
|
||||||
for (;;) {
|
|
||||||
($sec,$min,$hour,$mday,$mon,$year) = localtime($time);
|
|
||||||
if ($comma) {
|
|
||||||
print $ctlfh ", ";
|
|
||||||
} else {
|
|
||||||
$comma = 1;
|
|
||||||
}
|
|
||||||
printf $ctlfh qq|"%04d-%02d-%02d %02d:%02d" %d|, $year+1900, $mon+1, $mday, $hour, $min, $time;
|
|
||||||
if ($time > $lasttime) {last}
|
|
||||||
|
|
||||||
$time += 60;
|
|
||||||
}
|
|
||||||
$lasttime = $time;
|
|
||||||
print $ctlfh ")\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
# what to plot
|
# what to plot
|
||||||
|
|
||||||
print $ctlfh "plot ";
|
print $ctlfh "plot ";
|
||||||
$comma = 0;
|
my $comma = 0;
|
||||||
$col = 2;
|
my $col = 2;
|
||||||
|
|
||||||
for $i (@{$self->{legend}}) {
|
for my $i (@{$self->{legend}}) {
|
||||||
if ($comma) {
|
if ($comma) {
|
||||||
print $ctlfh ", ";
|
print $ctlfh ", ";
|
||||||
} else {
|
} else {
|
||||||
|
@ -591,4 +421,136 @@ sub plot {
|
||||||
return $graph;
|
return $graph;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
=head2 get_ticks($firsttime, $lasttime)
|
||||||
|
|
||||||
|
Compute a "reasonable" set of ticks
|
||||||
|
covering the interval between $firsttime and $lasttime.
|
||||||
|
|
||||||
|
The spacing of the ticks a bit tricky: They should be related to
|
||||||
|
common time units (1 hour, 1 day, 1 week, ...), which are
|
||||||
|
irregular and not even of constant length (a day can be 23, 24 or
|
||||||
|
25 hours, a month 28 to 31 days, a year 365 or 366 days). Also the
|
||||||
|
spacing shouldn't be too tight or too sparse.
|
||||||
|
|
||||||
|
The function returns an ordered list of [ $timestamp, $label ] pairs.
|
||||||
|
$firsttime falls into the interval between the first and second timestamp.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub get_ticks {
|
||||||
|
my ($firsttime, $lasttime) = @_;
|
||||||
|
|
||||||
|
my @ticks = ();
|
||||||
|
|
||||||
|
if ($lasttime - $firsttime > 3 * 365 * 24 * 3600) {
|
||||||
|
# more than 3 years: 4 ticks/year
|
||||||
|
|
||||||
|
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($firsttime);
|
||||||
|
$sec = $min = $hour = 0;
|
||||||
|
$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}
|
||||||
|
}
|
||||||
|
} elsif ($lasttime - $firsttime > 3 * 30 * 24 * 3600) {
|
||||||
|
# 3 to 36 months: 1 tick/month
|
||||||
|
|
||||||
|
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($firsttime);
|
||||||
|
$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}
|
||||||
|
}
|
||||||
|
} elsif ($lasttime - $firsttime > 30 * 24 * 3600) {
|
||||||
|
# 30 ... 90 days: 1 tick/week.
|
||||||
|
|
||||||
|
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($firsttime);
|
||||||
|
$firsttime -= 86400 * $wday;
|
||||||
|
|
||||||
|
($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}
|
||||||
|
|
||||||
|
$time += 7 * 24 * 3600;
|
||||||
|
$time = dstcorr($time);
|
||||||
|
}
|
||||||
|
} 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}
|
||||||
|
|
||||||
|
$time += 24 * 3600;
|
||||||
|
$time = dstcorr($time);
|
||||||
|
}
|
||||||
|
} 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}
|
||||||
|
|
||||||
|
$time += 4 * 3600;
|
||||||
|
$time = dstcorr($time, 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}
|
||||||
|
|
||||||
|
$time += 3600;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
# less than 6 hours: 1 tick per minute.
|
||||||
|
# (ok, that's too much - need to find some intermediate steps,
|
||||||
|
# but for now I need graphs over a few minutes.
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return @ticks;
|
||||||
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|
Loading…
Reference in New Issue