在Perl中将YYYYMMDD日期拆分为3部分

3

如何将格式为YYYYMMDD的日期拆分为其组成部分?

my ($yyyy, $mm, $dd) = $date =~ /(\4d+)(\2d+)(\2d+)/;
5个回答

15
my ($year, $month, $day) = unpack "A4A2A2", $date;

packunpack 是很强大但很少被使用的内置函数。


3
unpack是Perl中最快的函数,特别适用于处理固定宽度的数据。 - vol7ron
你能用unpack进行错误检查吗?例如:在此之后加上一个or 'die "Wrong format"'语句吗? - syker
强大的功能却缺乏有效验证 - ysth
@ysth:使用正则表达式也无法正确验证。它会允许9999-99-99作为日期,尽管这显然不是有效的日期。 - Leon Timmermans
1
这取决于$date的存储方式,unpack仅适用于固定宽度。根据我的例子,如果除了8个数字(甚至空格)之外还有其他文本,则unpack将会出错。这就是为什么我的答案会添加一些预验证,使用\b - vol7ron
@Leon Timmermans:是的,但这是一个很好的第一步;至少你知道你的变量是数字并且可以按照数字处理。 - ysth

4
#!/usr/bin/perl -w

use strict;

   sub main{
      my $date = "some text with the numbers 2010063011 and more text";
      print "Input Date: $date\n";

      my ($year, $month, $day) = $date =~ /\b(\d{4})(\d{2})(\d{2})\b/;      
      print qq{
               Date:  $date
               Year:  $year
               Month: $month
               Day:   $day\n} if (defined $year && defined $month && defined $day);
   }

   main();

请注意,这将查找正则表达式中的第一个日期,它不适用于2010063011,因为它不是一个日期,但它适用于20100630,这就是您想要的。


你的方法和unpack方法都很有道理,谢谢你在unpack答案中添加了那个注释。 - user376314

4
my ($year, $month, $day) = $date =~ /^(\d{4})(\d{2})(\d{2})\z/a
    or die "bad date: $date";

也许是想用 $ 而不是 \z - jdehaan
我能用 o 替代吗?我已经在另外两个地方使用了它(不过不是在循环中)。 - syker
@syker:请参考perldoc perlre了解正则表达式语法的详细信息(例如,z、$、\d和其他组件的含义)。 - Ether
@syker: @jdehaan: $ 的意思是字符串的结尾或 \n 并且后面没有其他字符。由于指定的格式不应该有 \n,所以我使用了 \z。 - ysth
@syker:这里与 o 无关 - 我不明白你建议用什么来替换它。 - ysth
请注意,\d 匹配任何 Unicode 数字,而不仅仅是拉丁十进制数字。因此,如果您想进行输入验证,请使用 [0-9] 而不是 \d - dolmen

0
每当我需要处理日期时,我都会使用DateTime模块。你可以从CPAN上获取它。

-1
请注意,\d 匹配任何 Unicode 数字,而不仅仅是拉丁十进制数字。
因此,如果您想进行输入验证,请使用 '[0-9]' 而不是 '\d'。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接