Subject: | sunset->previous can return time in future (+patch) |
There is a problem in the calculation of previous/next sunrise/sunset
times: under some conditions, it would return a "previous" sunset time
that was in the future (and also for next sunrises).
Have attached a test script that shows the problem.
Examples of script:
$ /tmp/srTest.pl 1212537601 1 1 46.74575,65.2488
inc=1, count=1, lat=46.74575, long=65.2488
Error:
sunSetPrevTime > t
time = 1212537601 : Tue Jun 3 21:30:01 2008
sunRisePrevTime = 1212481736 : Tue Jun 3 05:58:56 2008
sunRiseNextTime = 1212568106 : Wed Jun 4 05:58:26 2008
sunSetPrevTime = 1212538107 : Tue Jun 3 21:38:27 2008
sunSetNextTime = 1212624556 : Wed Jun 4 21:39:16 2008
and
$ /tmp/srTest.pl 1212536601 1 1 64.74575,220.2488
inc=1, count=1, lat=64.74575, long=220.2488
Error:
sunRiseNextTime < t
time = 1212536601 : Tue Jun 3 21:13:21 2008
sunRisePrevTime = 1212423624 : Mon Jun 2 13:50:24 2008
sunRiseNextTime = 1212509861 : Tue Jun 3 13:47:41 2008
sunSetPrevTime = 1212498208 : Tue Jun 3 10:33:28 2008
sunSetNextTime = 1212584787 : Wed Jun 4 10:36:27 2008
For the previous sunset problem: the code computes the sunset
for the "current" day, and if it is greater than the requested time,
returns the sunset time for the previous day. But if the "current" day
is actually "tomorrow" (which can happen due to the longitude), the
"previous" day's sunset may still be in the future. A solution is
to add another test and, if needed, compute and return the sunset time for
the "previous previous" day.
The attached patch fixes the two problems shown above and the two other
possible (but not confirmed) similar problems.
Misc info: DateTime::Event::Sunrise, version 0.0501;
perl -v
This is perl, v5.8.5 built for i386-linux-thread-multi
Copyright 1987-2004, Larry Wall
Perl may be copied only under the terms of either the Artistic License
or the
GNU General Public License, which may be found in the Perl 5 source kit.
Complete documentation for Perl, including FAQ lists, should be found on
this system using `man perl' or `perldoc perl'. If you have access to the
Internet, point your browser at http://www.perl.com/, the Perl Home Page.
os: Linux xxx 2.6.9-67.0.7.ELsmp #1 SMP Sat Mar 15 06:54:55 EDT 2008
i686 i686 i386 GNU/Linux
Subject: | DateTime-Event-Sunrise.pm-patch.01 |
Message body not shown because it is not plain text.
Subject: | srTest.pl |
#!/usr/bin/perl
use DateTime();
use DateTime::Event::Sunrise();
# Script to test DateTime::Event::Sunrise() results in a particular
# time range.
if (@ARGV == 0) {
@ARGV = (1212537601, 1, 1, '46.74575,65.2488');
} else {
die "Usage: $0 epochSeconds incSeconds count lat,long\n"
if @ARGV != 4;
}
my $t = $ARGV[0];
my $inc = $ARGV[1];
my $count = $ARGV[2];
my ($latitude, $longitude) = split(',', $ARGV[3]);
my $dt = DateTime->from_epoch(epoch => $t);
my $sunRisePrevTime;
my $sunRiseNextTime;
my $sunSetPrevTime;
my $sunSetNextTime;
my @errors = ();
my $sunrise = DateTime::Event::Sunrise->sunrise(
longitude => -$longitude,
latitude => $latitude,
iteration => '1',
);
my $sunset = DateTime::Event::Sunrise->sunset(
longitude => -$longitude,
latitude => $latitude,
iteration => '1',
);
# Error examples:
#
# for lat/long: 46.74575,65.2488
# sunSetPrevTime(1212538107) > dt(1212537601)
# Jun 3 21:38:27 2008 > Jun 3 21:30:00 2008
# repeat by: srTest.pl 1212537601 1 1 46.74575,65.2488
# for lat/long: 64.74575,220.2488
# sunRiseNextTime(1212509861) < dt(1212536601)
# Jun 3 13:47:41 2008 < Jun 3 21:13:21 2008
# repeat by: srTest.pl 1212536601 1 1 64.74575,220.2488
#
#
print "inc=$inc, count=$count, lat=$latitude, long=$longitude\n";
for (my $i = 0; $i < $count; ++$i) {
$sunRisePrevTime = $sunrise->current($dt)->epoch();
$sunRiseNextTime = $sunrise->next($dt)->epoch();
$sunSetPrevTime = $sunset->previous($dt)->epoch();
$sunSetNextTime = $sunset->next($dt)->epoch();
@errors = ();
if ($sunRisePrevTime >= $sunRiseNextTime) {
push(@errors, "sunRisePrevTime >= sunRiseNextTime");
}
if ($sunSetPrevTime >= $sunSetNextTime) {
push(@errors, "sunSetPrevTime >= sunSetNextTime");
}
if ($sunRisePrevTime > $t) {
push(@errors, "sunRisePrevTime > t");
}
if ($sunSetPrevTime > $t) {
push(@errors, "sunSetPrevTime > t");
}
if ($sunRiseNextTime < $t) {
push(@errors, "sunRiseNextTime < t");
}
if ($sunSetNextTime < $t) {
push(@errors, "sunSetNextTime < t");
}
if (@errors || $i % (60 * 60) == 0) {
if (@errors) {
print "Error:\n\t", join("\n\t", @errors), "\n";
}
print "time = $t : " . localtime($t) . "\n";
print "sunRisePrevTime = $sunRisePrevTime : " . localtime($sunRisePrevTime)
. "\n";
print "sunRiseNextTime = $sunRiseNextTime : " . localtime($sunRiseNextTime)
. "\n";
print "sunSetPrevTime = $sunSetPrevTime : " . localtime($sunSetPrevTime)
. "\n";
$| = 1;
print "sunSetNextTime = $sunSetNextTime : " . localtime($sunSetNextTime)
. "\n";
$| = 0;
}
$dt->add('seconds' => $inc);
$t += $inc;
}