Generate random date of birth
Solution 1
import java.util.GregorianCalendar;
public class RandomDateOfBirth {
public static void main(String[] args) {
GregorianCalendar gc = new GregorianCalendar();
int year = randBetween(1900, 2010);
gc.set(gc.YEAR, year);
int dayOfYear = randBetween(1, gc.getActualMaximum(gc.DAY_OF_YEAR));
gc.set(gc.DAY_OF_YEAR, dayOfYear);
System.out.println(gc.get(gc.YEAR) + "-" + (gc.get(gc.MONTH) + 1) + "-" + gc.get(gc.DAY_OF_MONTH));
}
public static int randBetween(int start, int end) {
return start + (int)Math.round(Math.random() * (end - start));
}
}
Solution 2
java.util.Date
has a constructor that accepts milliseconds since The Epoch, and java.util.Random
has a method that can give you a random number of milliseconds. You'll want to set a range for the random value depending on the range of DOBs that you want, but those should do it.
Very roughly:
Random rnd;
Date dt;
long ms;
// Get a new random instance, seeded from the clock
rnd = new Random();
// Get an Epoch value roughly between 1940 and 2010
// -946771200000L = January 1, 1940
// Add up to 70 years to it (using modulus on the next long)
ms = -946771200000L + (Math.abs(rnd.nextLong()) % (70L * 365 * 24 * 60 * 60 * 1000));
// Construct a date
dt = new Date(ms);
Solution 3
Snippet for a Java 8 based solution:
Random random = new Random();
int minDay = (int) LocalDate.of(1900, 1, 1).toEpochDay();
int maxDay = (int) LocalDate.of(2015, 1, 1).toEpochDay();
long randomDay = minDay + random.nextInt(maxDay - minDay);
LocalDate randomBirthDate = LocalDate.ofEpochDay(randomDay);
System.out.println(randomBirthDate);
Note: This generates a random date between 1Jan1900 (inclusive) and 1Jan2015 (exclusive).
Note: It is based on epoch days, i.e. days relative to 1Jan1970 (EPOCH) - positive meaning after EPOCH, negative meaning before EPOCH
You can also create a small utility class:
public class RandomDate {
private final LocalDate minDate;
private final LocalDate maxDate;
private final Random random;
public RandomDate(LocalDate minDate, LocalDate maxDate) {
this.minDate = minDate;
this.maxDate = maxDate;
this.random = new Random();
}
public LocalDate nextDate() {
int minDay = (int) minDate.toEpochDay();
int maxDay = (int) maxDate.toEpochDay();
long randomDay = minDay + random.nextInt(maxDay - minDay);
return LocalDate.ofEpochDay(randomDay);
}
@Override
public String toString() {
return "RandomDate{" +
"maxDate=" + maxDate +
", minDate=" + minDate +
'}';
}
}
and use it like this:
RandomDate rd = new RandomDate(LocalDate.of(1900, 1, 1), LocalDate.of(2010, 1, 1));
System.out.println(rd.nextDate());
System.out.println(rd.nextDate()); // birthdays ad infinitum
Solution 4
You need to define a random date, right?
A simple way of doing that is to generate a new Date
object, using a long
(time in milliseconds since 1st January, 1970) and substract a random long
:
new Date(Math.abs(System.currentTimeMillis() - RandomUtils.nextLong()));
(RandomUtils is taken from Apache Commons Lang).
Of course, this is far to be a real random date (for example you will not get date before 1970), but I think it will be enough for your needs.
Otherwise, you can create your own date by using Calendar
class:
int year = // generate a year between 1900 and 2010;
int dayOfYear = // generate a number between 1 and 365 (or 366 if you need to handle leap year);
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, randomYear);
calendar.set(Calendar.DAY_OF_YEAR, dayOfYear);
Date randomDoB = calendar.getTime();
Solution 5
For Java8 -> Assumming the data of birth must be before current day:
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.Period;
import java.time.temporal.ChronoUnit;
import java.util.Random;
public class RandomDate {
public static LocalDate randomBirthday() {
return LocalDate.now().minus(Period.ofDays((new Random().nextInt(365 * 70))));
}
public static void main(String[] args) {
System.out.println("randomDate: " + randomBirthday());
}
}
user475529
Updated on July 05, 2022Comments
-
user475529 almost 2 years
I'm trying to generate a random date of birth for people in my database using a Java program. How would I do this?
-
lbalazscs about 11 yearsThis is not an uniform distribution because for example in February there should be less people.
-
Saul about 11 years@lbalazscs - Indeed. I updated the example, it should be a bit better now.
-
AJMansfield almost 11 yearsThis is exactly what I started thinking when I first read the question.
-
AJMansfield almost 11 yearsIs it really so burdensome to just use the standard random?
-
Ren over 9 yearsthis answer is a little outdated. When I type
new Date(Math.abs(System.currentTimeMillis() - RandomUtils.nextLong()));
, it shows the method is deprecated. However I cannot find a parallel equivalent method anywhere else. -
mareckmareck about 9 yearsFor the sake of completeness - you should use access constants via
Calendar
class (Calendar.YEAR
,Calendar.DAY_OF_YEAR
) not via instancegc
. -
ewall about 9 yearsThis answer is much more to my preference too. No need to do separate random calls for month, day, and year when a single number can determine it.
-
Maze over 8 yearsThis answer is rather old, but month is counted from 0. So January results in 0. For printing the actual date you have to print
(gc.get(gc.MONTH)+1)
-
Saul over 8 years@Maze - Some answers remain useful and relevant even when several years pass but your observation is entirely accurate. Fixed it.
-
L. Blanc over 8 yearsThis is a fine answer, but the utility class might be made a little more efficient by doing the toEpochDay() conversions for min and max in the constructor and saving the int results rather than the LocalDates. Then it only needs to be done once, rather than once for each call to nextDate().
-
Alissa about 7 yearsIt's a nice and simple solution, but I'd rather use
RandomUtils.nextLong(0, 70L * 365 * 24 * 60 * 60 * 1000);
from apache lang3 -
Basil Bourque over 6 yearsConsider using a
ThreadLocalRandom
rather than instantiating a newRandom
each time. -
Witold Kaczurba over 6 yearsTrue. Better practice.
-
jaco0646 almost 6 yearsYou can avoid casting the epoch days to
int
by calling ThreadLocalRandom.current().nextLong(n). -
Edward J Beckett almost 5 yearsThis is going into going into my testing toolbox for generating mock reports. Thanks for the contribution
-
David Buck over 3 yearsWhen answering an old question, your answer would be much more useful to other StackOverflow users if you included some context to explain how your answer helps, particularly for a question that already has an accepted answer. See: How do I write a good answer.