Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

Date munging suddenly broken

by motomuse (Sexton)
on Oct 05, 2000 at 00:50 UTC ( [id://35333]=perlquestion: print w/replies, xml ) Need Help??

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

Oh mighty Perl Monks, answer of your wisdom, I entreat.

I have a subroutine whose original intent was to mung the date so as to name a file based on whatever the date is of the Friday of the given week. So that, for example, if it's Wednesday 10/4/2000, the file gets gets titled 10_6_2000.html (with the idea that it's appended to after that).

It worked fine up to some unspecified time ago (I only found out it was broken when one of my users reported a different problem entirely). Now it's telling me that Friday is 9/28/2000. Here's the code in question:

$now = time(); ($sec,$min,$hour,$mday,$mon,$year,$wday,$rest) = localtime($now); if ($wday !=4) { $dow = $wday; if ($dow < 4) { $dow += 7; } $then = (($dow - 4) * 60 * 60 * 24); } ($sec,$min,$hour,$mday,$mon,$year,$rest) = localtime($now - $then); $mon=$mon+1; $year=$year+1900;

Why's it not working? Should it have ever worked??

Thanks for your attention.

    - Muse

Replies are listed 'Best First'.
(jcwren) Re: Date munging suddenly broken
by jcwren (Prior) on Oct 05, 2000 at 00:58 UTC
    I'm not clear how this would have ever worked, since your always subtract $then from $now, which means dates will always be in the past, never in the future.

    In addition, according to the 'man -f localtime' page, Sunday is day 0, so Friday would be day 5, not day 4. By changing the 4's to 5's, you at least will get the most recent previous Friday.

    If you can take a slight performance hit of loading a slightly large module, use Date::Manip. This is a tried and trusted module, and will allow text descriptions of dates you're looking for, like below.
    #!/usr/local/bin/perl -w use strict; use Date::Manip; { print ParseDate ("next Friday"); }
    --Chris

    e-mail jcwren
      I know that 4 is Thursday; that's intentional. People in general start creating their status reports on Thursday -- if they start on Wednesday, I want them to append to the previous Friday. If it's Thursday, I want them to append to the coming Friday. Sorry I didn't make that clear.

      Anyway, irrespective of that, performance isn't particularly an issue with this, so I'll gladly take your advice re: loading the said module. Thanks!

          - Muse

        Ah, OK. Here's a version that does it algorithmically, rather than using Date::Manip. You'll have to correct for the "If it's Thursday" problem, but this will generate a list of all Friday's in the year.

        Also, just as a side note, if you're not using 'use strict', and -w, I'd highly recommend enabling that. It'll help you track down problems a lot faster.
        #!/usr/local/bin/perl -w use strict; use Time::Local 'timelocal_nocheck'; { my $friday_date; my $now = time (); # Not used, here, but it's where the time would + come from for (my $i = 0; $i < 365; $i++) { $now = timelocal_nocheck (0, 0, 0, $i, 0, 2000); my ($sec,$min,$hour,$mday,$mon,$year,$wday,$rest) = localtime ($ +now); my $then = ((((5 - $wday) + 7) % 7) * (60 * 60 * 24)); ($sec,$min,$hour,$mday,$mon,$year,$rest) = localtime ($now + $th +en); $mon += 1; $year += 1900; my $temp = sprintf ("%02d/%02d/%04d", $mon, $mday, $year); if ($friday_date ne $temp) { print "$temp\n"; $friday_date = $temp; } } }
        --Chris

        e-mail jcwren
        So, you want something like:
        $now = time; $hour = (localtime $now)[2]; $now += (12 - $hour)*60*60; # offset to noon-hour so DST doesn't fry u +s $dow = (localtime $now)[6]; $now += (($dow < 4 ? -2 : 5) - $dow)*24*60*60; ($y, $m, $d) = (localtime $now)[5,4,3]; $file = sprintf "%d_%d_%d.html", $m+1, $d, $y+1900;
        perhaps?

        -- Randal L. Schwartz, Perl hacker

RE: Date munging suddenly broken
by extremely (Priest) on Oct 05, 2000 at 02:00 UTC
    It never worked right. here are my results for Oct 3 backwards 8 days...
    28, 9, 2000
    28, 9, 2000
    28, 9, 2000
    28, 9, 2000
    28, 9, 2000
    27, 9, 2000
    21, 9, 2000
    21, 9, 2000

    That isn't right at all... How about this:

    sub next_friday { my $now = shift || time(); my ($sec,$min,$hour,$mday,$mon,$year,$wday,$rest) = localtime($now); my $then = (($wday-5) * 60 * 60 * 24); ($sec,$min,$hour,$mday,$mon,$year,$rest) = localtime($now - $then); $mon += 1; $year += 1900; return "$year.$mon.$mday"; }

    That is evil as heck but it works. If you want this friday to return next friday, you can ++$wday before the $then calc.

    Notice I fancied it up enough that you can send it arbritary times or it will default to time(). Notice I made it a sub. Notice what I did to the logic.

    Now, forget all that except as a basic lesson in how things work and use Date::Manip =)

    --
    $you = new YOU;
    honk() if $you->love(perl)

      It's not a big deal, but if it were me, I wouldn't want to pollute my code with a bunch of unnecessary lexicals. I prefer to use array slices. So those two localtime calls would become:
      my $wday = (localtime $now)[6]; .... my($mday, $mon, $year) = (localtime($now-$then))[3..5];
      Which, in my opinion, is cleaner.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others rifling through the Monastery: (5)
As of 2024-04-23 22:53 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found