Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generate a random LocalDate with java.time

I'm writing some code to populate a MySQL database with random data for testing purposes. I need to populate a DATE column with random dates from 1970-2015.

Here's the relevant method:

public Date dateGenerator() throws Exception {
    Random ry = new Random();
    Random rm = new Random();
    Random rd = new Random();
    int year = 1969 + ry.nextInt(2015-1969+1);
    int month = 1 + rm.nextInt(12);
    int day = 1 + rm.nextInt(31);

    if (month==2 && day>28){
        day = day - 3;            
    } else {
        if((month%2==0 && month != 8 ) && day==31 ){
            day = day -1;
        }
    }
}

My purpose is to create three random integers (for day, month, year) and somehow combine them into some Date object to pass to the database. But the database rejects everything I try to feed it.

It would be very educational for me if you can supply me with a suggestion based in the newest java.time library if this is possible.

like image 539
HappyCane Avatar asked Dec 02 '15 19:12

HappyCane


2 Answers

A simple way is to convert the minimum and maximum date to their corresponding epoch day, generate a random integer between those two values and finally convert it back to a LocalDate. The epoch day is obtained with toEpochDay() which is the count of days since 1970-01-01 (ISO).

The problem with generating a random year, then month and then day is that you have a small chance of falling with an invalid date (like 31st of February). Also, taking a random epoch day guarantees a uniform distribution across all possible dates.

public static void main(String... args) {
    long minDay = LocalDate.of(1970, 1, 1).toEpochDay();
    long maxDay = LocalDate.of(2015, 12, 31).toEpochDay();
    long randomDay = ThreadLocalRandom.current().nextLong(minDay, maxDay);
    LocalDate randomDate = LocalDate.ofEpochDay(randomDay);
    System.out.println(randomDate);
}

Note that since the minimum date is actually the very first, you could replace it with 0.

To convert this LocalDate into a java.sql.Date, you can refer to this post:

java.sql.Date date = java.sql.Date.valueOf(randomDate);
like image 109
Tunaki Avatar answered Oct 24 '22 16:10

Tunaki


Try something like this.

public static void main(String[] args) {
    LocalDate start = LocalDate.of(1970, Month.JANUARY, 1);
    long days = ChronoUnit.DAYS.between(start, LocalDate.now());
    LocalDate randomDate = start.plusDays(new Random().nextInt((int) days + 1));
    System.out.println(randomDate);
}
like image 27
Raudbjorn Avatar answered Oct 24 '22 15:10

Raudbjorn