为什么Perl DateTime::Format::ISO8601解析文件日期报错但硬编码正常
问题原因
- 读取文件行时未处理末尾换行符,且按逗号拆分字段后,每个日期字段首尾带有多余空白字符:
DateTime::Format::ISO8601不会自动过滤字符串首尾的空白、换行符,你报错信息中的日期前带有多余空格,就是导致格式识别失败的直接原因。硬编码测试正常是因为硬编码的日期字符串没有多余空白和换行,符合ISO8601格式要求。 - 模块名大小写错误:你代码中写的是
use Datetime::Format::ISO8601,正确模块名应为DateTime::Format::ISO8601,T字母需要大写,大小写不匹配属于潜在兼容问题。
解决方法
按以下步骤修改代码即可:
- 读取文件每行后先执行
chomp去掉末尾换行符 - 拆分字段后对每个字段做去首尾空白处理
- 修正模块名大小写
修改后可正常运行的代码参考:
use strict; use warnings; # 建议开启,方便排查其他潜在问题 use DateTime; use DateTime::Span; use DateTime::Format::ISO8601; # 修正模块名大小写 open(FH_Comp, "<", "C:\\Perl_Scripts\\Stock_List_COMPARE.txt") or die("Cannot open Stock_List_COMPARE.txt: $!\n"); my @lines = <FH_Comp>; close(FH_Comp); open(FH_CompRev, "<", "C:\\Perl_Scripts\\Stock_List_Rev.txt") or die("Cannot open Stock_List_Rev.txt: $!\n"); my @compRev = <FH_CompRev>; close(FH_CompRev); my $iso8601 = DateTime::Format::ISO8601->new; foreach $lines (@lines) { chomp $lines; # 移除行尾换行符 @COMPlist = split(",",$lines); $_ =~ s/^\s+|\s+$//g for @COMPlist; # 移除每个字段的首尾空白 foreach $compRev (@compRev) { chomp $compRev; # 移除行尾换行符 @REVlist = split(",",$compRev); $_ =~ s/^\s+|\s+$//g for @REVlist; # 移除每个字段的首尾空白 my $dt_set = DateTime::Span->from_datetimes( start => $iso8601->parse_datetime($REVlist[0]), before => $iso8601->parse_datetime($REVlist[4]), ); if ( $dt_set->contains( $iso8601->parse_datetime($COMPlist[0]) ) ) { print "Within date range\n"; $Total1 = $COMPlist[2] + $REVlist[2]; print "ADJ Date is '$COMPlist[0]' => $COMPlist[2] + $REVlist[2] = " . $Total1 . " ! '$REVlist[0]' or '$REVlist[4]'\n"; } else { print "Not within date range\n"; } } }
内容的提问来源于stack exchange,提问作者Paul Yang
相关产品推荐
相关产品推荐

