Håkon Hægland
Håkon Hægland

Reputation: 40778

Sort dates using DateTime->compare()

I am trying to sort an array of dates chronologically using DateTime:

use strict;
use warnings;
use Data::Printer;
use Date::Time;
use DateTime::Format::Strptime;

my $strp = DateTime::Format::Strptime->new(
    pattern   => '%D',
    time_zone => 'America/New_York',
);
 my @dates = (
    [1, '5/18/2011'],
    [2, '6/18/2011'],
    [3, '6/18/2014'],
    [4, '6/18/2010'],
);

my @res = sort { date_sort( $a->[1], $b->[1], $strp ) } @dates;

p \@res;

sub date_sort {
    my ( $date1, $date2, $strp ) = @_;

    my $dt1 = $strp->parse_datetime($date1);
    my $dt2 = $strp->parse_datetime($date2);
    return DateTime->compare($dt1, $dt2);
}

Output:

[
    [0] [
        [0] 1,
        [1] "5/18/2011"
    ],
    [1] [
        [0] 2,
        [1] "6/18/2011"
    ],
    [2] [
        [0] 3,
        [1] "6/18/2014"
    ],
    [3] [
        [0] 4,
        [1] "6/18/2010"
    ]
]

Expected output:

[
    [0] [
        [0] 4,
        [1] "6/18/2010"
    ],
    [1] [
        [0] 1,
        [1] "5/18/2011"
    ],
    [2] [
        [0] 2,
        [1] "6/18/2011"
    ],
    [3] [
        [0] 3,
        [1] "6/18/2014"
    ]
]

Upvotes: 1

Views: 200

Answers (2)

ikegami
ikegami

Reputation: 386361

[ This is a comment rather than an answer ]

Using DateTime is overkill here.

sub date_sort {
    my ( $date1, $date2 ) = @_;
    $date1 = sprintf '%3$s%1$02s%2$02s', split /\//, $date1;
    $date2 = sprintf '%3$s%1$02s%2$02s', split /\//, $date2;
    return $date1 cmp $date2;
}

my @res = sort { date_sort( $a->[1], $b->[1] ) } @dates;

Better yet,

use Sort::Key qw( ikeysort );

sub date_key {
    my ( $date ) = @_;
    return sprintf '%3$s%1$02s%2$02s', split /\//, $date;
}

my @res = ikeysort { date_key( $_->[1] ) } @dates;

Upvotes: 3

mob
mob

Reputation: 118645

%D is equivalent to %m/%d/%y, where %y is a 2-digit year. You want to use the format%m/%d/%Y to support a four digit year. With %D (and %m/%d/%y), all of your input is interpreted as having the year 2020.

Upvotes: 3

Related Questions