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;
|
||||
|
||||
=head1 NAME
|
||||
|
@ -21,13 +23,16 @@ implemented.
|
|||
|
||||
=cut
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
use File::Temp qw(tempfile);
|
||||
use Time::Local;
|
||||
use Data::Dumper;
|
||||
use HTTP::Date qw(parse_date);
|
||||
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)
|
||||
|
||||
|
@ -291,7 +296,7 @@ sub dstcorr {
|
|||
my ($time, $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;
|
||||
if ($toff != 0) {
|
||||
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 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 $lasttime = $self->{data}[$#{$self->{data}}][0];
|
||||
|
||||
if ($lasttime - $firsttime > 3 * 365 * 24 * 3600) {
|
||||
# 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 @tics = get_ticks($firsttime, $lasttime);
|
||||
|
||||
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);
|
||||
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";
|
||||
}
|
||||
print $ctlfh "set xtics rotate (",
|
||||
join(", ", map sprintf(qq|"%s" %d|, $_->[1], $_->[0]), @tics),
|
||||
")\n";
|
||||
|
||||
# what to plot
|
||||
|
||||
print $ctlfh "plot ";
|
||||
$comma = 0;
|
||||
$col = 2;
|
||||
my $comma = 0;
|
||||
my $col = 2;
|
||||
|
||||
for $i (@{$self->{legend}}) {
|
||||
for my $i (@{$self->{legend}}) {
|
||||
if ($comma) {
|
||||
print $ctlfh ", ";
|
||||
} else {
|
||||
|
@ -591,4 +421,136 @@ sub plot {
|
|||
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;
|
||||
|
|
Loading…
Reference in New Issue