On Tue May 18 04:45:33 2010, Andreas.Pfaff@meteoswiss.ch wrote:
Show quoted text> Hi,
>
> I have discovered a strange behaviour which happens about every 2
> weeks and is not reproducable manually. I am using the function
> System_Clock() in a Perl script running every morning at 2:00 am to
> get the current date for some calculations and archiving functions.
> Sometimes this function delivers yesterday as the date and a time
> (not the current time). The Perl script is called from a batch file
> on a Windows 2008 server.
> Fot testing purposes I am printing the date and time from my batch
> file and the result is correct. When the Perl script is called from
> that batch file (in the next line) I am printing the date again
> from within the Perl script and it is printing yesterday:
>
> Batch file:
> date /t
> 2010-05-18
>
> Perl script:
> (my $year, my $month, my $day, my $hour, my $min, my $sec, my $doy, my
> $dow, my $dst) = System_Clock();
> print qq($year, $month, $day, $hour, $min, $sec, $doy, $dow, $dst\n);
> 2010, 5, 17, 15, 18, 40, 137, 1, 0
>
> Even the $dst is wrong as we have DST currently.
>
> Am I doing soemthing wrong or is this a bug??
>
> Thanks in advance
> Andi Pfaff
Hi Andreas!
Since Date::Calc only passes through what it gets from Perl's built-in
"localtime()" (in the case when Date::Calc::XS is not installed) or your
C runtime library's "localtime()" (in the case of Date::Calc::XS),
anything can happen:
Date::Calc::PP:
sub System_Clock
{
DATECALC_USAGE('System_Clock([$gmt])') unless ((@_ == 0) or (@_ == 1));
my($year,$month,$day,$hour,$min,$sec,$doy,$dow,$dst,$gmt);
if (@_ == 1) { $gmt = shift; }
else { $gmt = 0; }
if (DateCalc_system_clock(\$year,\$month,\$day,
\$hour,\$min,\$sec,
\$doy,\$dow,\$dst,
$gmt))
{
return($year,$month,$day,$hour,$min,$sec,$doy,$dow,$dst);
}
else { DATECALC_SYSTEM_ERROR('System_Clock'); }
}
sub DateCalc_system_clock
{
my($_year,$_month,$_day,$_hour,$_min,$_sec,$_doy,$_dow,$_dst,$gmt) = @_;
my($seconds) = time();
if ($seconds >= 0)
{
$$_dst = 0;
if ($gmt) {
($$_sec,$$_min,$$_hour,$$_day,$$_month,$$_year,$$_dow,$$_doy) =
gmtime($seconds); }
else {
($$_sec,$$_min,$$_hour,$$_day,$$_month,$$_year,$$_dow,$$_doy,$$_dst) =
localtime($seconds); }
${$_year} += 1900;
${$_month}++;
${$_dow} = 7 if (${$_dow} == 0);
${$_doy}++;
if ($$_dst != 0)
{
if ($$_dst < 0) { $$_dst = -1; }
else { $$_dst = 1; }
}
return 1;
}
return 0;
}
Date::Calc::XS:
void
DateCalc_System_Clock(...)
PPCODE:
{
Z_int year;
Z_int month;
Z_int day;
Z_int hour;
Z_int min;
Z_int sec;
Z_int doy;
Z_int dow;
Z_int dst;
boolean gmt;
if ((items == 0) or (items == 1))
{
if (items == 1) gmt = (boolean) SvIV( ST(0) );
else gmt = false;
if (DateCalc_system_clock(&year,&month,&day,
&hour,&min,&sec,
&doy,&dow,&dst,
gmt))
{
EXTEND(sp,9);
PUSHs(sv_2mortal(newSViv((IV)year)));
PUSHs(sv_2mortal(newSViv((IV)month)));
PUSHs(sv_2mortal(newSViv((IV)day)));
PUSHs(sv_2mortal(newSViv((IV)hour)));
PUSHs(sv_2mortal(newSViv((IV)min)));
PUSHs(sv_2mortal(newSViv((IV)sec)));
PUSHs(sv_2mortal(newSViv((IV)doy)));
PUSHs(sv_2mortal(newSViv((IV)dow)));
PUSHs(sv_2mortal(newSViv((IV)dst)));
}
else DATECALC_SYSTEM_ERROR;
}
else croak("Usage: Date::Calc::System_Clock([gmt])");
}
boolean DateCalc_system_clock(Z_int *year, Z_int *month, Z_int *day,
Z_int *hour, Z_int *min, Z_int *sec,
Z_int *doy, Z_int *dow, Z_int *dst,
boolean gmt)
{
time_t seconds;
struct tm *date;
if (time(&seconds) >= 0)
{
if (gmt) date = gmtime(&seconds);
else date = localtime(&seconds);
if (date != NULL)
{
*year = (*date).tm_year + 1900;
*month = (*date).tm_mon + 1;
*day = (*date).tm_mday;
*hour = (*date).tm_hour;
*min = (*date).tm_min;
*sec = (*date).tm_sec;
*doy = (*date).tm_yday + 1;
*dow = (*date).tm_wday; if (*dow == 0) *dow = 7;
*dst = (*date).tm_isdst;
if (*dst != 0)
{
if (*dst < 0) *dst = -1;
else *dst = 1;
}
return(true);
}
}
return(false);
}
Unfortunately there is nothing that I can do about it; except: Have you
tried using Date::Calc::XS (just install; it will be used automatically
if it is installed) and using Date::Calc::PP, in order to check whether
the problem might be related to either the Perl or the XS implementation?
Use the following to prevent Date::Calc::XS from being loaded
(defaulting to Date::Calc::PP):
BEGIN { $Date::Calc::XS_DISABLE = 1; }
use Date::Calc qw(:all);
You can check the variable $Date::Calc::XS_OK after "use Date::Calc" in
order to see which version is actually running.
You might also check whether calling "Localtime()" instead of
"System_Clock()" makes any difference:
#!perl -w
use strict;
# BEGIN { $Date::Calc::XS_DISABLE = 1; }
use Date::Calc qw(:all);
print $Date::Calc::XS_OK ? "Date::Calc::XS is running\n" :
"Date::Calc::PP is running\n";
(my $year, my $month, my $day, my $hour, my $min, my $sec, my $doy, my
$dow, my $dst) = System_Clock();
print qq($year, $month, $day, $hour, $min, $sec, $doy, $dow, $dst\n);
($year,$month,$day, $hour,$min,$sec, $doy,$dow,$dst) = Localtime();
print qq($year, $month, $day, $hour, $min, $sec, $doy, $dow, $dst\n);
__END__
This is what I get on my FreeBSD 7.2-STABLE system:
$ perl dc.pl
Date::Calc::PP is running
2010, 5, 24, 9, 33, 15, 144, 1, 1
2010, 5, 24, 9, 33, 15, 144, 1, 1
$ perl dc.pl
Date::Calc::XS is running
2010, 5, 24, 9, 33, 46, 144, 1, 1
2010, 5, 24, 9, 33, 46, 144, 1, 1
And on my Windows XP Media Center Edition SP3:
Date::Calc::XS is running
2010, 5, 24, 9, 36, 7, 144, 1, 1
2010, 5, 24, 9, 36, 7, 144, 1, 1
Date::Calc::PP is running
2010, 5, 24, 9, 36, 21, 144, 1, 1
2010, 5, 24, 9, 36, 21, 144, 1, 1
Good luck!