-1

I want to generate random DOB for the given range of year. So I tried the below code

private static String randomDataOfBirth(int yearStart, int yearEnd)
    {
        GregorianCalendar gc = new GregorianCalendar();
        int year = randBetween(yearStart, yearEnd);
        gc.set(Calendar.YEAR, year);
         int dayOfYear = randBetween(1, gc.getActualMaximum(Calendar.DAY_OF_YEAR));

            gc.set(Calendar.DAY_OF_YEAR, dayOfYear);
            String date = null;
            if(gc.get(Calendar.MONTH) == 0)
            {
                 date = gc.get(Calendar.YEAR) + "-" + 1 + "-" + gc.get(Calendar.DAY_OF_MONTH);
            }else
            {
                 date = gc.get(Calendar.YEAR) + "-" + gc.get(Calendar.MONTH) + "-" + gc.get(Calendar.DAY_OF_MONTH);
            }
            return date;    
    }

private static int randBetween(int start, int end) {
        // TODO Auto-generated method stub
         return start + (int)Math.round(Math.random() * (end - start));
    }

Main:-

public static void main(String[] args) {
String dob = randomDataOfBirth(1899, 1937);
System.out.println(dob);
}

I can be able to generate the random DOB. But only for the Month and Day, I want to add a prefix '0' for the range from 1 to 9

Month - 01, 02, 03 and ... up to 09
Day - 01, 02, 03 and ... up to 09


Aishu
  • 1,111
  • 4
  • 20
  • 42
  • http://stackoverflow.com/questions/11279683/adding-zero-to-a-single-digit-number-is-it-possible – log N Mar 08 '17 at 09:37
  • If you must use `GregorianCalendar` (with Java 8 you need not), I think `SimpleDateFormat` is the standard and straightforward answer to your question. – Ole V.V. Mar 08 '17 at 09:50
  • @nullpointer - Need to add zero in the prefix for month and day, if it is less than 10 – Aishu Mar 08 '17 at 10:08

2 Answers2

1

Apart from the desired formatting of you date I see some other problems with your code that I think you would want to address:

  • Assuming you want a usual month number, 01 for January through 12 for December, your handling of the month number is not correct. get(Calendar.MONTH) gives you a 0-based month: 0 for January through 11 for December. Therefore, your code not only will never give you 12 as month and 1 all too often. It will also give you non-existing dates. I have seen 1905-2-31 and 1929-4-31 (because you get 2 for March, which we interpret as February, etc.).
  • Possibly unimportant, your distribution gives each day in a leap year slightly smaller probablity than other days.

If you can, I suggest you use LocalDate. The class was introduced in Java 8:

private static String randomDataOfBirth(int yearStartInclusive, int yearEndExclusive) {
    LocalDate start = LocalDate.ofYearDay(yearStartInclusive, 1);
    LocalDate end = LocalDate.ofYearDay(yearEndExclusive, 1);

    long longDays = ChronoUnit.DAYS.between(start, end);
    int days = (int) longDays;
    if (days != longDays) {
        throw new IllegalStateException("int overflow; too many years");
    }
    int day = randBetween(0, days);
    LocalDate dateOfBirth = start.plusDays(day);

    return dateOfBirth.toString();
}

This gives you evenly distributed, correct dates formatted with 2 digits for month and day-of-month, e.g., 1926-07-05.

If you want to avoid the overflow check, you may of course rewrite your randBetween() to handle longs.

If you cannot use Java 8, you can do something similar with GregorianCalendar and SimpleDateFormat. Counting the exact number of days from lower to upper bound is complicated, though, so you will probably want to stick to your way of picking the date. SimpleDateFormat can still give you correct dates formatted with two digits for month and day. Edit: In your class, declare:

static DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");

Now just substitute your if-else statement with this:

    String date = formatter.format(gc.getTime());

If your randomDataOfBirth() may be accessed from more than one thread, this won’t work since SimpleDateFormat is not thread-safe. If so, each thread should have its own SimpleDateFormat instance.

Ole V.V.
  • 65,573
  • 11
  • 96
  • 117
0

With Java7 you can try with something like this:

public class DobMaker
{

    public String getDOB(int min, int max)
    {
        Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
        int year = min + new Random().nextInt(max - min + 1);
        calendar.set(Calendar.YEAR, year);
        int day = 1+new Random().nextInt(calendar.getActualMaximum(Calendar.DAY_OF_YEAR));
        calendar.set(Calendar.DAY_OF_YEAR, day);
        return new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime());
    }

    public static void main(String[] args)
    {
        DobMaker d = new DobMaker();

        System.out.println(d.getDOB(1970, 1980));
        System.out.println(d.getDOB(1970, 1971));
        System.out.println(d.getDOB(2007, 2016));

    }
}
Sampisa
  • 1,257
  • 2
  • 17
  • 23