2010-10-21 26 views
43

Sto provando a generare una data di nascita casuale per le persone nel mio database utilizzando un programma Java. Come lo farei?Genera data di nascita casuale

+3

si prega di non utilizzare acronimi enigma;) –

risposta

65
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)); 
    } 
} 
+2

Questa non è una distribuzione uniforme perché ad esempio a febbraio dovrebbero esserci meno persone. – lbalazscs

+2

@ lbalazscs - Infatti. Ho aggiornato l'esempio, dovrebbe essere un po 'meglio ora. – Saul

+5

Per completezza, è necessario utilizzare le costanti di accesso tramite la classe 'Calendar' (' Calendar.YEAR', 'Calendar.DAY_OF_YEAR') non tramite l'istanza' gc'. – mareckmareck

27

java.util.Date ha un constructor che accetta millisecondi dall'epoca, e java.util.Random ha a method che si può dare un numero casuale di millisecondi. Ti consigliamo di impostare un intervallo per il valore casuale in base all'intervallo di DOB che desideri, ma questi dovrebbero farlo.

Molto all'incirca:

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

Questo è esattamente quello che ho iniziato a pensare quando ho letto la questione. – AJMansfield

+1

Questa risposta è molto più a mia preferenza. Non è necessario effettuare chiamate casuali separate per mese, giorno e anno quando un singolo numero può determinarlo. – ewall

+0

È una soluzione semplice e carina, ma preferirei usare 'RandomUtils.nextLong (0, 70L * 365 * 24 * 60 * 60 * 1000);' da apache lang3 – Alissa

20

È necessario definire una data casuale, giusto?

Un modo semplice per farlo è quello di generare un nuovo Date oggetto, utilizzando un long (time in milliseconds since 1st January, 1970) e sottrarre un caso long:

new Date(Math.abs(System.currentTimeMillis() - RandomUtils.nextLong())); 

(RandomUtils è tratto da Apache Commons Lang).

Naturalmente, questa è una data molto lontana (ad esempio, non si otterrà un appuntamento prima del 1970), ma penso che sarà sufficiente per le vostre esigenze.

caso contrario, è possibile creare il proprio data utilizzando Calendar classe:

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(); 
+5

È davvero così gravoso usare solo lo standard casuale ? – AJMansfield

+1

questa risposta è un po 'obsoleta. Quando digito 'new Date (Math.abs (System.currentTimeMillis() - RandomUtils.nextLong()));', mostra che il metodo è deprecato. Tuttavia non riesco a trovare un metodo equivalente parallelo altrove. – Yokhen

2

Generazione casuale Data di nascite:

import java.util.Calendar; 

public class Main { 
    public static void main(String[] args) { 
    for (int i = 0; i < 100; i++) { 
     System.out.println(randomDOB()); 
    } 
    } 

    public static String randomDOB() { 

    int yyyy = random(1900, 2013); 
    int mm = random(1, 12); 
    int dd = 0; // will set it later depending on year and month 

    switch(mm) { 
     case 2: 
     if (isLeapYear(yyyy)) { 
      dd = random(1, 29); 
     } else { 
      dd = random(1, 28); 
     } 
     break; 

     case 1: 
     case 3: 
     case 5: 
     case 7: 
     case 8: 
     case 10: 
     case 12: 
     dd = random(1, 31); 
     break; 

     default: 
     dd = random(1, 30); 
     break; 
    } 

    String year = Integer.toString(yyyy); 
    String month = Integer.toString(mm); 
    String day = Integer.toString(dd); 

    if (mm < 10) { 
     month = "0" + mm; 
    } 

    if (dd < 10) { 
     day = "0" + dd; 
    } 

    return day + '/' + month + '/' + year; 
    } 

    public static int random(int lowerBound, int upperBound) { 
    return (lowerBound + (int) Math.round(Math.random() 
      * (upperBound - lowerBound))); 
    } 

    public static boolean isLeapYear(int year) { 
    Calendar calendar = Calendar.getInstance(); 
    calendar.set(Calendar.YEAR, year); 
    int noOfDays = calendar.getActualMaximum(Calendar.DAY_OF_YEAR); 

    if (noOfDays > 365) { 
     return true; 
    } 

    return false; 
    } 
} 
0

Sto studiando Scala e ha finito per soluzioni Googling Java per scegliere una data casuale tra l'intervallo. Ho trovato il post this super utile e questa è la mia soluzione finale. Spero che possa aiutare i futuri programmatori Scala e Java.

import java.sql.Timestamp 

def date_rand(ts_start_str:String = "2012-01-01 00:00:00", ts_end_str:String = "2015-01-01 00:00:00"): String = { 
    val ts_start = Timestamp.valueOf(ts_start_str).getTime() 
    val ts_end = Timestamp.valueOf(ts_end_str).getTime() 
    val diff = ts_end - ts_start 
    println(diff) 
    val ts_rand = new Timestamp(ts_start + (Random.nextFloat() * diff).toLong) 
    return ts_rand.toString 
}           //> date_rand: (ts_start_str: String, ts_end_str: String)String 

println(date_rand())      //> 94694400000 
               //| 2012-10-28 18:21:13.216 

println(date_rand("2001-01-01 00:00:00", "2001-01-01 00:00:00")) 
               //> 0 
               //| 2001-01-01 00:00:00.0 
println(date_rand("2001-01-01 00:00:00", "2010-01-01 00:00:00")) 
               //> 283996800000 
               //| 2008-02-16 23:15:48.864     //> 2013-12-21 08:32:16.384 
23

Snippet per una soluzione basata su Java 8:

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

Nota: Questo genera una data casuale tra 1Jan1900 (incluso) e 1Jan2015 (esclusiva).

Nota: Si basa su epoch days, cioè giorni rispetto al 1Jan1970 (EPOCH) - significato positivo dopo EPOCH, significato negativo prima dell'epoca


È inoltre possibile creare una piccola classe di utilità:

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 + 
       '}'; 
    } 
} 

e usarlo in questo modo:

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 
+2

Questa è una risposta soddisfacente, ma la classe di utilità potrebbe essere resa un po 'più efficiente effettuando le conversioni toEpochDay() per min e max nel costruttore e salvando i risultati int invece dei LocalDates. Quindi deve essere eseguito una sola volta, anziché una volta per ogni chiamata a nextDate(). –

-1

riceverai la data in gg/mm/aaaa
Puoi usare il Math.funzione random() come ho fatto qui di seguito

qui stiamo generando 3 numeri casuali da 1 a 31,1 a 12,1990 al 2016 e concatenando "/" tra di loro

public static String getRandomJoinDate() 
    { 
     String date=""; 
     int yearBegin=1990; 
     int yearEnd=2016-yearBegin; 

     date=""+(1 + (int)(Math.random() * 31)+"/"+(1 + (int)(Math.random() * 12)+"/"+(yearBegin + (int)(Math.random() * yearEnd)))); 
     return date; 
    } 

sapere di più su Link Math.random() di seguito può aiutare
Math.random() explained

+1

spiega qualcosa .. !! –

2

è possibile verifica randomizer per la libreria di dati casuali generation.This aiuta a creare i dati casuali da dato modello class.Checkout sotto esempio di codice.

public class Person { 

    @DateValue(from = "01 Jan 1990",to = "31 Dec 2002" , customFormat = "dd MMM yyyy") 
    String dateOfBirth; 

} 

//Generate random 100 Person(Model Class) object 
Generator<Person> generator = new Generator<>(Person.class); 
List<Person> persons = generator.generate(100);       

come ci sono molti costruito nel generatore di dati è accessibile tramite l'annotazione, È inoltre possibile creare dati personalizzati generator.I vi proponiamo di passare attraverso documentazione fornita sulla pagina della libreria.

2

Guardate questo metodo:

public static Date dateRandom(int initialYear, int lastYear) { 
    if (initialYear > lastYear) { 
     int year = lastYear; 
     lastYear = initialYear; 
     initialYear = year; 
    } 

    Calendar cInitialYear = Calendar.getInstance(); 
    cInitialYear.set(Calendar.YEAR, 2015); 
    long offset = cInitialYear.getTimeInMillis(); 

    Calendar cLastYear = Calendar.getInstance(); 
    cLastYear.set(Calendar.YEAR, 2016); 
    long end = cLastYear.getTimeInMillis(); 

    long diff = end - offset + 1; 
    Timestamp timestamp = new Timestamp(offset + (long) (Math.random() * diff)); 
    return new Date(timestamp.getTime()); 
} 
2

Se non ti dispiace l'aggiunta di una nuova libreria per il codice è possibile utilizzare MockNeat (disclaimer: io sono uno degli autori).

MockNeat mock = MockNeat.threadLocal(); 

// Generates a random date between [1970-1-1, NOW) 
LocalDate localDate = mock.localDates().val(); 
System.out.println(localDate); 

// Generates a random date in the past 
// but beore 1987-1-30 
LocalDate min = LocalDate.of(1987, 1, 30); 
LocalDate past = mock.localDates().past(min).val(); 
System.out.println(past); 

LocalDate max = LocalDate.of(2020, 1, 1); 
LocalDate future = mock.localDates().future(max).val(); 
System.out.println(future); 

// Generates a random date between 1989-1-1 and 1993-1-1 
LocalDate start = LocalDate.of(1989, 1, 1); 
LocalDate stop = LocalDate.of(1993, 1, 1); 
LocalDate between = mock.localDates().between(start, stop).val(); 
System.out.println(between); 
2

Per Java8 -> assume di dati di nascita deve essere prima del giorno corrente:

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()); 
    } 
} 
+1

Considera l'uso di un ['ThreadLocalRandom'] (https://docs.oracle.com/javase/9/docs/api/java/util/concurrent/ThreadLocalRandom.html) piuttosto che l'istanziazione di un nuovo [' Random'] (https : //docs.oracle.com/javase/9/docs/api/java/util/Random.html) ogni volta. –

+0

Vero. Migliore pratica –

1

penso che questo farà il trucco:

public static void main(String[] args) { 
    Date now = new Date(); 
    long sixMonthsAgo = (now.getTime() - 15552000000l); 
    long today = now.getTime(); 

    for(int i=0; i<10; i++) { 
     long ms = ThreadLocalRandom.current().nextLong(sixMonthsAgo, today); 

     Date date = new Date(ms); 

     System.out.println(date.toString()); 
    } 

} 
1

Se non ti dispiace una libreria di terze parti, la libreria Utils ha un RandomDateUtils che genera java.util.Dates casuali e tutte le date, le ore, gli istanti e le durate da Java 8 date and time API

LocalDate birthDate = RandomDateUtils.randomPastLocalDate(); 
LocalDate today = LocalDate.now(); 
LocalDate under18YearsOld = RandomDateUtils.randomLocalDate(today.minus(18, YEARS), today); 
LocalDate over18YearsOld = RandomDateUtils.randomLocalDateBefore(today.minus(18, YEARS)); 

È nel Maven centrale Repository a:

<dependency> 
    <groupId>com.github.rkumsher</groupId> 
    <artifactId>utils</artifactId> 
    <version>1.0</version> 
</dependency> 
Problemi correlati