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

I am working on a l'il CGI script that needs to print times translated from epoch. When I wrote the bit that converts 24 hour time to 12hour time, I got some weird behavior.

The problem code would label everything as am. I'm not sure why.

This didn't work:
$hour > 11 ? $xm = "pm" : $xm = "am";
These did:
if ($hour > 11) {$xm = "pm"} else {$xm = "am"};
$hour > 11 ? ($xm = "pm") : ($xm = "am");

So how do I know when to use parentheses on ?: clauses? Is it better to always use them? I am quite confused.

Replies are listed 'Best First'.
Re: Weird ?: behavior
by btrott (Parson) on Aug 08, 2000 at 22:57 UTC
    If you run that line through B::Deparse, you get:
    $hour > 11 ? ($xm = 'pm') : $xm = 'am';
    The ternary operator (?:) has a higher precendence than =. That's why it's getting parsed that way.

    Anyway, IMO, the best way to write that would be:

    $xm = $hour > 11 ? "pm" : "am";
    No precendence problems, and it's clearer, to me. I like using ternary operators for assignment, not for executing arbitrary code. It's just a matter of personal preference, really, but in certain cases it'll keep you out of trouble. Like this one. :)
      It might also be clearer to you like this:
      $xm = ($hour>11) ? "pm" : "am";
      $hour > 11 ? ($xm = 'pm') : $xm = 'am';

      To make this a little clearer, this is the same as:

      if( $hour > 11 ) { ( $xm= 'pm' )= 'am'; } else { $xm= 'am'; }

      So $xm is always set to 'am'.

              - tye (but my friends call me "Tye")
Re: Weird ?: behavior
by tiny (Beadle) on Aug 08, 2000 at 23:59 UTC
    Not saying that what you are currently doing is wrong, but you should check out the POSIX function strftime. This makes it trivial to convert from an epoch time into any time format you like!
    use POSIX qw(strftime); my $epochTime = 965760598; my $timeStr = strftime "%A, %B %d, %Y - %I:%M%p %Z", localtime($epochT +ime); print $timeStr;
    This prints out:
    Tuesday, August 08, 2000 - 02:49PM EDT

    The % codes for strftime are as follows (from date --help):
    %% a literal % %a locale's abbreviated weekday name (Sun..Sat) %A locale's full weekday name, variable length (Sunday..Saturday) %b locale's abbreviated month name (Jan..Dec) %B locale's full month name, variable length (January..December) %c locale's date and time (Sat Nov 04 12:02:33 EST 1989) %d day of month (01..31) %D date (mm/dd/yy) %e day of month, blank padded ( 1..31) %h same as %b %H hour (00..23) %I hour (01..12) %j day of year (001..366) %k hour ( 0..23) %l hour ( 1..12) %m month (01..12) %M minute (00..59) %n a newline %p locale's AM or PM %r time, 12-hour (hh:mm:ss [AP]M) %s seconds since 00:00:00, Jan 1, 1970 (a GNU extension) %S second (00..60) %t a horizontal tab %T time, 24-hour (hh:mm:ss) %U week number of year with Sunday as first day of week (00..53) %V week number of year with Monday as first day of week (01..52) %w day of week (0..6); 0 represents Sunday %W week number of year with Monday as first day of week (00..53) %x locale's date representation (mm/dd/yy) %X locale's time representation (%H:%M:%S) %y last two digits of year (00..99) %Y year (1970...) %z RFC-822 style numeric timezone (-0500) (a nonstandard extension +) %Z time zone (e.g., EDT), or nothing if no time zone is determinab +le
Re: Weird ?: behavior
by KM (Priest) on Aug 08, 2000 at 23:03 UTC
    This happens, I believe (I can't find the FAQ on this) when you are doing variable assignments. I would write that line more like:
    my $xm = $hour > 11 ? "pm" : "am";

    Cheers,
    KM

Re: Weird ?: behavior
by Maclir (Curate) on Aug 09, 2000 at 02:10 UTC
    I believe all the operator precedence stuff is in the perlop man page.
Re: Weird ?: behavior
by TGI (Parson) on Aug 08, 2000 at 23:42 UTC

    Damn, that was fast!

    Thanks all!

    I hadn't seen the assignment idiom before, it seems more operator-like and helps clear up the differnce between if and ?:. This use is subtly implied on p62 of Perl in a Nutshell when it says "the value of the evaluated expression becomes the value of the entire expression." I didn't see that I could use assignment as a consequence of this. Go figure.

    Extra thanks to Tye for teasing apart the precedence issue. I pondered that one for a while but could not crack it. I just started adding parens until it worked!

    PerlMonks kicks ass.