Random date

A date drawn uniformly across the days in your range — not by picking a month and a day and clamping the impossible ones, which makes the end of February four times too likely. Nothing you type here leaves your browser — it is worked out on your own device, so there is nothing to send and nothing to log.

This page will not fall back to Math.random(). Everything here is drawn from crypto.getRandomValues(), which the browser backs with the operating system's cryptographic source. If that is unavailable the page says so and produces nothing — because output from a weak source looks exactly like output from a strong one, and that is the whole problem.

Picking a month and a day is not picking a date

The tempting way to generate a random date is to pick a month from 1 to 12 and a day from 1 to 31. That gives 372 combinations for 365 days, and seven of them — 30 and 31 February, 31 April, June, September and November — do not exist.

What happens next decides whether the result is uniform. Rejecting the impossible combination and drawing again is fine. Clamping it to the last day of the month is not, and clamping is what most code does, because it looks tidier and never loops.

Clamp, and 28 February collects four of the 372 cells — its own, plus 29, 30 and 31. Every ordinary date gets one. The last day of February becomes four times as likely as any other day of the year, and 30 April, 30 June, 30 September and 30 November each become twice as likely.

This page does neither. It counts the days in the range, draws a single index uniformly across that count, and converts it to a date — so every day is equally likely by construction, with no rejection loop and nothing to clamp.

Days of the week are not equally likely either

Over a whole number of years they nearly are, but over an arbitrary range they are not, and a 365-day year is 52 weeks plus one day — so one weekday appears 53 times. Over a leap year, two do.

The counts under your dates are the exact numbers for the range you chose, not an approximation.

Where the randomness comes from

One draw per date from crypto.getRandomValues(), with the uneven tail of the range rejected so that a range whose length does not divide the random pool is still uniform. Not Math.random(), and no fallback.

Where to go next