Willekeurige datums genereren in Java

1. Overzicht

In deze tutorial gaan we zien hoe we willekeurige datums en tijden kunnen genereren in begrensde en onbegrensde modes.

We zullen bekijken hoe we deze waarden kunnen genereren met behulp van de erfenis java.util.Date API en ook de nieuwe datum-tijdbibliotheek van Java 8.

2. Willekeurige datum en tijd

Datums en tijden zijn niets meer dan 32-bits gehele getallen vergeleken met een epoch-tijd, dus we kunnen willekeurige tijdelijke waarden genereren door dit eenvoudige algoritme te volgen:

  1. Genereer een willekeurig 32-bits getal, een int
  2. Geef de gegenereerde willekeurige waarde door aan een geschikte constructor of builder voor datum en tijd

2.1. Begrensd Onmiddellijk

java.time.Instant is een van de nieuwe toevoegingen aan datum en tijd in Java 8. Ze vertegenwoordigen momentane punten op de tijdlijn.

Om een ​​random Onmiddellijk tussen twee andere kunnen we:

  1. Genereer een willekeurig getal tussen de epochseconden van het gegeven Instants
  2. Creëer het willekeurige Onmiddellijk door dat willekeurige nummer door te geven aan de ofEpochSecond () methode
openbare statische Instant tussen (Instant startInclusive, Instant endExclusive) {long startSeconds = startInclusive.getEpochSecond (); long endSeconds = endExclusive.getEpochSecond (); long random = ThreadLocalRandom .current () .nextLong (startSeconds, endSeconds); retourneer Instant.ofEpochSecond (willekeurig); }

Om meer doorvoer te behalen in omgevingen met meerdere threads, gebruiken we de ThreadLocalRandom om onze willekeurige getallen te genereren.

We kunnen verifiëren dat het gegenereerde Onmiddellijk is altijd groter dan of gelijk aan de eerste Instant en is minder dan de tweede Onmiddellijk:

Instant honderdYearsAgo = Instant.now (). Minus (Duration.ofDays (100 * 365)); Instant tenDaysAgo = Instant.now (). Minus (Duration.ofDays (10)); Instant random = RandomDateTimes.between (honderdYearsAgo, tenDaysAgo); assertThat (willekeurig) .isBetween (honderdYearsAgo, tenDaysAgo);

Onthoud natuurlijk dat het testen van willekeur inherent niet-deterministisch is en over het algemeen niet wordt aanbevolen in een echte toepassing.

Evenzo is het ook mogelijk om een ​​random Onmiddellijk na of voor een andere:

openbare statische Instant after (Instant startInclusive) {return between (startInclusive, Instant.MAX); } public static Instant before (Instant upperExclusive) {return tussen (Instant.MIN, upperExclusive); }

2.2. Begrensd Datum

Een van de java.util.Date constructors nemen het aantal milliseconden na de epoch. We kunnen dus hetzelfde algoritme gebruiken om een ​​willekeurige Datum tussen twee anderen:

openbare statische Datum tussen (Datum startInclusief, Datum eindeExclusief) {long startMillis = startInclusive.getTime (); long endMillis = endExclusive.getTime (); lang randomMillisSinceEpoch = ThreadLocalRandom .current () .nextLong (startMillis, endMillis); retourneer nieuwe datum (randomMillisSinceEpoch); }

Evenzo zouden we dit gedrag moeten kunnen verifiëren:

lange aDay = TimeUnit.DAYS.toMillis (1); nu lang = nieuwe datum (). getTime (); Datum honderdYearsAgo = nieuwe datum (nu - aDay * 365 * 100); Datum tenDaysAgo = nieuwe datum (nu - aDay * 10); Datum willekeurig = LegacyRandomDateTimes.between (honderdYearsAgo, tenDaysAgo); assertThat (willekeurig) .isBetween (honderdYearsAgo, tenDaysAgo);

2.3. Onbegrensd Onmiddellijk

Om een ​​totaal willekeurig Onmiddellijk, kunnen we eenvoudig een willekeurig geheel getal genereren en dit doorgeven aan de ofEpochSecond () methode:

openbare statische Instant timestamp () {return Instant.ofEpochSecond (ThreadLocalRandom.current (). nextInt ()); }

Het gebruik van 32-bits seconden sinds de epoch-tijd genereert redelijkere willekeurige tijden, daarom gebruiken we de volgendeInt () methode hier.

Deze waarde moet ook nog tussen het minimum en maximum liggen Onmiddellijk waarden die Java aankan:

Instant random = RandomDateTimes.timestamp (); assertThat (willekeurig) .isBetween (Instant.MIN, Instant.MAX);

2.4. Onbegrensd Datum

Net als bij het begrensde voorbeeld kunnen we een willekeurige waarde doorgeven aan Datum constructor om een ​​willekeurig Datum:

openbare statische datum timestamp () {terugkeer nieuwe datum (ThreadLocalRandom.current (). nextInt () * 1000L); }

Sinds dede tijdseenheid van de constructeur is milliseconden, we converteren de 32-bit epochseconden naar milliseconden door het te vermenigvuldigen met 1000.

Deze waarde ligt zeker nog tussen het minimum en maximum mogelijk Datum waarden:

Datum MIN_DATE = nieuwe datum (Long.MIN_VALUE); Datum MAX_DATE = nieuwe datum (Long.MAX_VALUE); Datum willekeurig = LegacyRandomDateTimes.timestamp (); assertThat (willekeurig) .isBetween (MIN_DATE, MAX_DATE);

3. Willekeurige datum

Tot nu toe hebben we willekeurige temporals gegenereerd die zowel datum- als tijdcomponenten bevatten. Evenzo we kunnen het concept van epoch-dagen gebruiken om willekeurige tijdwaarden te genereren met alleen datumcomponenten.

Een epochendag is gelijk aan het aantal dagen sinds 1 januari 1970. Dus om een ​​willekeurige datum te genereren, we hoeven alleen maar een willekeurig nummer te genereren en dat nummer te gebruiken als de epoch-dag.

3.1. Begrensd

We hebben een tijdelijke abstractie nodig die alleen datumcomponenten bevat, dus java.time.LocalDate lijkt een goede kandidaat:

openbare statische LocalDate tussen (LocalDate startInclusive, LocalDate endExclusive) {long startEpochDay = startInclusive.toEpochDay (); long endEpochDay = endExclusive.toEpochDay (); long randomDay = ThreadLocalRandom .current () .nextLong (startEpochDay, endEpochDay); retourneer LocalDate.ofEpochDay (randomDay); }

Hier gebruiken we de toEpochDay () methode om elk LocalDate naar de corresponderende epochendag. Evenzo kunnen we controleren of deze aanpak correct is:

LocalDate start = LocalDate.of (1989, Month.OCTOBER, 14); LocalDate end = LocalDate.now (); LocalDate random = RandomDates.between (start, end); assertThat (willekeurig) .isBetween (begin, einde);

3.2. Onbegrensd

Om willekeurige datums te genereren, ongeacht een bereik, kunnen we eenvoudig een willekeurige epoch-dag genereren:

openbare statische LocalDate date () {int honderdYears = 100 * 365; retourneer LocalDate.ofEpochDay (ThreadLocalRandom .current (). nextInt (-hundredYears, honderdenYears)); }

Onze willekeurige datumgenerator kiest een willekeurige dag uit 100 jaar voor en na het tijdperk. Nogmaals, de grondgedachte hierachter is om redelijke datumwaarden te genereren:

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

4. Willekeurige tijd

Net als wat we deden met datums, kunnen we willekeurige temporele waarden genereren met alleen tijdcomponenten. Om dat te doen, we kunnen het tweede van de dag-concept gebruiken. Dat is, een willekeurige tijd is gelijk aan een willekeurig getal dat de seconden vertegenwoordigt sinds het begin van de dag.

4.1. Begrensd

De java.time.LocalTime klasse is een tijdelijke abstractie die niets anders dan tijdcomponenten omvat:

openbare statische LocalTime tussen (LocalTime startTime, LocalTime endTime) {int startSeconds = startTime.toSecondOfDay (); int endSeconds = endTime.toSecondOfDay (); int randomTime = ThreadLocalRandom .current () .nextInt (startSeconds, endSeconds); retourneer LocalTime.ofSecondOfDay (randomTime); }

Om een ​​willekeurige tijd tussen twee andere te genereren, kunnen we:

  1. Genereer een willekeurig getal tussen de tweede van de dag van de opgegeven tijden
  2. Maak een willekeurige tijd met dat willekeurige nummer

We kunnen eenvoudig het gedrag van dit algoritme voor het genereren van willekeurige tijd verifiëren:

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

4.2. Onbegrensd

Zelfs onbegrensde tijdwaarden moeten in het bereik van 00:00:00 tot 23:59:59 liggen, dus we kunnen deze logica eenvoudig implementeren door te delegeren:

openbare statische LocalTime time () {terugkeer tussen (LocalTime.MIN, LocalTime.MAX); }

5. Conclusie

In deze tutorial hebben we de definitie van willekeurige datums en tijden teruggebracht tot willekeurige getallen. Vervolgens zagen we hoe deze reductie ons hielp om willekeurige temporele waarden te genereren die zich gedroegen als tijdstempels, datums of tijden.

Zoals gewoonlijk is de voorbeeldcode beschikbaar op GitHub.


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