I'm using perl to, as part of a larger script, create a list of dates for an entire year formatted YYYYMMDD.For example, if the user specifies the year 2002, it will create the following list and write it to a text file:
200201012002010220020103...20021231
5/23/2008 5:36:44 PM
use the DateTime module?
5/23/2008 6:35:04 PM
if the year is divisible by 4 with a whole number and none extra point it to a second set of dates with leap year addedyou're gonna need 2 lists for it i think, but the rest is pretty simple^ have you tried this yet?
5/26/2008 1:49:22 PM
two lists? what are you talking about?all you need to do is on the fly generate a list of numbers that are always the same, then when you get to then to february 29 just run a statement likeif( 0 == $year % 4 and 0 != $year % 100 or 0 == $year % 400 ) { print "$year0229";}it is a leap year if it is divisible by 4 but not by 100, except if it is for 400
5/26/2008 3:40:37 PM
without using any additional modules or any "smart" date handling (i.e. interpreting the dates purely as numbers), then something like this might work (not tested or debugged, no error checking, and assumes $year and $outFileName are provided already)
open (OUTFILE, ">$outFileName");select OUTFILE; # select default output streamprint "Dates in $year\n"; # headerfor ($month = 1; $month<=12; $month++) { $daysInMonth = 31; #default days in month is 31 because it is most frequent if ($month == 4 or $month == 6 or $month == 9 or $month == 11) $daysInMonth = 30; elseif ($month == 2) { #leap year calculation if (0 == $year % 4 and 0 != $year % 100 or 0 == $year % 400 ) $daysInMonth = 29; else $daysInMonth = 28; } for ($day=1; $day<=$daysInMonth; $day++) { print "$year"; ($month<10) ? print "0$month" : print "$month"; ($day<10) ? print "0$day" : print "$day\n"; }}close OUTFILE
5/26/2008 3:58:40 PM
I feel like a dumb ass for not thinking to do this:
"0$day"
5/28/2008 10:36:21 PM
5/28/2008 11:03:59 PM
My code: (don't laugh too much... it does actually work)
@listMonths = ("01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12");@listDay_28 = ("01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28");@listDay_29 = ("01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29");@listDay_30 = ("01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30");@listDay_31 = ("01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31");foreach $Month (@listMonths){ if ($Month eq "01" or $Month eq "03" or $Month eq "05" or $Month eq "07" or $Month eq "08" or $Month eq "10" or $Month eq "12") { foreach $Day (@listDay_31) { $Date="$Year$Month$Day"; system("echo \'$Date\' >> \'$DateList\'"); } } elsif ($Month eq "04" or $Month eq "06" or $Month eq "09" or $Month eq "11") { foreach $Day (@listDay_30) { $Date="$Year$Month$Day"; system("echo \'$Date\' >> \'$DateList\'"); } } else { if ($Year eq "2000" or $Year eq "2004" or $Year eq "1998" or $Year eq "2008" or $Year eq "2012") #all leap years in the TRMM dataset { foreach $Day (@listDay_29) { $Date="$Year$Month$Day"; system("echo \'$Date\' >> \'$DateList\'"); } } else { foreach $Day (@listDay_28) { $Date="$Year$Month$Day"; system("echo \'$Date\' >> \'$DateList\'"); } } }}
5/30/2008 4:33:23 PM
a colleague just reminded me of the printf function, which will format your output, for example, with leading zeros. The printing can be further simplified to for ($day=1; $day<=$daysInMonth; $day++) { print "\n$year"; printf '%02s', $month; printf '%02s', $day; }
6/2/2008 1:10:56 PM
a little more optimization - this is all you need in the for loop
for ($day=1; $day<=$daysInMonth; $day++) sprint '%04s%02s%02s\n', $year, $month, $day;
6/2/2008 1:40:42 PM
ok, now i have Perl geeks at work doing what Perl geeks do best - making the program shorterthis will take care of all the year, month and day printing, including leap years
$month = 1;foreach (31,28,31,30,31,30,31,31,30,31,30,31) { $daysInMonth=$_; $month++; if ($daysInMonth == 28 && !($year%4) && ($year%100) || !($year%400) ) $daysInMonth = 29; for ($day=1; $day<=$daysInMonth; $day++) printf "%04s%02s%02s\n",$year,$month,$day;}
6/2/2008 4:09:32 PM
^wow... I <3 perl
6/2/2008 8:47:51 PM
I don't mean to butt in with my opinion, but date handling should pretty much never be done by loop or list, and it really sounds like this is going to be used as a work around for a proper implementation of date and time logic. If that's the case you should probably realize how terribly wrong it is to difference dates by file line numbers. Sure it may work, but it's so far from having predictable behavior or utilizing resources efficiently that I'd just err on the side of caution and call it flat out wrong.
6/2/2008 8:59:51 PM
^ read the intended goal and comment again
6/2/2008 9:02:09 PM
I read the intended goal, and I honestly can't think of a good reason to generate such a text file. The point I was trying to convey was that the need for such a text in your application implied a greater problem with date handling than simply generating the text file.Again, if I'm making assumptions about your application I apologize. I've seen too many good script ideas rendered useless in implementation, as hacks were unnecessarily used to treat computer science challenges in the same manner as API challenges.
6/2/2008 9:42:19 PM
you know, that reminds me of a problem i was trying to solve at work todaygiven a start and end DateTime (we're talking c# now), generate a List representing the range of dates between the start and end date separated by a given amount of time. the only way i could think to do it was a loopList dates = new List<DateTime>();DateTime curDate = start;while (curDate<=end){ dates.Add(curDate); curDate.AddMonths(1);}it seemed like there should be a better way, but i couldn't think of anything simpler than this]
List dates = new List<DateTime>();DateTime curDate = start;while (curDate<=end){ dates.Add(curDate); curDate.AddMonths(1);}
6/2/2008 10:27:44 PM
^^ The file generated is used as input for a called script.
6/2/2008 10:43:56 PM
6/4/2008 10:04:48 PM
6/4/2008 10:06:18 PM