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

Hi Monks,
I am trying to change the time that comes in as 19:45:34 as an example, to actually display like 7:45 PM. It Will have two variables to be checked, and I know what I am doing isn't efficient, since the code can just grow to long. There is anyone out there that could tell me a better way of doing that?
Here is the code:
my $xcltime = "19:45:34"; # It should print 7:45 PM my $xcltime2 = "23:35:14"; # It should print 11:35 PM if (($xcltime=~/(\d{1,2}):(\d{1,2}):(\d{1,2})/)||($xcltime2=~/(\d{1,2} +):(\d{1,2}):(\d{1,2})/)) { my $h1=$1;my $m2=$2; my $s3=$3; print "$h1,$m2,$s3<br>"; if($h1=~/13||14||15||16||17||18||19||20||21||22||23||24/) { $h1=~s/13/1/; $h1=~s/14/2/; $h1=~s/15/3/; $h1=~s/16/4/; $h1=~s/17/5/; $h1=~s/18/6/; $h1=~s/19/7/; $h1=~s/20/8/; $h1=~s/21/9/; $h1=~s/22/10/; $h1=~s/23/11/; $h1=~s/24/12/; $xcltime=$h1.":".$m2."&nbsp;PM"; $xcltime2=$h1.":".$m2."&nbsp;PM"; print "<b>$xcltime - $xcltime2</b><br>"; }else {$xcltime = $xcltime."AM"; print "<b>$xcltime - $xcltime2 +</b><br>";}

Thank you all very much!

Replies are listed 'Best First'.
Re: Time transformation
by eieio (Pilgrim) on Sep 03, 2004 at 13:24 UTC
    Here's a code snippet that handles the conversion of the time:
    use POSIX qw(strftime); my $time = "19:45:34"; my ($hour, $minute, $second) = split ':', $time; my $convertedTime = strftime("%I:%M:%S %p", $second, $minute, $hour, 1 +, 0, 2004 );
      Thank you all, I have now good examples on what to do.
Re: Time transformation
by periapt (Hermit) on Sep 03, 2004 at 13:08 UTC
    Try this. I cut out the HTML formatting bits for clarity but I assume you can put them back in where needed.
    #! /usr/bin/perl use strict; use warnings; my $xcltime = "19:45:34"; # It should print 7:45 PM my $xcltime2 = "23:35:14"; # It should print 11:35 PM my ($h1,$m1,$s1) = split /:/, $xcltime; print "$h1,$m1,$s1\n"; my ($h2,$m2,$s2) = split /:/, $xcltime2; print "$h2,$m2,$s2\n"; $xcltime =sprintf("%02s:%02s%s", $h1 % 12, $m1, ($h1 > 12) ? "PM" : "A +M" ); $xcltime2=sprintf("%02s:%02s%s", $h2 % 12, $m2, ($h2 > 12) ? "PM" : "A +M" ); print "$xcltime - $xcltime2"; __END__ 19,45,34 23,35,14 07:45PM - 11:35PM

    PJ
    use strict; use warnings; use diagnostics; (if needed)
Re: Time transformation
by Eimi Metamorphoumai (Deacon) on Sep 03, 2004 at 13:11 UTC
    I'm not understanding how your variables $xcltime and $xcltime2 are related. It looks like you're trying to set them both at once, to the same thing. Unless there's some weird dependency, you'd probably do best to extract out the time manipulation code into a subroutine, so the heart of your program can be just
    $xcltime=convert_time($xcltime); $xcltime2=convert_time($xcltime2);
    or similar. Then you just create a subroutine to do the conversion. I'd probably write it like this
    sub convert_time{ my ($time)=shift; my ($h, $m, $s) = $time =~ /^(\d\d?):(\d\d?):(\d\d?)$/; my ($suffix); if ($h > 12){ $h-=12; $suffix="&nbsp;PM"; } elsif ($h == 0) { $h = 12; $suffix="&nbsp;AM"; } else { $suffix="&nbsp;AM"; } return "$h:$m:$s$suffix"; }
    Another issue is that your code inserts no space for AM, but an html nonbreaking space for PM. I've inserted the space in both cases, but you could change that if you really wanted to.

    I've also included a fix for if the time is "00:15:17" or such, converting it to "12:15:17 AM".

Re: Time transformation
by Arunbear (Prior) on Sep 03, 2004 at 13:13 UTC
    use strict; use warnings; my $xcltime = "00:45:34"; # It should print 12:45 AM my ($h, $m) = split /:/, $xcltime; my $ampm = $h < 12 ? 'AM' : 'PM'; $h = ($h % 12) || 12; print "$h:$m $ampm"; # prints 12:45 AM
Re: Time transformation
by lestrrat (Deacon) on Sep 03, 2004 at 13:08 UTC

    How about this. I'd rather look for some module to do it, though...

    my @times = qw(7:45:34 19:45:34 23:34:14); foreach my $t (@times) { if ($t =~ /^(\d?\d):(\d?\d):\d?\d$/) { my $ampm = "AM"; my ($h, $m) = ($1, $2); if ($h > 12) { $h -= 12; $ampm = "PM"; } print "$h:$m $ampm\n"; } }
Re: Time transformation
by japhy (Canon) on Sep 03, 2004 at 16:04 UTC
    Everyone told you how to do it right, but no one told you what you were doing wrong.
    my $xcltime = "19:45:34"; # It should print 7:45 PM my $xcltime2 = "23:35:14"; # It should print 11:35 PM if (($xcltime =~ /(\d{1,2}):(\d{1,2}):(\d{1,2})/) || ($xcltime2 =~ /(\ +d{1,2}):(\d{1,2}):(\d{1,2})/)) {
    You should probably do a loop over both $xcltime and $xcltime2, to make sure BOTH of them get the treatment.
    my $h1=$1;my $m2=$2; my $s3=$3; if ($h1 =~ /13||14||15||16||17||18||19||20||21||22||23||24/) {
    You're confusing Perl's "OR" operator || with the regex's alternation symbol |. When you use a||b in a regex, you're saying "match 'a' or nothing or 'b'".

    There's also no point in saying "if $str matches /foo/, substitute 'bar' for /foo/". Just say "substitute 'bar' for /foo/", and if any matches are found, they'll be changed. The idiom s/a/b/ if /a/ is pointless.

    $h1=~s/13/1/; $h1=~s/14/2/; $h1=~s/15/3/; $h1=~s/16/4/; $h1=~s/17/5/; $h1=~s/18/6/; $h1=~s/19/7/; $h1=~s/20/8/; $h1=~s/21/9/; $h1=~s/22/10/; $h1=~s/23/11/; $h1=~s/24/12/;
    And there's no reason to use regexes here. $h1 is just a number now. This logic should be written as
    my $pm = 0; # assume AM if ($h1 > 12) { $pm = 1; $h1 -= 12; }
    _____________________________________________________
    Jeff japhy Pinyan, P.L., P.M., P.O.D, X.S.: Perl, regex, and perl hacker
    How can we ever be the sold short or the cheated, we who for every service have long ago been overpaid? ~~ Meister Eckhart