Generiranje slučajnih datuma u Javi

1. Pregled

U ovom uputstvu vidjet ćemo kako generirati slučajne datume i vremena na ograničen i neomeđen način.

Razmatrat ćemo kako generirati ove vrijednosti pomoću naslijeđa java.util.Datum API i nova knjižnica datuma i vremena s Jave 8.

2. Slučajni datum i vrijeme

Datumi i vremena nisu ništa više od 32-bitnih cijelih brojeva u usporedbi s epohom, tako da možemo generirati slučajne vremenske vrijednosti slijedeći ovaj jednostavan algoritam:

  1. Generirajte slučajni 32-bitni broj, int
  2. Proslijedite generiranu slučajnu vrijednost odgovarajućem konstruktoru datuma i vremena ili graditelju

2.1. Ograničena Trenutak

java.vrijeme.Instant jedan je od novih dodataka za datum i vrijeme u Javi 8. Oni predstavljaju trenutne točke na vremenskoj liniji.

Da bi se generirao slučajni slučaj Trenutak između dvije druge, možemo:

  1. Generirajte slučajni broj između epohnih sekundi zadane Trenutci
  2. Stvorite slučajno Trenutak prosljeđivanjem tog slučajnog broja na ofEpochSecond () metoda
javna statička Instant između (Instant startInclusive, Instant endExclusive) {long startSeconds = startInclusive.getEpochSecond (); long endSeconds = endExclusive.getEpochSecond (); long random = ThreadLocalRandom .current () .nextLong (startSeconds, endSeconds); return Instant.ofEpochSecond (slučajno); }

Da bismo postigli veću propusnost u okruženjima s više niti, koristimo ThreadLocalRandom za generiranje naših slučajnih brojeva.

Možemo provjeriti je li generirano Trenutak je uvijek veći ili jednak prvom Instant i je manje od drugog Trenutak:

Instant stotYearsAgo = Instant.now (). Minus (Duration.ofDays (100 * 365)); Instant tenDaysAgo = Instant.now (). Minus (Duration.ofDays (10)); Trenutačno slučajno = RandomDateTimes.be Between (stotYearsAgo, tenDaysAgo); assertThat (random) .isBetween (stotYearsAgo, tenDaysAgo);

Ne zaboravite, naravno, da je ispitivanje slučajnosti u osnovi nedeterminističko i da se obično ne preporučuje u stvarnoj aplikaciji.

Slično tome, također je moguće generirati slučajno Trenutak nakon ili prije drugog:

javna statička Instant after (Instant startInclusive) {povratak između (startInclusive, Instant.MAX); } javna statička Instant before (Instant upperExclusive) {return between (Instant.MIN, upperExclusive); }

2.2. Ograničena Datum

Jedan od java.util.Datum konstruktori uzimaju broj milisekundi nakon epohe. Dakle, isti algoritam možemo koristiti za generiranje slučajnog Datum između dvije druge:

javni statički datum između (Datum početkaInkluzivno, Datum završava Ekskluzivno) {long startMillis = startInclusive.getTime (); long endMillis = endExclusive.getTime (); long randomMillisSinceEpoch = ThreadLocalRandom .current () .nextLong (startMillis, endMillis); vrati novi datum (randomMillisSinceEpoch); }

Slično tome, trebali bismo biti u mogućnosti provjeriti ovo ponašanje:

long aDay = TimeUnit.DAYS.toMillis (1); long now = novi datum (). getTime (); Datum stoYearsAgo = novi datum (sada - dan * 365 * 100); Date tenDaysAgo = novi datum (sada - aDay * 10); Datum slučajan = LegacyRandomDateTimes.između (stoYearsAgo, tenDaysAgo); assertThat (random) .isBetween (stotYearsAgo, tenDaysAgo);

2.3. Neograničeno Trenutak

Da bi se generirao potpuno slučajan Trenutak, možemo jednostavno generirati slučajni cijeli broj i proslijediti ga na ofEpochSecond () metoda:

javna statička Instant vremenska oznaka () {return Instant.ofEpochSecond (ThreadLocalRandom.current (). nextInt ()); }

Korištenje 32-bitnih sekundi od epohe generira razumnija slučajna vremena, stoga koristimo nextInt () metoda ovdje.

Također, ta bi vrijednost trebala biti i dalje između minimalne i maksimalne moguće Trenutak vrijednosti koje Java može obraditi:

Trenutno slučajno = RandomDateTimes.timestamp (); assertThat (random) .isBetween (Instant.MIN, Instant.MAX);

2.4. Neograničeno Datum

Slično ograničenom primjeru, možemo proslijediti slučajnu vrijednost Datumi konstruktor za generiranje slučajnog Datum:

javna statička vremenska oznaka datuma () {vrati novi datum (ThreadLocalRandom.current (). nextInt () * 1000L); }

Budući da jevremenska jedinica konstruktora je milisekunde, pretvaramo 32-bitne epohe sekunde u milisekunde množeći je s 1000.

Svakako, ta je vrijednost još uvijek između minimalne i maksimalne moguće Datum vrijednosti:

Datum MIN_DATE = novi datum (Long.MIN_VALUE); Datum MAX_DATE = novi datum (Long.MAX_VALUE); Datum slučajan = LegacyRandomDateTimes.timestamp (); assertThat (random) .isBetween (MIN_DATE, MAX_DATE);

3. Slučajan datum

Do sada smo generirali nasumične vremenske brojeve koji sadrže i datumske i vremenske komponente. Slično tome, možemo koristiti koncept epošnih dana da bismo generirali nasumične vremenske okvire s komponentama samo datuma.

Dan epohe jednak je broju dana od 1. siječnja 1970. Dakle, da bi se generirao slučajan datum, mi jednostavno moramo generirati slučajni broj i taj broj upotrijebiti kao epošni dan.

3.1. Ograničena

Trebamo privremenu apstrakciju koja sadrži samo datumske komponente, dakle java.time.LocalDate čini se dobrim kandidatom:

javni statički LocalDate između (LocalDate startInclusive, LocalDate endExclusive) {long startEpochDay = startInclusive.toEpochDay (); long endEpochDay = endExclusive.toEpochDay (); long randomDay = ThreadLocalRandom .current () .nextLong (startEpochDay, endEpochDay); vratiti LocalDate.ofEpochDay (randomDay); }

Ovdje koristimo toEpochDay () metoda za pretvaranje svake LocalDate do odgovarajućeg dana epohe. Slično tome, možemo provjeriti je li ovaj pristup točan:

LocalDate start = LocalDate.of (1989, mjesec.OKTOBAR, 14); Kraj lokalnog datuma = LocalDate.now (); LocalDate random = RandomDates.between (početak, kraj); assertThat (random) .isBetween (početak, kraj);

3.2. Neograničeno

Kako bismo generirali slučajne datume bez obzira na bilo koji raspon, možemo jednostavno generirati slučajni epošni dan:

javni statični datum LocalDate () {int stoGodina = 100 * 365; return LocalDate.ofEpochDay (ThreadLocalRandom .current (). nextInt (-h stotina godina, sto godina)); }

Naš generator slučajnih datuma bira slučajni dan od 100 godina prije i nakon epohe. Opet, obrazloženje ovoga je generiranje razumnih datumskih vrijednosti:

LocalDate randomDay = RandomDates.date (); assertThat (randomDay) .isBetween (LocalDate.MIN, LocalDate.MAX);

4. Slučajno vrijeme

Slično onome što smo radili s datumima, možemo generirati slučajne vremenske temelje sa samo vremenskim komponentama. Da bi to učinili, možemo koristiti koncept drugog dana. To je, slučajno vrijeme jednako je slučajnom broju koji predstavlja sekunde od početka dana.

4.1. Ograničena

The java.time.LocalTime klasa je vremenska apstrakcija koja ne obuhvaća ništa osim vremenskih komponenata:

javno statično LocalTime između (LocalTime startTime, LocalTime endTime) {int startSeconds = startTime.toSecondOfDay (); int endSeconds = endTime.toSecondOfDay (); int randomTime = ThreadLocalRandom .current () .nextInt (startSeconds, endSeconds); vratiti LocalTime.ofSecondOfDay (randomTime); }

Kako bismo generirali slučajno vrijeme između dvoje drugih, možemo:

  1. Generirajte slučajni broj između drugog dana dana
  2. Stvorite slučajno vrijeme pomoću tog slučajnog broja

Lako možemo provjeriti ponašanje ovog algoritma generiranja slučajnog vremena:

LocalTime morning = LocalTime.of (8, 30); LocalTime randomTime = RandomTimes.između (LocalTime.MIDNIGHT, jutro); assertThat (randomTime) .isBetween (LocalTime.MIDNIGHT, morning) .isBetween (LocalTime.MIN, LocalTime.MAX);

4.2. Neograničeno

Čak i neograničene vrijednosti vremena trebale bi biti u rasponu od 00:00:00 do 23:59:59, tako da ovu logiku možemo jednostavno implementirati delegiranjem:

javno statično LocalTime vrijeme () {povratak između (LocalTime.MIN, LocalTime.MAX); }

5. Zaključak

U ovom uputstvu smanjili smo definiciju slučajnih datuma i vremena na slučajne brojeve. Tada smo vidjeli kako nam je ovo smanjenje pomoglo da generiramo slučajne vremenske vrijednosti koje se ponašaju poput vremenskih oznaka, datuma ili vremena.

Kao i obično, uzorak koda dostupan je na GitHubu.


$config[zx-auto] not found$config[zx-overlay] not found