ITmajor has asked for the wisdom of the Perl Monks concerning the following question:
I want to set a time range for dates with yymmdd format. I want to be able to set a starting and ending date and run a for loop that will increase the date each time through the loop. Most of the information I have found is for 8 digit dates. How can I do this using only six? My code follows this rough outline
$start_date = $start_year, $start_month, $start_day;
$end_date = $end_year, $end_month, $end_day;
For ($filename = $start_date, $name; $start_date <= $end_date; $start_date->add(days=>1))[
open(FILE, ¡¥<$filename.txt¡¨); # Files look like this ----> 080518_name.txt
#do stuff w/file
#continue until last file in date span
}
I'm having trouble formatting the dates to look just like this "080623" without spaces, symbols or date/time. How can I do this? How do I set the date to increase the day (and month and year as necessary)?
Re: Using a range of dates in yymmdd format
by mr_mischief (Monsignor) on Aug 13, 2008 at 17:06 UTC
|
The main reason you're seeing mostly eight-digit dates is because the world just spent billions of dollars a few years ago dealing with the problems inherent in the format you are proposing. That caveat out of the way, there are a number of ways to deal with your issue.
- There are Date and Time modules on CPAN. Some of them are particularly suited to managing date ranges.
- You could play with times by adding seconds to the epoch clock, but you'd need to be aware of many issues the date and time modules handle for you.
- You can use the unary increment operator (++) on a value of 80623 and format the printing how you want, but you'd have to roll over the months and days with a nasty collection of case or if statements. You'd still also need to handle many issues the date and time modules handle for you.
- There are probably even worse ways to handle this, and we could probably have a contest to see how perverse a working solution could be.
If you search the PM site, you'll probably find some great comparisons and advice about date and time modules as well. One should do what you need.
Update: s/data/date/ in the second list item. | [reply] |
|
I never stated that I was proposing to us this format (yymmdd) over the 8 digits. I am simply trying to use data that has already been formatted by someone else. The format shouldn't be a problem because it is only used to name text files that are less than a year old.
Also, you stated that there are worse ways to do this....……what are some better ways? Why not have a contest to create the best solution?
| [reply] |
|
You want a better way than other people writing more than a dozen modules you can choose from to do your work? What's better than that, other than someone actually writing your code for you?
| [reply] |
|
The dates could be compared alphabetically. For example, '080801' is alphabetically less than '080812'. So, in the code below, the 'ge' and 'le' string comparison operators could be used to filter out the dates contained in the file name.
#!/usr/bin/perl
use strict;
use warnings;
my $path = "/some/path";
my $name = "name";
my $start = "$path/080801_$name";
my $end = "$path/080930_$name";
for my $file (grep {$_ ge $start && $_ le $end} glob "$path/??????_$na
+me") {
open my $fh, "<", $file or die "unable to open $file";
while (<$fh>) {
# process...
}
close $fh or die "unable to close $file";
}
Update: Changed glob "$path/????_$name to glob "$path/??????_$name to correctly let the wildcard operator, '?', match the 6 chars in the date portion of the file name. | [reply] [d/l] [select] |
Re: Using a range of dates in yymmdd format
by ikegami (Patriarch) on Aug 13, 2008 at 17:10 UTC
|
If the module you're using to do your date arithmetic doesn't allow you to produce a formatted date, you can use the following statement:
my $date_string = sprintf('%02d%02d%02d', $year-1900, $month, $day);
| [reply] [d/l] [select] |
|
my $date_string = sprintf('%02d%02d%02d', $year%100, $month, $day);
Which just illustrates why this is such a bad date format to use
| [reply] [d/l] |
Re: Using a range of dates in yymmdd format
by Cristoforo (Curate) on Aug 14, 2008 at 20:10 UTC
|
For a 'simple' solution, you could try the Date::Simple module.
#!/usr/bin/perl
use strict;
use warnings;
use Date::Simple 'ymd';
for (my $date=ymd(2008,8,1), my $end=ymd(2008,9,30);$date <= $end; $da
+te++) {
my $file = $date->format("%y%m%d_name");
warn("$file: no such file\n"), next unless -e $file;
open IN, "<", $file or die "Unable to open $file";
while (<IN>) {
# ... process
}
close IN or die "Unable to close $file";
}
Chris | [reply] [d/l] |
Re: Using a range of dates in yymmdd format
by Krambambuli (Curate) on Aug 14, 2008 at 13:49 UTC
|
Probably what you want is something like the following:
#!/usr/bin/perl
use strict;
use warnings;
use Date::Manip;
my $start_date_str = '080225';
my $end_date_str = '080304';
my $std_start_date_str = join( '-', substr($start_date_str, 0,2 ), sub
+str($start_date_str, 2) );
my $std_end_date_str = join( '-', substr($end_date_str, 0,2 ), sub
+str($end_date_str, 2) );
my $current_dt = ParseDate( $std_start_date_str);
my $end_dt = ParseDate( $std_end_date_str);
while( $current_dt le $end_dt) {
my $display_date_str = UnixDate( $current_dt, '%y%m%d' );
print "$display_date_str\n";
$current_dt = DateCalc( $current_dt, '+ 1 day');
}
Be warned about using a (non-standard, and as such potentially bad) yymmdd format.
If your curious, read a bit through Date::Manip to see why dealing with datetime data is far from trivial in most all circumstances.
| [reply] [d/l] |
|
|