http://www.perlmonks.org?node_id=102824

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

I'm helping a serverdude with a logfile summarization script.   Since the script will run daily, he'd like the output file to be named for the date in format yyyymmdd (with month and day leading-zero padded as needed).

The following snippet with localtime() and printf() are a start.   But there's clearly something I'm overlooking or misunderstand.   Suggestions for a Better Way To Do It?
    thanks,
    Don
    striving toward Perl Adept
    (it's pronounced "why-bick")

#!/usr/bin/perl -w use strict; my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(t +ime); printf ("%04d%02d%02d",$year+1900,$mon+1,$mday); print "\n\n"; # result is 20010807 # good; exactly what was expected my $ymd = printf("%04d%02d%02d",$year+1900,$mon+1,$mday); print "$ymd"; print "\n\n"; # result is 200108071 # why the appended 1 ?? my $outfile = "$ymd.summary"; print "$outfile"; print "\n\n"; # result is 1.summary # ????

Replies are listed 'Best First'.
(jeffa) Re: create file with current date for name
by jeffa (Bishop) on Aug 07, 2001 at 20:06 UTC
    The '1' is appended because you are using printf instead of sprintf:
    my $ymd = sprintf("%04d%02d%02d",$year+1900,$mon+1,$mday);
    This will fix your '1.summary' problem as well. This is a very easy mistake to make - i remember it making myself a few years ago programming in C++. :D

    jeffa

Re: create file with current date for name
by Hofmator (Curate) on Aug 07, 2001 at 20:18 UTC

    you got your answer but as a side remark ... this is ugly if you don't need all return values:

    my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(t +ime); # use a slice my ($year, $mon, $mday) = (localtime())[5,4,3];

    -- Hofmator

Re (tilly) 1: create file with current date for name
by tilly (Archbishop) on Aug 07, 2001 at 22:31 UTC
    A random note. Barring specific functions to do it for you, I like constructing yyyymmdd format through a numerical operation, not a sprintf.
    # Takes the time in seconds as an optional argument. # Returns the local date in yyyymmdd format. sub local_yyyymmdd { my $time = shift || time(); my ($year, $month, $mday) = (localtime($time))[5,4,3]; return 10_000*($year + 1900) + 100*($month + 1) + $mday; }
    Why? Because I have met many languages without a sprintf, but none without arithmetic. And sure, it may be ugly, but that is why Larry gave us functions...
Re: create file with current date for name
by tachyon (Chancellor) on Aug 07, 2001 at 20:09 UTC

    Your need sprintf not printf. This works as expected. The 1 is the true return value from printf which gets assigned to $ymd after printf has printed the string.

    #!/usr/bin/perl -w use strict; my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(t +ime); printf ("%04d%02d%02d",$year+1900,$mon+1,$mday); print "\n\n"; # result is 20010807 # good; exactly what was expected my $ymd = sprintf("%04d%02d%02d",$year+1900,$mon+1,$mday); print "$ymd"; print "\n\n"; # result is 20010807 my $outfile = "$ymd.summary"; print "$outfile"; print "\n\n"; # result is 20010807.summary

    You can simplify and use the default behaviour for localtime and an array slice to give this:

    #!/usr/bin/perl -w use strict; my ($mday,$mon,$year) = (localtime)[3..5]; my $ymd = sprintf("%04d%02d%02d",$year+1900,$mon+1,$mday); my $outfile = "$ymd.summary"; print $outfile, "\n";

    cheers

    tachyon

    s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

Re: create file with current date for name
by clemburg (Curate) on Aug 07, 2001 at 20:20 UTC

    If you are running on a Linux box, please be aware that date -I or date --iso-8601 will give you a date like '2001-08-07'. No need for any processing, and it's the ISO standard. You can even specify an optional precision.

    Examples:

    > date -I 2001-08-07 > date -Id 2001-08-07 > date -Ih 2001-08-07T18+0200 > date -Im 2001-08-07T18:32+0200 > date -Is 2001-08-07T18:32:39+0200

    Christian Lemburg
    Brainbench MVP for Perl
    http://www.brainbench.com

Re: create file with current date for name
by timbo (Initiate) on Aug 07, 2001 at 20:21 UTC
    aside from that I'd just do as follows, biut then maybe I'm just a bad man :)
    #!/usr/bin/perl -w use POSIX qw(strftime); my $myfile = strftime("%Y%m%d",localtime(time)); $myfile .=".summary"; print $myfile; print "\n";
    outputs 20010807.summary
Re: create file with current date for name
by scain (Curate) on Aug 07, 2001 at 20:09 UTC
    I'm not exactly an expert on (s)printf, but don't you want to use sprintf in the assignment to another variable?

    Scott

Re: create file with current date for name
by dvergin (Monsignor) on Aug 07, 2001 at 20:11 UTC
    In your second attempt you should use 'sprintf'.

    As it is, you are setting $ymd to the value returned from actually printing (using printf). So printf actually prints the desired value. Then '1' (success) is assigned to $ymd. Then that '1' is printed by the line: print "$ymd";

    This also explains the result of '1.summary' in your final trace print.

    If you say

      my $ymd = sprintf("%04d%02d%02d",$year+1900,$mon+1,$mday);

    you should be fine.

Re: create file with current date for name
by Masem (Monsignor) on Aug 07, 2001 at 20:10 UTC
    my $ymd = printf("%04d%02d%02d",$year+1900,$mon+1,$mday);
    printf returns 1 if printing was successful, otherwise zero. Thus $ymd is 1; the print statement follows what printf has printed out.

    Make that sprintf, and your problems are gone.

    -----------------------------------------------------
    Dr. Michael K. Neylon - mneylon-pm@masemware.com || "You've left the lens cap of your mind on again, Pinky" - The Brain

Re: create file with current date for name
by Anonymous Monk on Aug 07, 2001 at 21:01 UTC
    Try the Time::Object module, soon to be renamed Time::Piece and included in Perl 5.8