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,

my $yearstart = ParseDate(UnixDate($ARGV[0], "%Y"));
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 = $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

    So here's a little one-liner

    That's rather large one-liner.

    Simpler:

    perl -MDateTime -le'$d = DateTime->new(year=>$ARGV[0]); $d->add(days => rand($d->is_leap_year?366:365)); print $d->ymd' year

    It would probably be better if you returned a day no later than the current month & day to avoid changing your age.

      And if we don't care about last day in leap year (imho the result is random enough), it can be true one-liner:
      perl -MDateTime -le 'print DateTime -> new(year=>$ARGV[0]) -> add(days +=>rand(365)) -> ymd' 2013
Re: Random day of a year
by JavaFan (Canon) on Feb 19, 2009 at 23:08 UTC
    I like to give February 29, 1923 as my day of birth. You'd be amazed by the number of sites accepting that date.
Re: Random day of a year
by jwkrahn (Abbot) on Feb 19, 2009 at 21:19 UTC
    perl -MTime::Local -le' $s = timelocal 0,0,0,1,0,$ARGV[0]-1900; print scalar localtime $s + rand timelocal( 0,0,0,1,0,$ARGV[0]-1899 ) +- $s; ' 1985
Re: Random day of a year
by ambrus (Abbot) on Mar 14, 2009 at 21:51 UTC

    The random.org website, which provides random numbers generated from atmospheric radio noise, also has a random date generator: this link gives you a fresh random day in 1985.

Re: Random day of a year
by jh (Beadle) on Feb 23, 2009 at 19:49 UTC
    Why don't you just enter January 1, <your year of birth>? Or for that matter, Dec 25, <year>? That may not SEEM random, but ~1/365 people is born on any given day of the year...

      Because I don't want to spoil my holidays with birthday greeting emails from random sites I once visited and forgot about it.

      Update 2011-09-24: Happy unbirthday!