Some webpages require that you give your birthday to register. Now, I often do not want to give them your birthday, because I don't feel like they need it, but I'll still give them my correct year of birth so they can give me correctly targeted ads etc. In this case, I'll want to enter a random date in that year, but of course I can't just make something up because that won't be random enough.
So here's a little one-liner that gives a random day uniformly chosen from all days of that year (taking leap years into account). The year is given as the command-line argument.
perl -we 'use Date::Manip; my $yearstart = ParseDate(UnixDate($ARGV[0] +, "%Y")); my $yeardays = Delta_Format(DateCalc($yearstart, DateCalc($ +yearstart, "+1 year")), 0, "%.3dys"); my $randday = DateCalc($yearsta +rt, int(rand($yeardays)) . "days"); print UnixDate($randday, "%B %e, +%Y\n");' 1985
Example output:
September 8, 1985
(By the way, the web form I'm filling out right now says "(YEAR/MONTH/DAY, eg. 1972/01/13) obligatory" after the form element, and has some javascript magic that pops up a pointless calendar control when I select that field – are they thinking I can't type my birthday without choosing from a calendar –, and the javascript does not allow me to type slashes in the input box, though hyphens instead seem to work.)
Update: changed "%y" to "%Y" to fix a y2k bug that would occur only for unusual input years only, and removed the statement print STDERR "." that I accidentally left in when I tried to see how fast this runs if repeated.
Update: Here's some explanation to this solution. As you can see, we're using the cpan module Date::Manip.
The first statement,
makes a date object pointing to the first day of the year from the argument. Actually the ParseDate call is completely unnecessary, it just makes the intention clearer; whereas the UnixDate call is needed only if the argument is not a simple year but a full birthdate like "may 20, 1985", because a simple year parses as the start of that year. Thus, this would be enough instead:my $yearstart = ParseDate(UnixDate($ARGV[0], "%Y"));
my $yearstart = $ARGV[0];
The next statement completes the length of that year in dates by adding one year (resulting in the first day of the next year), then subtracting the original date from the result, then printing this in days as units.
my $yeardays = Delta_Format(DateCalc($yearstart, DateCalc($yearstart, +"+1 year")), 0, "%.3dys");
The third statement generates a random number that's at least zero and at most one less than the length of the year, and adds that many days to the start of the day, so we get a random day that can be the 1st January earliest and the 31th December latest.
my $randday = DateCalc($yearstart, int(rand($yeardays)) . "days");
Finally, the last statements prints that date in a human-readable format.
print UnixDate($randday, "%B %e, %Y\n");
Update 2012-05-01: the original version of this code silently gave an incorrect date when using a later version of Date::Manip.
Update 2012-06-19: I have fixed the code. It should work now. The original code was the following.
perl -we 'use Date::Manip; my $yearstart = ParseDate(UnixDate($ARGV[0] +, "%Y")); my $yeardays = Delta_Format(DateCalc($yearstart, DateCalc($ +yearstart, "+1 year")), 3, "%dt"); my $randday = DateCalc($yearstart, + int(rand($yeardays)) . "days"); print UnixDate($randday, "%B %e, %Y\ +n");' 1985
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Random day of a year
by ikegami (Patriarch) on Feb 19, 2009 at 16:52 UTC | |
by grizzley (Chaplain) on Feb 20, 2009 at 09:40 UTC | |
|
Re: Random day of a year
by JavaFan (Canon) on Feb 19, 2009 at 23:08 UTC | |
|
Re: Random day of a year
by jwkrahn (Abbot) on Feb 19, 2009 at 21:19 UTC | |
|
Re: Random day of a year
by ambrus (Abbot) on Mar 14, 2009 at 21:51 UTC | |
|
Re: Random day of a year
by jh (Beadle) on Feb 23, 2009 at 19:49 UTC | |
by ambrus (Abbot) on Feb 23, 2009 at 20:29 UTC |