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

Sorting Times

by mt2k (Hermit)
on Apr 28, 2001 at 04:46 UTC ( [id://76319]=perlquestion: print w/replies, xml ) Need Help??

mt2k has asked for the wisdom of the Perl Monks concerning the following question:

I have a really hard question that I can't seem to figure out (okay, so I *can't* figure it out!)...

How would I go about sorting times, that include the hour, minutes, and AM/PM, into a well-sorted list??

Here is what the times I need to sort would look like:

3:15PM 1:00AM 8:30AM 6:15PM 2:45PM

The way I want these sorted is in the order that the times pass during a day. So, the above examples should sort out to:
1:00AM 8:30AM 2:45PM 3:15PM 6:15PM

So basically, how would I go sorting these? I can't use a simple sort { $a cmp $b}, because then it sorts to:

1:00AM 2:45PM 3:15AM 6:15AM 8:30AM

Thanks in advance!

Replies are listed 'Best First'.
Re: Sorting Times
by clintp (Curate) on Apr 28, 2001 at 05:21 UTC
    This is a good place for a Schwartzian transform...
    @r=qw( 1:00AM 2:45PM 8:30AM 3:15PM 6:15PM ); @t=map { $_->[0] } sort { $a->[1] <=> $b->[1] } map { $a=$_; s/://; s/(\d+)(\w)M/$1+($2 eq "P"?1200:0)/e; [ $a, $_ ] } @r; # @t has your sorted times.
    The second map can be shortened up a bit. I'm just making what's going on there a little more obvious...
Re: Sorting Times
by boo_radley (Parson) on Apr 28, 2001 at 05:02 UTC
    well, uh, how about military time?
    there's lots of good ways to do this. date::manip and all that. how about something less optimal, but wacky?
    $_= "11:12AM"; tr/://d; if (s/(\d\d)(\d\d?)([A|P])M/$1$2/) { if ($3 eq "P") {$_ +=1200 unless $1==12}; } print $_;
    update Military Time ™ crazyinsomniac.
Re: Sorting Times
by Rhandom (Curate) on Apr 28, 2001 at 06:30 UTC
    You could also ...
    %h = map { $a=$_; s{(\d+):(\d+)(A|P)} { sprintf("%02d:%02d",$1+($3 eq 'A'?0:12),$2) }e; $_ => $a } @times;
    Now you have a hash where the key is military time and the value is your original time. You can do whatever want after that (including foreach (sort keys %h)).

    my @a=qw(random brilliant braindead); print $a[rand(@a)];
(tye)Re: Sorting Times
by tye (Sage) on Apr 28, 2001 at 10:17 UTC

    I agree with the oft-repeated idea of converting to a padded 24-hour notation (or "military time" where the ":" is dropped), but everyone got it wrong. Yes, you need to add 12 to the "hours" for PM times, but you also need to subtrace 12 hours for 12AM times. q-:

            - tye (but my friends call me "Tye")
Re: Sorting Times
by Trimbach (Curate) on Apr 28, 2001 at 07:49 UTC
    Depending on your situation it might be a good idea to rethink your data. Personally, I'm a big fan of doing date/time calculations using # of seconds since the epoch (that is, on Unix, time and date are described as the number of seconds since January 1, 1970.) Number of seconds is a very handy format: it's easy to sort, easy to manipulate (need to add or subtract a minute/hour/day/month? Piece of cake!) and easily transferable back and forth into something legible using localtime() and Time::Local.

    Of course, you might not have that option... but IMHO dealing in epoch-time is a good habit to get into.

    Gary Blackburn
    Trained Killer

      it's easy to sort

      Beware the ides of September.
      <code> perl -e 'print time."\n".localtime(1_000_000_000)."\n";'

      my @a=qw(random brilliant braindead); print $a[rand(@a)];
        Says Rhandom:
        Beware the ides of September.
        perl -e 'print time."\n".localtime(1_000_000_000)."\n";'
        Nice thought, but the ides of September don't begin until 1_000_339_200. (Plus or minus a bit, depending on time zones and local conventions.)

        --
        Mark Dominus
        Perl Paraphernalia

Re: Sorting Times
by japhy (Canon) on Apr 29, 2001 at 01:09 UTC
    I'd forego the ST, and use a GRT instead:
    @s = map { (my $x = join '', reverse /(..)\s*(.*)/) =~ s/00:/12:/; $x } sort map { (my $x = sprintf "%2s%5s", reverse /(.{4,5})(..)/) =~ s/12:/00 +:/; $x } @t;


    japhy -- Perl and Regex Hacker
Re: Sorting Times
by mt2k (Hermit) on Apr 28, 2001 at 23:26 UTC
    I used clintp's version. Works perfectly! Thanks to everyone for the help.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://76319]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others studying the Monastery: (5)
As of 2024-03-28 16:53 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found