【问题标题】:Java - Generate Random DOB [duplicate]Java - 生成随机 DOB [重复]
【发布时间】:2017-03-08 09:35:55
【问题描述】:

我想为给定的年份范围生成随机 DOB。所以我尝试了下面的代码

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));
    }

主要:-

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

我可以生成随机 DOB。但仅针对月份和日期,我想为 1 到 9 的范围添加前缀 '0'

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


【问题讨论】:

  • 如果您必须使用GregorianCalendar(Java 8 则不需要),我认为SimpleDateFormat 是您问题的标准且直接的答案。
  • @nullpointer - 如果小于 10,则需要在月份和日期的前缀中添加零

标签: java


【解决方案1】:

除了您希望的日期格式之外,我还发现您的代码存在一些其他问题,我认为您希望解决这些问题:

  • 假设您想要一个通常的月份编号,01 表示 1 月到 12 表示 12 月,您对月份编号的处理不正确。 get(Calendar.MONTH) 为您提供从 0 开始的月份:0 表示 1 月,11 表示 12 月。因此,您的代码不仅不会经常给您 12 个月和 1 。它还会为您提供不存在的日期。我见过 1905-2-31 和 1929-4-31(因为您得到 2 表示三月,我们将其解释为二月等)。
  • 可能并不重要,您的分布使闰年中的每一天的概率略小于其他日子。

如果可以的话,我建议你使用LocalDate。该类是在 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();
}

这为您提供均匀分布的正确日期,格式为 2 位数的月份和日期,例如 1926-07-05

如果你想避免溢出检查,你当然可以重写你的randBetween()来处理longs。

如果您不能使用 Java 8,您可以使用 GregorianCalendarSimpleDateFormat 执行类似的操作。但是,计算从下限到上限的确切天数很复杂,因此您可能希望坚持选择日期的方式。 SimpleDateFormat 仍然可以为您提供正确的日期,格式为月份和日期的两位数。编辑:在您的班级中,声明:

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

现在只需将您的 if-else 语句替换为:

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

如果您的randomDataOfBirth() 可以从多个线程访问,这将不起作用,因为SimpleDateFormat 不是线程安全的。如果是这样,每个线程都应该有自己的SimpleDateFormat 实例。

【讨论】:

  • V.V - 我正在使用 java 1.7。所以我正在使用GregorianCalendar。我发布了代码。如果小于 10,我只想在月份和日期附加零。你能提供解决方案吗
  • 我现在已经在我的回答中用代码说明了这一点。 @爱书
  • 帮助了 :) 谢谢
【解决方案2】:

使用 Java7,您可以尝试以下方式:

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));

    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-12-31
    • 2018-09-14
    • 2013-04-06
    • 2016-05-15
    • 1970-01-01
    相关资源
    最近更新 更多