From 08e8660ad9a031ed7e2dc739e01c646ab79f5662 Mon Sep 17 00:00:00 2001 From: "Peter J. Holzer" Date: Sat, 4 Jun 2016 13:17:19 +0200 Subject: [PATCH] Extend usable time range to about 200 years Previously the maximum grid spacing was 3 months which became impractical with more than about 10 years of data. Now there are also 1 year and 5 year grid spacings. Also worked around timelocal() DWIMery which would return wrong values for much of the 20th century. --- TimeSeries.pm | 45 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/TimeSeries.pm b/TimeSeries.pm index d2a8070..1206403 100644 --- a/TimeSeries.pm +++ b/TimeSeries.pm @@ -31,7 +31,7 @@ use Time::Local; use Data::Dumper; use HTTP::Date qw(parse_date); use Time::Local qw(timegm_nocheck); -use POSIX qw(strftime); +use POSIX qw(floor strftime); our $VERSION = do { my @r=(q$Revision: 1.24 $=~/\d+/g);sprintf "%d."."%02d"x$#r,@r}; @@ -404,8 +404,10 @@ sub plot { my @tics = get_ticks($firsttime, $lasttime); + # force tick values to look like fp numbers to avoid warnings about + # exceeding the int range from gnuplot print $ctlfh "set xtics rotate (", - join(", ", map sprintf(qq|"%s" %d|, $_->[1], $_->[0]), @tics), + join(", ", map sprintf(qq|"%s" %.16e|, $_->[1], $_->[0]), @tics), ")\n"; # what to plot @@ -499,7 +501,32 @@ sub get_ticks { my $label; my $nexttime; - if ($lasttime - $firsttime > 3 * 365 * 24 * 3600) { + if ($lasttime - $firsttime > 50 * 365 * 24 * 3600) { + # more than 50 years: 1 tick/5 years + + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($firsttime); + $sec = $min = $hour = 0; + $mday = 1; + $mon = 0; + $year = floor($year / 5) * 5; + $firsttime = timelocal($sec,$min,$hour,$mday,$mon,$year); + + $label = '%Y-%m-%d'; + + $nexttime = sub { return add_years($_[0], 5) }; + } elsif ($lasttime - $firsttime > 10 * 365 * 24 * 3600) { + # more than 10 years: 1 tick/year + + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($firsttime); + $sec = $min = $hour = 0; + $mday = 1; + $mon = 0; + $firsttime = timelocal($sec,$min,$hour,$mday,$mon,$year); + + $label = '%Y-%m-%d'; + + $nexttime = sub { return add_years($_[0], 1) }; + } elsif ($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); @@ -601,11 +628,21 @@ sub add_months { my ($time, $d_mon) = @_; my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time); + $year += 1900; # localtime/timelocal mismatch $mon += $d_mon; if ($mon >= 12) { $mon -= 12; $year++; } $time = timelocal($sec,$min,$hour,$mday,$mon,$year); -}; +} + +sub add_years { + my ($time, $d_year) = @_; + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) + = localtime($time); + $year += 1900; # localtime/timelocal mismatch + $year += $d_year; + $time = timelocal($sec,$min,$hour,$mday,$mon,$year); +} 1;