Generering af tilfældige datoer i Java

1. Oversigt

I denne vejledning skal vi se, hvordan man genererer tilfældige datoer og tidspunkter i afgrænsede og ubegrænsede mode.

Vi ser på, hvordan man genererer disse værdier ved hjælp af arven java.util.Date API og også det nye dato-tidsbibliotek fra Java 8.

2. Tilfældig dato og tid

Datoer og tidspunkter er intet mere end 32-bit heltal sammenlignet med en epoke-tid, så vi kan generere tilfældige tidsværdier ved at følge denne enkle algoritme:

  1. Generer et tilfældigt 32-bit nummer, et int
  2. Videregiv den genererede tilfældige værdi til en passende dato og tidskonstruktør eller bygherre

2.1. Begrænset Øjeblikkelig

java.time.Instant er en af ​​de nye tilføjelser til dato og tid i Java 8. De repræsenterer øjeblikkelige punkter på tidslinjen.

For at generere en tilfældig Øjeblikkelig mellem to andre kan vi:

  1. Generer et tilfældigt tal mellem de givne tidsperioder Øjeblikkelige
  2. Opret tilfældigt Øjeblikkelig ved at sende det tilfældige tal til ofEpochSecond () metode
offentlig statisk Øjeblikkelig mellem (Øjeblikkelig startInclusive, Øjeblikkelig endExclusive) {long startSeconds = startInclusive.getEpochSecond (); long endSeconds = endExclusive.getEpochSecond (); lang tilfældig = ThreadLocalRandom .current () .nextLong (startSeconds, endSeconds); returner Instant.ofEpochSecond (tilfældig); }

For at opnå mere gennemstrømning i miljøer med flere tråde bruger vi ThreadLocalRandom for at generere vores tilfældige tal.

Vi kan kontrollere, at den genererede Øjeblikkelig er altid større end eller lig med den første Øjeblikkelig og er mindre end det andet Øjeblikkelig:

Øjeblikkelig hundredYearsAgo = Instant.now (). Minus (Duration.ofDays (100 * 365)); Øjeblikkelig tenDaysAgo = Øjeblikkelig. Nu (). Minus (Varighed.afDage (10)); Øjeblikkelig tilfældig = RandomDateTimes.between (hundredYearsAgo, tenDaysAgo); assertThat (tilfældig) .isBetween (hundredYearsAgo, tenDaysAgo);

Husk selvfølgelig, at test af tilfældighed er i sagens natur ikke-deterministisk og generelt ikke anbefales i en reel applikation.

På samme måde er det også muligt at generere en tilfældig Øjeblikkelig efter eller før en anden:

offentlig statisk Øjeblikkelig efter (Øjeblikkelig startInclusive) {retur mellem (startInclusive, Instant.MAX); } offentlig statisk Øjeblikkelig før (Øjeblikkelig upperExclusive) {return mellem (Instant.MIN, upperExclusive); }

2.2. Begrænset Dato

En af de java.util.Date konstruktører tager antallet af millisekunder efter epoken. Så vi kan bruge den samme algoritme til at generere en tilfældig Dato mellem to andre:

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

På samme måde skal vi være i stand til at kontrollere denne adfærd:

lang aDay = TimeUnit.DAYS.toMillis (1); lang nu = ny dato (). getTime (); Dato hundredYearsAgo = ny dato (nu - aDag * 365 * 100); Dato tenDaysAgo = ny dato (nu - aDag * 10); Dato tilfældig = LegacyRandomDateTimes.between (hundredYearsAgo, tenDaysAgo); assertThat (tilfældig) .isBetween (hundredYearsAgo, tenDaysAgo);

2.3. Ubegrænset Øjeblikkelig

For at generere en helt tilfældig Øjeblikkelig, kan vi simpelthen generere et tilfældigt heltal og videregive det til ofEpochSecond () metode:

offentlig statisk øjeblikkelig tidsstempel () {returner Instant.ofEpochSecond (ThreadLocalRandom.current (). nextInt ()); }

Brug af 32-bit sekunder siden epoken genererer mere rimelige tilfældige tider, derfor bruger vi næsteInt () metode her.

Denne værdi skal også være mellem det mindste og maksimale mulige Øjeblikkelig værdier, som Java kan håndtere:

Øjeblikkelig tilfældig = RandomDateTimes.timestamp (); assertThat (tilfældig) .isBetween (Instant.MIN, Instant.MAX);

2.4. Ubegrænset Dato

I lighed med det afgrænsede eksempel kan vi overføre en tilfældig værdi til Dato er konstruktør til at generere en tilfældig Dato:

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

Siden denkonstruktørens tidsenhed er millisekunder, vi konverterer 32-bit-epoken sekunder til millisekunder ved at gange den med 1000.

Bestemt er denne værdi stadig mellem det mindste og det maksimale mulige Dato værdier:

Dato MIN_DATE = ny dato (Lang.MIN_VALUE); Dato MAX_DATE = ny dato (Long.MAX_VALUE); Dato tilfældig = LegacyRandomDateTimes.timestamp (); assertThat (tilfældig) .isBetween (MIN_DATE, MAX_DATE);

3. Tilfældig dato

Indtil nu genererede vi tilfældige temporale, der indeholder både dato- og tidskomponenter. Tilsvarende Vi kan bruge begrebet epoke dage til at generere tilfældige temporals med kun dato komponenter.

En epoke-dag er lig med antallet af dage siden 1. januar 1970. Så for at generere en tilfældig dato, vi er bare nødt til at generere et tilfældigt tal og bruge dette nummer som epoke-dagen.

3.1. Begrænset

Vi har brug for en tidsmæssig abstraktion, der kun indeholder datakomponenter, så java.time.LocalDate synes en god kandidat:

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

Her bruger vi toEpochDay () metode til at konvertere hver LocalDate til den tilsvarende epoke-dag. På samme måde kan vi kontrollere, at denne tilgang er korrekt:

LocalDate start = LocalDate.of (1989, måned.OCTOBER, 14); LocalDate end = LocalDate.now (); LocalDate random = RandomDates.between (start, end); assertThat (tilfældig) .isBetween (start, slut);

3.2. Ubegrænset

For at generere tilfældige datoer uanset hvilket som helst interval kan vi simpelthen generere en tilfældig tidsdag:

offentlig statisk LocalDate-dato () {int hundredYears = 100 * 365; returnere LocalDate.ofEpochDay (ThreadLocalRandom .current (). nextInt (-hundredYears, hundredYears)); }

Vores tilfældige datagenerator vælger en tilfældig dag fra 100 år før og efter epoken. Igen er begrundelsen bag dette at generere rimelige datoværdier:

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

4. Tilfældig tid

I lighed med hvad vi gjorde med datoer, kan vi generere tilfældige tidsmæssige med kun tidskomponenter. For at gøre det, vi kan bruge det andet af dagen konceptet. Det er, en tilfældig tid er lig med et tilfældigt tal, der repræsenterer sekunderne siden begyndelsen af ​​dagen.

4.1. Begrænset

Det java.time.LocalTime klasse er en tidsmæssig abstraktion, der kun indkapsler tidskomponenter:

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

For at generere en tilfældig tid mellem to andre kan vi:

  1. Generer et tilfældigt tal mellem den anden dag på de givne tidspunkter
  2. Opret en tilfældig tid ved hjælp af det tilfældige tal

Vi kan let kontrollere opførelsen af ​​denne tilfældige tidsgenereringsalgoritme:

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. Ubegrænset

Selv ubegrænsede tidsværdier skal være i området 00:00:00 indtil 23:59:59, så vi kan simpelthen implementere denne logik ved delegation:

offentlig statisk LocalTime-tid () {return mellem (LocalTime.MIN, LocalTime.MAX); }

5. Konklusion

I denne vejledning reducerede vi definitionen af ​​tilfældige datoer og tidspunkter til tilfældige tal. Derefter så vi, hvordan denne reduktion hjalp os med at generere tilfældige tidsmæssige værdier, der opførte sig som tidsstempler, datoer eller tidspunkter.

Som sædvanlig er prøvekoden tilgængelig på GitHub.