什么是Perl正则表达式将“2012年12月26日12:00 AM”等日期转换为yyyymmdd?

时间:2012-09-21 12:49:32

标签: regex perl datetime type-conversion

我很难找到使用Perl正则表达式进行此特定转换(这些日期格式)的示例,但无济于事。有人可以帮我转换这些格式之间的日期吗?

Dec 26 2012 12:00AM ==>  201212126

以下是我最初的尝试,但是运行速度太慢(很明显,我使用了5次这样的子项,这很荒谬)。

# Format the input time to yyyymmdd from 'Dec 26 2012 12:00AM' like format.
sub formatTime($)
{
    #Get passed in value of format 'Dec 26 2012 12:00AM'.
    my $col = shift; 

    if (substr($col, 4, 1) eq " "){
        substr($col, 4, 1) = "0";
    }

    return substr($col, 7, 4).$months{substr($col, 0, 3)}.substr($col, 4, 2);
}

注意:这是为了工作,用于将输入文件转换为非常大的数据包摄取,不幸的是,平台上不支持python,这是我编写脚本的首选语言。我尝试制作自己的Perl正则表达式,但我没有时间阅读并在做其他部分时弄明白。昨天我已经浪费了大部分时间编写Perl脚本并在其余部分学习,这种转换只需要花费太长时间。

3 个答案:

答案 0 :(得分:19)

我建议你使用模块DateTime + DateTime::Format::Strptime

#!/usr/local/bin/perl
use strict;

use DateTime;
use DateTime::Format::Strptime;

my $strp = DateTime::Format::Strptime->new(
      pattern => '%b %d %Y %l:%M%p',
      locale  => 'en_US',
);

# convert date to 
my $date = 'Dec 26 2012 10:10AM';
my $dt   = $strp->parse_datetime( $date );
printf "%s -> %s\n", $date, $dt->strftime("%Y-%m-%d %H:%M");

<强>输出

Dec 26 2012 10:10AM -> 2012-12-26 10:10

答案 1 :(得分:1)

那么,Dec 26 2012 12:00AM的哪些部分很有意思?

Dec    26   2012     12:00      AM
$month $day $year $hour:$minute $pm

因此,我们只需定义普通的正则表达式,捕获有趣的信息,并将它们放入适当的变量中:

my ($month, $day, $year, $hour, $minute, $pm)
  = ($string =~ m{
        (\w{3})   \s+             # 3 word characters
        (\d{1,2}) \s+             # 1 or 2 digits
        (\d{4})   \s+             # 4 digits
        (\d{2}) : (\d{2}) (AM|PM) # the hour, minute and AM/PM context
      }ix;
    );

接下来,我们将月份设为数字并使用AM / PM信息:

$month = {
  Jan => 1,
  Feb => 2,
  ...
  Dec => 12,
}->{$month} or die "Unknown month $month";

$hour += $pm =~ /pm/i ? 12 : 0; # if $pm contains "pm", then add 12 h

然后,我们通过sprintf

构建一个适当的零填充字符串
my $format_string = "%04d%02d%02d" . ($include_hour ? "%02d%02d" : "");
my $date = sprintf $format_string,
  $year, $month, $day, $hour, $minute;

如果你有野心,你也可以轻松添加时区; - )

当输入类似16:00PM时,此方法会产生奇怪的结果,因为这会输出2800作为时间,这显然是错误的。如果这可能是一个问题,请仅pm更正if $hour <= 12。但是,这仅在$include_hour设置为真值时才有意义。

答案 2 :(得分:-1)

use strict;
use warnings;

my $str = "Dec 26 2012 12:00AM";

my %months = (
    Jan => "01",
    [...]
    Dec => "12"
);
$str =~ /^(\w{3}) (\d{1,2}) (\d{4})/; 

print $3.$months{$1}.$2;