Generate random date of birth

106,954

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());
    }
}
Share:
106,954
user475529
Author by

user475529

Updated on July 05, 2022

Comments

  • user475529
    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
    lbalazscs about 11 years
    This is not an uniform distribution because for example in February there should be less people.
  • Saul
    Saul about 11 years
    @lbalazscs - Indeed. I updated the example, it should be a bit better now.
  • AJMansfield
    AJMansfield almost 11 years
    This is exactly what I started thinking when I first read the question.
  • AJMansfield
    AJMansfield almost 11 years
    Is it really so burdensome to just use the standard random?
  • Ren
    Ren over 9 years
    this 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
    mareckmareck about 9 years
    For the sake of completeness - you should use access constants via Calendar class (Calendar.YEAR, Calendar.DAY_OF_YEAR) not via instance gc.
  • ewall
    ewall about 9 years
    This 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
    Maze over 8 years
    This 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
    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
    L. Blanc over 8 years
    This 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
    Alissa about 7 years
    It'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
    Basil Bourque over 6 years
    Consider using a ThreadLocalRandom rather than instantiating a new Random each time.
  • Witold Kaczurba
    Witold Kaczurba over 6 years
    True. Better practice.
  • jaco0646
    jaco0646 almost 6 years
    You can avoid casting the epoch days to int by calling ThreadLocalRandom.current().nextLong(n).
  • Edward J Beckett
    Edward J Beckett almost 5 years
    This is going into going into my testing toolbox for generating mock reports. Thanks for the contribution
  • David Buck
    David Buck over 3 years
    When 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.