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

I'm seeking some wisdom after having read Return of Program Repair Shop and Red Flags on perl.com.

The background for this is that I'm storing dates produced by localtime() in an XML file. The application that will be parsing the data (not mine, written in Visual C, can't change it) is expecting dates and times in the format MM-DD-YYYY HH:mm. In order to ensure that dates are formatted as required, I've written a routine to pad numeric values that are not long enough with zeros as follows:

# The appropriate time / date values are retrieved from localtime() ($sec, $min, $hour) = paddatevalues($sec, $min, $hour); sub paddatevalues { foreach my $value (@_) { while (length $value < 2) { $value = '0'.$value; } } return @_; }

The article mentions that whenever you say something like if (length $somenumber < 3), you should think about replacing it with if ($somenumber < 1000). Due to the potential for zero values being passed into my subroutine, a simple if ($value < 9) won't do what I need it to do - I'll end up with a '0' instead of a '00'. Is there a good way to not treat my number as a string without using an if ... elsif to catch the special case (zero)?

--
Grant me the wisdom to shut my mouth when I don't know what I'm talking about.

Replies are listed 'Best First'.
Re: Zero-padding integers and the numbers-as-strings Red Flag
by Paladin (Vicar) on Jan 14, 2003 at 05:05 UTC
    Why not just
    sub paddatevalues { foreach my $value (@_) { $value = sprintf "%02d", $value; } return @_; }
    Or if you want to get fancy
    sub paddatevalues { return map {sprintf "%02d", $_} @_; }

      D'oh. That easy, huh? *wince* Forgot about sprintf.

      Thanks.

Re: Zero-padding integers and the numbers-as-strings Red Flag
by Zaxo (Archbishop) on Jan 14, 2003 at 05:09 UTC

    You could use &POSIX::strftime.

    use POSIX qw( strftime ); my $datestring = strftime '%m-%d-%Y %H:%M', localtime; print $datestring, $/; # prints "01-14-2003 00:06" atm

    Update: Even though it is large, POSIX is cheap to load if you import only the functions you will call. It is part of the core perl distribution, so availability is not a problem with proper perl installations. The strftime(3) *nix man page gives a list of all the format specifiers available.

    After Compline,
    Zaxo

      Do you happen to know how much run-time overhead this would add? This is a CGI and I'm already up to my ears in modules.

Re: Zero-padding integers and the numbers-as-strings Red Flag
by graff (Chancellor) on Jan 14, 2003 at 05:15 UTC
    The typical way to handle this kind of string formatting is with sprintf:
    $date_string = sprintf( "%2.2d-%2.2d-%d %2.2d:%2.2d:2.2d", $month, $day, $year, $hour, $min, $sec );
    (Your explanation didn't mention seconds, but your code did, so I wrote the expression to produce "MM-DD-YYYY HH:MI:SS")

    I think there's another way to assure padding with leading zeros, but the "%N.Nd" is what I grew up with from using C in olden times... The first digit (before the decimal point) represents the field width, and the second digit (after the decimal) represents "precision" (i.e. number of visible digits to output, using leading zeroes as needed); the "d" means make the result look like an integer value (as opposed to "f" for floating point, where "precision" would refer to the number of digits to the right of the decimal point, and field width would usually be larger than precision).