除了 12 小时时间之外,字符串可以简单地按词法排序。
此解决方案使用Schwartzian 变换来更改用于对字符串进行排序的键。它只是将 12 添加到任何以该结尾的字符串的小时字段中PM
并按其排序。
use strict;
use warnings;
my @data = <DATA>;
chomp @data;
my @sorted = map $_->[0],
sort { $a->[1] cmp $b->[1] }
map { (my $dt = $_) =~ s/(\d\d)(?=:\d\d:\d\d PM)/$1+12/e; [$_, $dt] } @data;
print "$_\n" for @sorted;
__DATA__
2012-07-24 10:05:08 AM
2012-07-26 10:13:58 AM
2012-07-24 10:13:58 AM
2012-07-24 10:57:50 AM
2012-07-24 11:15:03 AM
2012-07-24 11:26:08 PM
2012-07-25 11:26:08 PM
输出
2012-07-24 10:05:08 AM
2012-07-24 10:13:58 AM
2012-07-24 10:57:50 AM
2012-07-24 11:15:03 AM
2012-07-24 11:26:08 PM
2012-07-25 11:26:08 PM
2012-07-26 10:13:58 AM
更新
正如 steffen 所指出的,即使在调整了上午/下午、午夜和中午的时间之后,仍然会阻止简单的字符串排序工作。
该程序使用核心Time::Piece
模块以 ISO 8601 格式重新格式化日期/时间2000-02-29T12:34:56
,可以按词法排序。
use strict;
use warnings;
use Time::Piece;
my @data = <DATA>;
chomp @data;
my @sorted = map $_->[0],
sort { $a->[1] cmp $b->[1] }
map { [ $_, toISO8601($_) ] } @data;
sub toISO8601 {
Time::Piece->strptime(@_, '%Y-%m-%d %I:%M:%S %p')->datetime;
}
print "$_\n" for @sorted;
__DATA__
2012-07-24 10:05:08 AM
2012-07-26 10:13:58 AM
2012-07-24 10:13:58 AM
2012-07-24 10:57:50 AM
2012-07-24 11:15:03 AM
2012-07-24 11:26:08 PM
2012-07-25 11:26:08 PM
2012-08-01 01:00:00 PM
2012-08-01 12:30:00 PM
2012-08-01 12:00:00 PM
2012-08-01 11:30:00 AM
2012-08-01 01:00:00 AM
2012-08-01 12:30:00 AM
2012-08-01 12:00:00 AM
输出
2012-07-24 10:05:08 AM
2012-07-24 10:13:58 AM
2012-07-24 10:57:50 AM
2012-07-24 11:15:03 AM
2012-07-24 11:26:08 PM
2012-07-25 11:26:08 PM
2012-07-26 10:13:58 AM
2012-08-01 12:00:00 AM
2012-08-01 12:30:00 AM
2012-08-01 01:00:00 AM
2012-08-01 11:30:00 AM
2012-08-01 12:00:00 PM
2012-08-01 12:30:00 PM
2012-08-01 01:00:00 PM