Perl 将格式化日期转换为 y-m-d H:M
Perl converting formatting date to y-m-d H:M
我 运行 遇到将日期 Apr 9 2017 3:45:00:000AM
转换为 2017-04-09 03:45:00
的问题
这是我试过的。
use DateTime::Format::Strptime;
my $strp = DateTime::Format::Strptime->new(pattern => '%h %d %Y %H:%M',);
$start_date = $strp->parse_datetime('Apr 9 2017 3:45:00:000AM');
打印 2017-04-09T03:45:00
而不是 2017-04-09 03:45:00
。试图获得 24 小时制,所以当我将 AM
切换到 PM
时,同时打印。
以下代码演示了如何在没有任何模块的情况下实现所需的输出
use strict;
use warnings;
use feature 'say';
my $date = 'Apr 9 2017 3:45:00:000AM';
my @fields = qw/month mday year hour min sec usec/;
my %months = ( Jan => 1, Feb => 2, Mar => 3,
Apr => 4, May => 5, Jun => 6,
Jul => 7, Aug => 8, Sep => 9,
Oct => 10, Nov => 11, Dec => 12
);
my %parts;
@parts{@fields} = split "[ :]+", $date;
$parts{hour} += 12 if $parts{usec} =~ /PM/;
$parts{month} = $months{ $parts{month} };
printf "%04d-%02d-%02d %02d:%02d:%02d\n",
@parts{qw/year month mday hour min sec/};
借助模块的 Perl 代码
use strict;
use warnings;
use feature 'say';
use DateTime::Format::DateParse;
my($date, $dt);
$date = 'Apr 9 2017 3:45:00:000AM';
$date =~ s/:(\d{3}[AP]M)/./;
$dt = DateTime::Format::DateParse->parse_datetime( $date );
$date = $dt;
$date =~ s/T/ /;
say $date;
更新 请参阅结尾以获得 strptime
模式以正确解析显示的输入字符串格式
显示的内容有效,† 因此显示的 DateTime::Format::Strptime constructor returns a DateTime
object. But when an object is simply printed then one gets the stringification。
因此您需要根据需要对其进行格式化以便打印。一般的方法是 strftime
say $start_date->strftime("%F %T");
其中 %F
和 %T
都是简写,参见 strftime patterns
或者结合基本的ymd
和hms
方法
say $start_date->ymd('-') . ' ' . $start_date->hms(':');
查看文档并根据需要调整 if/as。有些细节没看懂
† 在这个确切的例子中它只是偶然工作,因为在 new
中用于解析的模式对于显示的输入格式是错误的,并且是也不符合规定的要求
显示的模式没有秒的格式说明符,也没有跟随它的毫秒的格式说明符,也没有以下 AM/PM
的格式说明符——所有这些都在输入字符串中。所以一般来说,所示形式的输入无法用所示模式正确解析
%H
匹配 00-23
小时,因此不是 12 小时制,这是按预期说明的,并且因 AM
的存在而隐含。 (它仍然匹配一个 12 小时制的数字,但一旦添加了缺少的 AM/PM 格式说明符,它就不会匹配。)
OP 中的模式有效并正确解析给定的输入,因为 03:45...
恰好是 在 AM, 和 该模块使用正则表达式匹配给定字符串中任意位置的给定模式(默认情况下),因此 %H:%M
匹配 03:45
并且输入字符串的其余部分无关紧要。如果我们在构造函数中打开 strict
这将失败。请参阅文档。
假设显示的输入是我们需要的正确部分
my $strp = DateTime::Format::Strptime->new(
pattern => '%h %d %Y %I:%M:%S%3N%p'
);
此处 %I
用于 12 小时制 (1-12),添加 %S
用于秒,%3N
用于毫秒(请参阅文档中的页面了解模式,链接上面),以及 %p
对于 AM/PM.
其余部分按原样工作,并以上面给出的所需格式打印。
您的代码有两个问题。首先,您用来解析日期的模式不正确:%H
用于 24 小时格式小时。相反,您应该结合使用 %i
(12 小时)和 %p
(AM
/PM
)。其次,要打印一个 DateTime
对象,你应该先格式化它(例如使用 ->strftime
或 ->ymd()
)。
然而,日期中的毫秒数有点问题,因为 strptime
没有匹配毫秒数的选项。我建议先从你的日期中删除它们,然后才用 strptime
:
解析日期
use DateTime::Format::Strptime;
my $date = 'Apr 9 2017 3:45:00:505PM';
# Removing milliseconds from date
$date =~ s/:(\d{3})(?=AM|PM)//;
my $milliseconds = ;
my $strp = DateTime::Format::Strptime->new(pattern => '%h %d %Y %I:%M:%S%p',);
my $start_date = $strp->parse_datetime($date);
# Taking into account the milliseconds that were removed earlier
$start_date->add(seconds => 1) if $milliseconds > 500;
say $start_date->strftime("%F %T");
我 运行 遇到将日期 Apr 9 2017 3:45:00:000AM
转换为 2017-04-09 03:45:00
这是我试过的。
use DateTime::Format::Strptime;
my $strp = DateTime::Format::Strptime->new(pattern => '%h %d %Y %H:%M',);
$start_date = $strp->parse_datetime('Apr 9 2017 3:45:00:000AM');
打印 2017-04-09T03:45:00
而不是 2017-04-09 03:45:00
。试图获得 24 小时制,所以当我将 AM
切换到 PM
时,同时打印。
以下代码演示了如何在没有任何模块的情况下实现所需的输出
use strict;
use warnings;
use feature 'say';
my $date = 'Apr 9 2017 3:45:00:000AM';
my @fields = qw/month mday year hour min sec usec/;
my %months = ( Jan => 1, Feb => 2, Mar => 3,
Apr => 4, May => 5, Jun => 6,
Jul => 7, Aug => 8, Sep => 9,
Oct => 10, Nov => 11, Dec => 12
);
my %parts;
@parts{@fields} = split "[ :]+", $date;
$parts{hour} += 12 if $parts{usec} =~ /PM/;
$parts{month} = $months{ $parts{month} };
printf "%04d-%02d-%02d %02d:%02d:%02d\n",
@parts{qw/year month mday hour min sec/};
借助模块的 Perl 代码
use strict;
use warnings;
use feature 'say';
use DateTime::Format::DateParse;
my($date, $dt);
$date = 'Apr 9 2017 3:45:00:000AM';
$date =~ s/:(\d{3}[AP]M)/./;
$dt = DateTime::Format::DateParse->parse_datetime( $date );
$date = $dt;
$date =~ s/T/ /;
say $date;
更新 请参阅结尾以获得 strptime
模式以正确解析显示的输入字符串格式
显示的内容有效,† 因此显示的 DateTime::Format::Strptime constructor returns a DateTime
object. But when an object is simply printed then one gets the stringification。
因此您需要根据需要对其进行格式化以便打印。一般的方法是 strftime
say $start_date->strftime("%F %T");
其中 %F
和 %T
都是简写,参见 strftime patterns
或者结合基本的ymd
和hms
方法
say $start_date->ymd('-') . ' ' . $start_date->hms(':');
查看文档并根据需要调整 if/as。有些细节没看懂
† 在这个确切的例子中它只是偶然工作,因为在 new
中用于解析的模式对于显示的输入格式是错误的,并且是也不符合规定的要求
显示的模式没有秒的格式说明符,也没有跟随它的毫秒的格式说明符,也没有以下
AM/PM
的格式说明符——所有这些都在输入字符串中。所以一般来说,所示形式的输入无法用所示模式正确解析%H
匹配00-23
小时,因此不是 12 小时制,这是按预期说明的,并且因AM
的存在而隐含。 (它仍然匹配一个 12 小时制的数字,但一旦添加了缺少的 AM/PM 格式说明符,它就不会匹配。)
OP 中的模式有效并正确解析给定的输入,因为 03:45...
恰好是 在 AM, 和 该模块使用正则表达式匹配给定字符串中任意位置的给定模式(默认情况下),因此 %H:%M
匹配 03:45
并且输入字符串的其余部分无关紧要。如果我们在构造函数中打开 strict
这将失败。请参阅文档。
假设显示的输入是我们需要的正确部分
my $strp = DateTime::Format::Strptime->new(
pattern => '%h %d %Y %I:%M:%S%3N%p'
);
此处 %I
用于 12 小时制 (1-12),添加 %S
用于秒,%3N
用于毫秒(请参阅文档中的页面了解模式,链接上面),以及 %p
对于 AM/PM.
其余部分按原样工作,并以上面给出的所需格式打印。
您的代码有两个问题。首先,您用来解析日期的模式不正确:%H
用于 24 小时格式小时。相反,您应该结合使用 %i
(12 小时)和 %p
(AM
/PM
)。其次,要打印一个 DateTime
对象,你应该先格式化它(例如使用 ->strftime
或 ->ymd()
)。
然而,日期中的毫秒数有点问题,因为 strptime
没有匹配毫秒数的选项。我建议先从你的日期中删除它们,然后才用 strptime
:
use DateTime::Format::Strptime;
my $date = 'Apr 9 2017 3:45:00:505PM';
# Removing milliseconds from date
$date =~ s/:(\d{3})(?=AM|PM)//;
my $milliseconds = ;
my $strp = DateTime::Format::Strptime->new(pattern => '%h %d %Y %I:%M:%S%p',);
my $start_date = $strp->parse_datetime($date);
# Taking into account the milliseconds that were removed earlier
$start_date->add(seconds => 1) if $milliseconds > 500;
say $start_date->strftime("%F %T");