Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

Date Range Parsing

by Tuna (Friar)
on Feb 15, 2001 at 21:00 UTC ( [id://58646]=perlquestion: print w/replies, xml ) Need Help??

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

Funny, I've begun this question and killed it to try some things on my own about 5 times this morning! Anyway, my problem is that I want to "do something" to files created within a certain range of dates, inclusively. And I'm stuck. Here's what I've got so far; be gentle as I'm new at this programming stuff.
#!/usr/local/bin/perl -w use strict; my $test_arg = $ARGV[0]; my @string = split('-',$test_arg); my $beg_date = $string[0]; my $end_date =$string[1]; my $date = $beg_date; my @list; if ($string[0] ge $string[1]) { die "Invalid date range\n"; } elsif ($test_arg =~ /\d{8}-\d{8}/){ $test_arg = "1"; } else { $test_arg = "0"; } die "Usage: $0 <yyyymmdd-yyyymmdd>\n" unless $test_arg == "1"; while ($date <= $end_date){ push (@list, $date); } continue { $date++; }
The array @list is getting populated by the date string that I will use for my file search. My problem is accounting for the fact that months have either 28, 29, 30, or 31 days, depending upon year and month.
As writtren, the given date range 20010101-20010201 will return 100 days!

Replies are listed 'Best First'.
Re: Date Range Parsing
by davorg (Chancellor) on Feb 15, 2001 at 21:48 UTC

    I wonder if it actually matters the these numbers are dates at all. If the filenames contain the date in the same format that you are using as arguments, then you could do something along the lines of this:

    #!/usr/bin/perl -w use strict; my ($from, $to); die "Invalid args\n" unless @ARGV; unless (($from, $to) = $ARGV[0] =~ /(\d{8})-(\d{8})/) { die "Invalid args\n"; } my $dir = '.'; opendir(DIR, $dir) or die "Can't open $dir: $!\n"; my @files = grep { /(\d{8})/ && $1 >= $from && $1 <= $to } readdir DIR; print "@files\n";

    An example:

    > ls date.pl file20001105.txt file20010101.txt file20000907.txt file20001231.txt file20010215.txt > ./date.pl 20010101-20010228 file20010101.txt file20010215.txt >
    --
    <http://www.dave.org.uk>

    "Perl makes the fun jobs fun
    and the boring jobs bearable" - me

      This is perfect! Thanks all!
Re: Date Range Parsing
by chipmunk (Parson) on Feb 15, 2001 at 21:10 UTC
    For this task, I would suggest using the Time::Local module to convert your beginning and end dates to epoch time, and the File::Find module to find files whose modification time (found using stat) is between the start time and end time.
      Thanks for the reply. The only problem with that is that a file contaning data for 20010201 is actually created sometime the following day. Or, am I not understanding something?
        Perhaps I am not understanding something. You wrote "I want to 'do something' to files created within a certain range of dates, inclusively." Is that not what you meant?

        Either way, you can still use Time::Local and compare your dates in epoch time.

        Another option is storing your dates in YYYYMMDD format (as you're already doing); then you can just compare them numerically.

        if ($begin_date <= $curr_date and $curr_date <= $end_date) { print "$curr_date is between $begin_date and $end_date.\n"; }
Re: Date Range Parsing
by boo_radley (Parson) on Feb 15, 2001 at 21:23 UTC
    Of course it returns 100 days; your while loop simply increments through the $date counter -- there's never any logic to treat $date like a date.

    I would suggest using Date::Calc to verify that $date is really a valid date, and I'm sure there's TIMTOWTDI.

    here's a sample I whomped up off the top of my head:

    while ($date <=$end_date) { . . . (manipulate data here) . . . ($this_year, $this_month, $this_day) = ($date =~/(\d{4})(\d(2})(\d{2}) +/) if (!checkdate ($this_year, $this_month, $this_day) { # a new month dawns $this_day=1; if ($this_month ==12) {#did december just pass $this_year++; $this_month=0; } $this_month++; #add one to the month. $date = $this_year . $this_month . $this_day; } }
    Note that there's a lot of improvement to be wrung from this -- the regexp to split the date and the concatenation to reform it could be removed by using just $this_year and  $this_month and $this_day, but this might require some other adjustments to your code. update : There's a function in Date::Calc called Add_Delta_YMD which does pretty much the same thing.
Re: Date Range Parsing
by stefan k (Curate) on Feb 15, 2001 at 21:10 UTC
    Hi,
    you might consider Date::Calc which is quite powerful in everything you got to do with dates. It should be in your perl installation already.

    Regards Stefan K

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others romping around the Monastery: (6)
As of 2024-04-19 06:32 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found