From b6aab82949fd76fa29ffa4e1699bd77bb4f175a4 Mon Sep 17 00:00:00 2001 From: hjp Date: Fri, 15 Aug 2003 21:08:33 +0000 Subject: [PATCH] Improved spacing of tics. --- TimeSeries.pm | 68 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 62 insertions(+), 6 deletions(-) diff --git a/TimeSeries.pm b/TimeSeries.pm index 5e5243f..91ac301 100644 --- a/TimeSeries.pm +++ b/TimeSeries.pm @@ -6,7 +6,7 @@ use Data::Dumper; use HTTP::Date qw(parse_date); use Time::Local qw(timegm_nocheck); -$VERSION = do { my @r=(q$Revision: 1.5 $=~/\d+/g);sprintf "%d."."%02d"x$#r,@r}; +$VERSION = do { my @r=(q$Revision: 1.6 $=~/\d+/g);sprintf "%d."."%02d"x$#r,@r}; sub new { my ($class, %opts) = @_; @@ -87,14 +87,30 @@ sub output_format { +=head2 dstcorr $time [, $period] + +corrects for time shifts caused by DST switches by aligning the +time to the given period in local time. + +Example: + +1048989600 is 2003-03-30 00:00:00 CET. 4 hours (14400 +seconds) later, the time is 2003-03-30 05:00:00 CEST. To get back to a +4 hour period starting at midnight, 1 hour needs to be subtracted, so +C returns 1048989600, which is 2003-03-30 +04:00:00 CEST. + +=cut + sub dstcorr { - my ($time) = @_; + my ($time, $period) = @_; + $period = 24 * 3600 unless ($period); ($sec,$min,$hour,$mday,$mon,$year) = localtime($time); - my $toff = $hour * 3600 + $min * 60 * $sec; + my $toff = ($hour * 3600 + $min * 60 * $sec) % $period; if ($toff != 0) { - if ($toff > 12*3600) { - $toff -= 24 * 3600; + if ($toff > $period/2) { + $toff -= $period; } print STDERR "correcting time by $toff seconds "; printf STDERR "from %04d-%02d-%02d %02d:%02d:%02d ", $year+1900, $mon+1, $mday, $hour, $min, $sec; @@ -137,10 +153,19 @@ sub plot { # 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; @@ -166,6 +191,8 @@ sub plot { $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); $sec = $min = $hour = 0; $mday = 1; @@ -189,6 +216,8 @@ sub plot { $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; @@ -212,7 +241,9 @@ sub plot { } $lasttime = $time; print $ctlfh ")\n"; - } elsif ($lasttime - $firsttime > 3 * 24 * 3600) { + } elsif ($lasttime - $firsttime > 10 * 24 * 3600) { + # 10 .. 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); @@ -233,7 +264,32 @@ sub plot { } $lasttime = $time; print $ctlfh ")\n"; + } elsif ($lasttime - $firsttime > 2 * 24 * 3600) { + # 2 .. 10 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"; } else { + # less than 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);