Genererer tilfeldige datoer i Java

1. Oversikt

I denne opplæringen skal vi se hvordan du genererer tilfeldige datoer og klokkeslett i avgrensede og ubegrensede moter.

Vi vil se på hvordan vi kan generere disse verdiene ved hjelp av arven java.util.Date API og også det nye datotidsbiblioteket fra Java 8.

2. Tilfeldig dato og klokkeslett

Datoer og tider er ikke mer enn 32-biters heltall sammenlignet med en epoketid, slik at vi kan generere tilfeldige tidsverdier ved å følge denne enkle algoritmen:

  1. Generer et tilfeldig 32-bit nummer, et int
  2. Gi den genererte tilfeldige verdien til en passende dato og tidskonstruktør eller byggherre

2.1. Begrenset Umiddelbar

java.time.Instant er en av de nye dato- og tidstilleggene i Java 8. De representerer øyeblikkelige punkter på tidslinjen.

For å generere en tilfeldig Umiddelbar mellom to andre, kan vi:

  1. Generer et tilfeldig tall mellom de angitte periodene Øyeblikkelig
  2. Lag tilfeldig Umiddelbar ved å overføre det tilfeldige tallet til ofEpochSecond () metode
offentlig statisk øyeblikkelig mellom (Instant startInclusive, Instant endExclusive) {long startSeconds = startInclusive.getEpochSecond (); long endSeconds = endExclusive.getEpochSecond (); lang tilfeldig = ThreadLocalRandom .current () .nextLong (startSeconds, endSeconds); returner Instant.ofEpochSecond (tilfeldig); }

For å oppnå mer gjennomstrømning i miljøer med flere tråder bruker vi ThreadLocalRandom for å generere tilfeldige tall.

Vi kan bekrefte at den genererte Umiddelbar er alltid større enn eller lik den første Øyeblikkelig og er mindre enn det andre Umiddelbar:

Øyeblikkelig hundredYearsAgo = Instant.now (). Minus (Duration.ofDays (100 * 365)); Øyeblikkelig tenDaysAgo = Instant.now (). Minus (Duration.ofDays (10)); Øyeblikkelig tilfeldig = RandomDateTimes.between (hundredYearsAgo, tenDaysAgo); assertThat (random) .isBetween (hundredYearsAgo, tenDaysAgo);

Husk selvfølgelig at testing av tilfeldighet i seg selv ikke er deterministisk og generelt ikke anbefales i en reell applikasjon.

På samme måte er det også mulig å generere en tilfeldig Umiddelbar etter eller før en annen:

offentlig statisk Øyeblikkelig etter (Øyeblikkelig startInclusive) {retur mellom (startInclusive, Instant.MAX); } offentlig statisk Øyeblikkelig før (Øyeblikkelig upperExclusive) {retur mellom (Instant.MIN, upperExclusive); }

2.2. Begrenset Dato

En av java.util.Date konstruktører tar antall millisekunder etter epoken. Så vi kan bruke den samme algoritmen til å generere en tilfeldig Dato mellom to andre:

offentlig statisk dato mellom (Date startInclusive, Date endExclusive) {long startMillis = startInclusive.getTime (); long endMillis = endExclusive.getTime (); long randomMillisSinceEpoch = ThreadLocalRandom .current () .nextLong (startMillis, endMillis); returner ny dato (randomMillisSinceEpoch); }

På samme måte bør vi kunne bekrefte denne oppførselen:

lang aDay = TimeUnit.DAYS.toMillis (1); lenge nå = ny dato (). getTime (); Date hundredYearsAgo = new Date (now - aDay * 365 * 100); Date tenDaysAgo = new Date (now - aDay * 10); Tilfeldig dato = LegacyRandomDateTimes.between (hundredYearsAgo, tenDaysAgo); assertThat (random) .isBetween (hundredYearsAgo, tenDaysAgo);

2.3. Ubegrenset Umiddelbar

For å generere en helt tilfeldig Umiddelbar, kan vi ganske enkelt generere et tilfeldig heltall og overføre det til ofEpochSecond () metode:

offentlig statisk øyeblikkelig tidsstempel () {retur Instant.ofEpochSecond (ThreadLocalRandom.current (). nextInt ()); }

Bruk av 32-bits sekunder siden epoken genererer rimeligere tilfeldige tider, derfor bruker vi nesteInt () metoden her.

Denne verdien bør også være mellom minimum og maksimum mulig Umiddelbar verdier som Java kan håndtere:

Øyeblikkelig tilfeldig = RandomDateTimes.timestamp (); assertThat (random) .isBetween (Instant.MIN, Instant.MAX);

2.4. Ubegrenset Dato

I likhet med det avgrensede eksemplet kan vi overføre en tilfeldig verdi til Dato er konstruktør for å generere en tilfeldig Dato:

public static Date timestamp () {return new Date (ThreadLocalRandom.current (). nextInt () * 1000L); }

Sidenkonstruktørens tidsenhet er millisekunder, vi konverterer 32-biters epok sekunder til millisekunder ved å multiplisere den med 1000.

Absolutt er denne verdien fortsatt mellom minimum og maksimum mulig Dato verdier:

Dato MIN_DATE = ny dato (Long.MIN_VALUE); Dato MAX_DATE = ny dato (Long.MAX_VALUE); Tilfeldig dato = LegacyRandomDateTimes.timestamp (); assertThat (tilfeldig) .isBetween (MIN_DATE, MAX_DATE);

3. Tilfeldig dato

Inntil nå genererte vi tilfeldige temporals som inneholder både dato- og tidskomponenter. På samme måte, vi kan bruke begrepet epoke dager til å generere tilfeldige temporals med bare dato komponenter.

En epoke-dag er lik antall dager siden 1. januar 1970. Så for å generere en tilfeldig dato, vi må bare generere et tilfeldig tall og bruke det tallet som epoken.

3.1. Begrenset

Vi trenger en tidsmessig abstraksjon som bare inneholder datokomponenter, så java.time.LocalDate virker en god kandidat:

offentlig statisk LocalDate mellom (LocalDate startInclusive, LocalDate endExclusive) {lang startEpochDay = startInclusive.toEpochDay (); lang sluttEpochDay = endExclusive.toEpochDay (); lang randomDay = ThreadLocalRandom .current () .nextLong (startEpochDay, endEpochDay); returner LocalDate.ofEpochDay (randomDay); }

Her bruker vi toEpochDay () metode for å konvertere hver LocalDate til den tilsvarende epoken. På samme måte kan vi bekrefte at denne tilnærmingen er riktig:

LocalDate start = LocalDate.of (1989, måned.OCTOBER, 14); LocalDate end = LocalDate.now (); LocalDate random = RandomDates.between (start, end); assertThat (tilfeldig) .isBetween (start, slutt);

3.2. Ubegrenset

For å generere tilfeldige datoer uavhengig av hvilket som helst område, kan vi ganske enkelt generere en tilfeldig tidsdag:

offentlig statisk LocalDate-dato () {int hundredYears = 100 * 365; return LocalDate.ofEpochDay (ThreadLocalRandom .current (). nextInt (-hundredår, hundreår)); }

Vår tilfeldige datagenerator velger en tilfeldig dag fra 100 år før og etter epoken. Igjen, begrunnelsen bak dette er å generere rimelige datoverdier:

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

4. Tilfeldig tid

I likhet med hva vi gjorde med datoer, kan vi generere tilfeldige temporals med bare tidskomponenter. For å gjøre det, vi kan bruke det andre av dagen konseptet. Det er, en tilfeldig tid er lik et tilfeldig tall som representerer sekundene siden begynnelsen av dagen.

4.1. Begrenset

De java.time.LocalTime klasse er en tidsmessig abstraksjon som ikke innkapsler annet enn tidskomponenter:

offentlig statisk LocalTime mellom (LocalTime startTime, LocalTime endTime) {int startSeconds = startTime.toSecondOfDay (); int endSeconds = endTime.toSecondOfDay (); int randomTime = ThreadLocalRandom .current () .nextInt (startSeconds, endSeconds); returner LocalTime.ofSecondOfDay (randomTime); }

For å generere en tilfeldig tid mellom to andre, kan vi:

  1. Generer et tilfeldig tall mellom den andre dagen av de angitte tidene
  2. Lag et tilfeldig tidspunkt ved å bruke det tilfeldige tallet

Vi kan enkelt bekrefte atferden til denne tilfeldige tidsgenereringsalgoritmen:

LocalTime morgen = LocalTime.of (8, 30); LocalTime randomTime = RandomTimes.between (LocalTime.MIDNIGHT, morgen); assertThat (randomTime) .isBetween (LocalTime.MIDNIGHT, morning) .isBetween (LocalTime.MIN, LocalTime.MAX);

4.2. Ubegrenset

Selv ubegrensede tidsverdier bør være i området 00:00:00 til 23:59:59, så vi kan ganske enkelt implementere denne logikken ved delegering:

offentlig statisk LocalTime-tid () {retur mellom (LocalTime.MIN, LocalTime.MAX); }

5. Konklusjon

I denne opplæringen reduserte vi definisjonen av tilfeldige datoer og tider til tilfeldige tall. Så så vi hvordan denne reduksjonen hjalp oss med å generere tilfeldige tidsverdier som oppførte seg som tidsstempler, datoer eller klokkeslett.

Eksempelkoden er som vanlig tilgjengelig på GitHub.


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