Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris

How to get minimum start date in these start dates ?

by Anonymous Monk
on Jul 10, 2006 at 07:23 UTC ( #560082=perlquestion: print w/replies, xml ) Need Help??
Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi monks,

I have a array with my start dates with DD/MM/YYYY format, I need minimum least start date from the group of dates. Please give me idea or codes ?

@start_date = qw(01-06-2007 01-08-2006 01-06-2006 01-07-2007 06-01-2007);

o/p : 01-06-2006

Edited by planetscape - added code tags

( keep:0 edit:16 reap:1 )

Replies are listed 'Best First'.
Re: How to get minimum start date in these start dates ?
by cog (Parson) on Jul 10, 2006 at 07:38 UTC
    I'm in a good mood, so I'll give you (untested) code:

    my @sorted_dates = map { $_->{'date'} } sort { $a->{'year'} <=> $b->{'year} or $a->{'month'} <=> $b->{'month} or $a->{'day'} <=> $b->{'day'} } map { /(\d\d)-(\d\d)-(\d\d\d\d)/ ; { 'date' => $_, 'day' => $1, 'month' => $2, 'year' => $3 } } @start_date; my $minimum_date = $sorted_dates[-1];

    Basically, I'm using a Schwartzian Transform in which I'm retrieving the elements of the date (year, month and day) and I'm sorting the dates by using those elements.

    Search for "Schwartzian Transform" here in the Monastery if you don't know what it is. As for the rest, it's just a matter of sorting by year, by month if the years are the same, and by day if the months are the same.

    Note that I'm assuming two digit days and two digit months.

      cog While I agree that a Schwartzian transfrom is a good idea here, I would like to make two small comments.

      1. Rather than doing three comparisons, first on year, then month, then day, I believe (though I haven't benchmarked it) that it would be faster to do a single comaprison of a string in the form yyyymmdd, which can be easily created with a regex.

      2. Depending on your data set, it maybe considerable faster to use an Orcish manouver. Especially if the same date may appear multiple time in the list (and I didn't nessicarily see anthing in the post to indicate that that wouldn't happen).

      my(%date_hash) = (); my(@start_date) = qw(01-06-2007 01-08-2006 01-06-2006 01-07-2007 06-01 +-2007); my @sorted_dates = sort({ ($date_has{$a} ||= &trans_date($a)) <=> ($date_has{$b} ||= &trans_date($b)) } @start_date); print join("\n", @sorted_dates); sub trans_date { my $date = shift; $date =~ s/(\d{2})-(\d{2})-(\d{4})/$3$2$1/; return $date; }

      They say that time changes things, but you actually have to change them yourself.

      —Andy Warhol

        While I don't disagree with you, I find the Schwartzian transform easier to understand and memorize than an Orcish Manouver, from the view point of a newbie.

        Also, the benchmarking would depend largely on the data set (suppose all the years are different, for instance).

        Still, I'm inclined to believe that speed won't be relevant, in this case :-) Just a hunch, you know? :-)

Re: How to get minimum start date in these start dates ?
by Corion (Pope) on Jul 10, 2006 at 07:38 UTC

    The idea is very simple: Convert your dates into something that sort can handle, sort them, and you're done. For example, the strings of the form YYYY/MM/DD sort very well. As you don't show the code you have written, we won't do your homework.

Re: How to get minimum start date in these start dates ?
by explorer (Chaplain) on Jul 10, 2006 at 09:29 UTC
    And after the homework, try this:
    use DateTime; use DateTime::Format::Strptime; my @start_date = qw(01-06-2007 01-08-2006 01-06-2006 01-07-2007 06-01- +2007); my $Strptime = new DateTime::Format::Strptime( pattern => '%d-%m-%Y' ) +; my @start_datetimes; foreach my $datetime ( @start_date ) { push @start_datetimes, $Strptime->parse_datetime( $datetime ); print $start_datetimes[-1]->ymd('-'); } print "-"x10; my @sort_datetimes = map { $_->[0] } sort { $a->[1] <=> $b->[1] } map { [ $_, $_->epoch ] } @start_datetimes; print $_->ymd('-') foreach @sort_datetimes; __OUTPUT__ 2007-06-01 2006-08-01 2006-06-01 2007-07-01 2007-01-06 ---------- 2006-06-01 2006-08-01 2007-01-06 2007-06-01 2007-07-01
    Note: Teachers don't likes modules :-)
Re: How to get minimum start date in these start dates ?
by Ieronim (Friar) on Jul 10, 2006 at 09:36 UTC
    If your array of dates is HUGE and you don't need to sort it - only to get the minimum date, you can extract the minimum date with simple loop:
    my $min; foreach (@dates) { next unless /^(\d+)-(\d+)-(\d+)$/; $min ||= ["$3$2$1", $_]; next unless "$3$2$1" < $min->[0]; $min = ["$3$2$1", $_]; } my $mindate = $min->[1];
    The idea is simple - the dates can be compared as numbers if they are written in the format YYYMMDD. The sorting can be optimized using the same technique, but you can do it yourself :)
Re: How to get minimum start date in these start dates ?
by johngg (Abbot) on Jul 10, 2006 at 10:12 UTC
    You can sort the dates lexically if you reverse the day, month and year and then just grab the first one, like this

    use strict; use warnings; my @startDates = qw(01-06-2007 01-08-2006 01-06-2006 01-07-2007 06-01-2007); my $leastDate = ( map {join q{-}, reverse split /-/} sort map {join q{-}, reverse split /-/} @startDates )[0]; print qq{Least date is $leastDate\n};

    When run this produces

    Least date is 01-06-2006

    I hope this is of use.



Re: How to get minimum start date in these start dates ?
by rjsaulakh (Beadle) on Jul 10, 2006 at 12:28 UTC

    u can use Date::Manip , convert ur dates into epoch and then sort this dates as per your criteria

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://560082]
Approved by Corion
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others about the Monastery: (7)
As of 2017-02-26 15:02 GMT
Find Nodes?
    Voting Booth?
    Before electricity was invented, what was the Electric Eel called?

    Results (375 votes). Check out past polls.