文字列は、12時間の時間を除いて、単純に字句的に並べ替えることができます。
このソリューションでは、シュワルツ変換を使用して、文字列の並べ替えに使用されるキーを変更します。で終わる文字列の時間フィールドに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
ISO8601形式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