Perl:在/Date/Manip.pm中使用数字lt(<)中的未初始化值

时间:2020-03-05 18:57:06  来源:igfitidea点击:

这让我感到困惑。该代码可在另一台服务器上使用,但在Perl v5.8.8上失败,并且今天从CPAN加载了Date :: Manip。

Warning:
Use of uninitialized value in numeric lt (<) at /home/downside/lib/Date/Manip.pm line 3327.
at dailyupdate.pl line 13
        main::__ANON__('Use of uninitialized value in numeric lt (<) at
/home/downsid...') called at
/home/downside/lib/Date/Manip.pm line 3327
        Date::Manip::Date_SecsSince1970GMT(09, 16, 2008, 00, 21, 22) called at
/home/downside/lib/Date/Manip.pm line 1905
        Date::Manip::UnixDate('today', '%Y-%m-%d') called at
TICKER/SYMBOLS/updatesymbols.pm line 122
        TICKER::SYMBOLS::updatesymbols::getdate() called at
TICKER/SYMBOLS/updatesymbols.pm line 439
        TICKER::SYMBOLS::updatesymbols::updatesymbol('DBI::db=HASH(0x87fcc34)',
'TICKER::SYMBOLS::symbol=HASH(0x8a43540)') called at
TICKER/SYMBOLS/updatesymbols.pm line 565
TICKER::SYMBOLS::updatesymbols::updatesymbols('DBI::db=HASH(0x87fcc34)', 1, 0, -1) called at
dailyupdate.pl line 149
        EDGAR::updatesymbols('DBI::db=HASH(0x87fcc34)', 1, 0, -1) called at
dailyupdate.pl line 180
        EDGAR::dailyupdate() called at dailyupdate.pl line 193

失败的代码很简单:

sub getdate()
{    my $err;                ## today
    &Date::Manip::Date_Init('TZ=EST5EDT');       
    my $today = Date::Manip::UnixDate('today','%Y-%m-%d'); ## today's date
    ####print "Today is ",$today,"\n";        ## ***TEMP***
    return($today);
}

这是正确的;日期:: Manip的"今天"失败。

Date :: Manip中失败的行是:

my($tz)=$Cnf{"ConvTZ"};  
  $tz=$Cnf{"TZ"}  if (! $tz);  
  $tz=$Zone{"n2o"}{lc($tz)}  if ($tz !~ /^[+-]\d{4}$/);  

  my($tzs)=1;  
  $tzs=-1 if ($tz<0); ### ERROR OCCURS HERE

因此Date :: Manip假设已使用元素" ConvTZ"或者" TZ"初始化了" $ Cnf"。那些是在Date_Init中初始化的,因此应该注意这一点。

这只是在我的大型程序中失败了。如果我只提取上面的"getdate()"
并独立运行,没有错误。所以有一些关于
影响这一点的全球环境。

这似乎是一个已知但尚未理解的问题。如果我们在Google搜索
"使用未初始化的起息日操作"有大约2400个命中。
MythTV和grepmail已报告此错误。

解决方案

回答

几乎可以确定主机没有为我们指定的时区定义,这就是导致值未定义的原因。

我们是否检查过主机上是否确实存在同名的TZ定义文件?

回答

日期:: Manip应该是独立的。它在其自己的来源中具有所有时区的列表,紧跟在" $ zonesrfc ="之后。

回答

我们可以尝试单步调试器以查看究竟出了什么问题吗?很可能是%Zone错误的%tz可能在第1行或者第2行中正确设置,但随后在第3行中的查找失败,最终出现undef。

编辑:%Date :: Manip :: Cnf和%Date :: Manip :: Zone是全局变量,因此我们应该能够在调用Date :: Manip :: Date_Init之前和之后对它们进行转储。如果我正确地阅读了源代码,则%Cnf应该在调用Date_Init之前包含配置选项的基本框架,并且%Zone应该为空;在Date_Init之后,TZ应该具有我们选择的值,并且%Zone应该由时区的查找表填充。

我在%Cnf中看到了对.DateManip.cnf的引用,这可能是值得一看的,是否可能是主目录或者当前工作目录中有这样的文件,它覆盖了默认设置?

回答

它是Win32的Date :: Manip版本5.48-5.54中的错误。我在使用时区的标准/日光变体方面遇到困难,例如'EST5EDT','US / Eastern'。似乎唯一起作用的时区是那些没有夏令时的时区,例如'美东时间'。

可以在Date :: Manip模块中关闭时区转换处理:

Date::Manip::Date_Init("ConvTZ=IGNORE");

如果正确处理日期,这将产生不良的副作用。除非我们确信我们永远不会处理来自不同时区的日期,否则我不会使用此替代方法。