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

In reply to Random day of a year by ambrus

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.