Véletlen dátumok generálása Java-ban
1. Áttekintés
Ebben az oktatóanyagban azt fogjuk megtudni, hogyan lehet véletlen dátumokat és időpontokat generálni korlátozott és korlátlan divatban.
Megvizsgáljuk, hogyan lehet ezeket az értékeket előállítani a örökség segítségével java.util.Dátum API, valamint a Java 8 új dátum-idő könyvtár.
2. Véletlenszerű dátum és idő
A dátumok és idők nem több, mint 32 bites egész számok egy korszakhoz képest, így véletlenszerű időbeli értékeket generálhatunk az egyszerű algoritmus követésével:
- Generáljon véletlenszerű 32 bites számot, egy int
- Adja át a generált véletlenértéket egy megfelelő dátum- és időszerkesztőnek vagy készítőnek
2.1. Megkötve Azonnali
java.time.Instant a Java 8 egyik új dátum- és idő-kiegészítése. Az idősor pillanatnyi pontjait képviselik.
Egy véletlen generálása érdekében Azonnali két másik között:
- Generáljon véletlenszerű számot az adott korszak másodpercei között Azonnali
- Hozza létre a véletlenszerűt Azonnali a véletlen szám átadásával a ofEpochSecond () módszer
public static Azonnali (Instant startInclusive, Instant endExclusive) {long startSeconds = startInclusive.getEpochSecond (); long endSeconds = endExclusive.getEpochSecond (); hosszú véletlenszerű = ThreadLocalRandom .current () .nextLong (startSeconds, endSeconds); return Instant.ofEpochSecond (véletlenszerű); }
Annak érdekében, hogy több szálú környezetben nagyobb teljesítményt érjünk el, a ThreadLocalRandom hogy előállítsuk a véletlenszerű számainkat.
Ellenőrizhetjük, hogy a létrehozott Azonnali mindig nagyobb vagy egyenlő az elsővel Azonnali és kevesebb, mint a második Azonnali:
Azonnali száz évAgo = Azonnali most (). Mínusz (Napok időtartama (100 * 365)); Instant tenDaysAgo = Instant.now (). Mínusz (Durations.ofDays (10)); Azonnali véletlenszerű = RandomDateTimes.between (százYearsAgo, tenDaysAgo); assertThat (véletlenszerű) .isBetween (százYearsAgo, tenDaysAgo);
Ne feledje, természetesen, hogy a véletlenszerűség tesztelése eleve nem determinisztikus, és általában nem ajánlott egy valós alkalmazásban.
Hasonlóképpen lehetséges véletlenszerű generálás is Azonnali egy másik után vagy előtt:
public static Azonnali (Instant startInclusive) {visszatérés között (startInclusive, Instant.MAX); } public static Instant before (Instant upperExclusive) {visszatérés között (Instant.MIN, upperExclusive); }
2.2. Megkötve Dátum
Az egyik java.util.Dátum a kivitelezők a korszak után milliszekundumok számát veszik fel. Tehát ugyanazt az algoritmust használhatjuk véletlenszerű generálására Dátum két másik között:
public static Dátum között (Date startInclusive, Date endExclusive) {long startMillis = startInclusive.getTime (); long endMillis = endExclusive.getTime (); hosszú randomMillisSinceEpoch = ThreadLocalRandom .current () .nextLong (startMillis, endMillis); return new Date (randomMillisSinceEpoch); }
Hasonlóképpen képesnek kell lennünk ellenőrizni ezt a viselkedést:
hosszú aDay = TimeUnit.DAYS.toMillis (1); régóta = új dátum (). getTime (); Dátum százYearsAgo = új dátum (most - nap * 365 * 100); Dátum tenDaysAgo = új dátum (most - aDay * 10); Dátum véletlenszerű = LegacyRandomDateTimes.between (százYearsAgo, tenDaysAgo); assertThat (véletlenszerű) .isBetween (százYearsAgo, tenDaysAgo);
2.3. Határtalan Azonnali
Teljesen véletlenszerű generálás érdekében Azonnali, egyszerűen létrehozhatunk egy véletlenszerű egész számot, és átadhatjuk a ofEpochSecond () módszer:
public static Azonnali időbélyeg () {return Instant.ofEpochSecond (ThreadLocalRandom.current (). nextInt ()); }
32 bites másodpercek használata, mivel a korszak ideje ésszerűbb véletlenszerű időket generál, ezért használjuk a nextInt () módszer itt.
Ezen értéknek továbbra is a lehető legkisebb és maximális között kell lennie Azonnali a Java által kezelhető értékek:
Instant random = RandomDateTimes.timestamp (); assertThat (véletlenszerű) .isBetween (Instant.MIN, Instant.MAX);
2.4. Határtalan Dátum
A behatárolt példához hasonlóan véletlenszerű értéket is átadhatunk Dátum konstruktor véletlenszerű generálásához Dátum:
public static Dátum időbélyeg () {return new Date (ThreadLocalRandom.current (). nextInt () * 1000L); }
Mivel aa konstruktor időegysége ezredmásodperc, a 32 bites korszak másodperceket milliszekundummá konvertáljuk, megszorozva 1000-vel.
Természetesen ez az érték még mindig a lehetséges minimum és maximum között van Dátum értékek:
Dátum MIN_DATE = új dátum (Long.MIN_VALUE); Dátum MAX_DATE = új dátum (Long.MAX_VALUE); Dátum véletlenszerű = LegacyRandomDateTimes.timestamp (); assertThat (véletlenszerű) .isBetween (MIN_DATE, MAX_DATE);
3. Véletlenszerű dátum
Eddig véletlenszerű időbeli adatokat generáltunk, amelyek dátum és idő komponenseket egyaránt tartalmaznak. Hasonlóképpen, használhatjuk a korszakos napok fogalmát véletlenszerű időbeli adatok előállításához, csak dátumösszetevőkkel.
Egy korszak napja megegyezik az 1970. január 1-je óta eltelt napok számával. Tehát egy véletlenszerű dátum generálása érdekében csak generálnunk kell egy véletlen számot, és ezt a számot használjuk korszakként.
3.1. Megkötve
Szükségünk van egy időbeli absztrakcióra, amely csak dátumkomponenseket tartalmaz, tehát java.time.LocalDate jó jelöltnek tűnik:
public static LocalDate között (LocalDate startInclusive, LocalDate endExclusive) {long startEpochDay = startInclusive.toEpochDay (); long endEpochDay = endExclusive.toEpochDay (); hosszú randomDay = ThreadLocalRandom .current () .nextLong (startEpochDay, endEpochDay); return LocalDate.ofEpochDay (randomDay); }
Itt használjuk a toEpochDay () módszer az egyes konvertálására LocalDate annak megfelelő korszakának napjáig. Hasonlóképpen ellenőrizhetjük, hogy ez a megközelítés helyes-e:
LocalDate start = LocalDate.of (1989, Month.OCTOBER, 14); LocalDate end = LocalDate.now (); LocalDate random = RandomDates.between (kezdet, vég); assertThat (véletlenszerű) .isBetween (kezdet, vég);
3.2. Határtalan
Annak érdekében, hogy véletlen dátumokat generáljunk bármilyen tartománytól függetlenül, egyszerűen generálhatunk egy véletlenszerű korszakot:
public static LocalDate date () {int száz év = 100 * 365; return LocalDate.ofEpochDay (ThreadLocalRandom .current (). nextInt (-száz év, száz év)); }
Véletlen dátumgenerátorunk véletlenszerű napot választ a korszak előtti és utáni 100 év közül. Ismét ennek oka az ésszerű dátumértékek létrehozása:
LocalDate randomDay = RandomDates.date (); assertThat (randomDay) .isBetween (LocalDate.MIN, LocalDate.MAX);
4. Véletlenszerű idő
Hasonlóan ahhoz, amit a dátumokkal tettünk, véletlenszerű időbeli idők generálására is csak időösszetevőket használunk. Ennek érdekében használhatjuk a nap második fogalmát. Vagyis egy véletlenszerű idő megegyezik egy véletlenszerű számmal, amely a nap eleje óta eltelt másodperceket képviseli.
4.1. Megkötve
A java.time.LocalTime osztály egy időbeli absztrakció, amely csak az idő összetevőit foglalja magában:
public static LocalTime között (LocalTime startTime, LocalTime endTime) {int startSeconds = startTime.toSecondOfDay (); int endSeconds = endTime.toSecondOfDay (); int randomTime = ThreadLocalRandom .current () .nextInt (startSeconds, endSeconds); return LocalTime.ofSecondOfDay (randomTime); }
Két másik között véletlenszerű idő előállításához:
- Generáljon véletlenszerű számot a megadott idők napjának második napja között
- Hozzon létre egy véletlenszerű időpontot a véletlenszám felhasználásával
Könnyen ellenőrizhetjük ennek a véletlenszerű időgenerációs algoritmusnak a viselkedését:
LocalTime morning = LocalTime.of (8, 30); LocalTime randomTime = RandomTimes.between (LocalTime.MIDNIGHT, reggel); assertThat (randomTime) .isBetween (LocalTime.MIDNIGHT, reggel) .isBetween (LocalTime.MIN, LocalTime.MAX);
4.2. Határtalan
Még a korlátlan időértékeknek is 00:00:00 és 23:59:59 között kell lenniük, így ezt a logikát egyszerűen meghatalmazással tudjuk végrehajtani:
public static LocalTime time () {return between (LocalTime.MIN, LocalTime.MAX); }
5. Következtetés
Ebben az oktatóanyagban a véletlen dátumok és idők meghatározását véletlenszámokra redukáltuk. Aztán láttuk, hogy ez a redukció hogyan segített nekünk véletlenszerű időbeli értékeket létrehozni, úgy viselkedve, mint az időbélyegek, dátumok vagy idők.
Szokás szerint a mintakód elérhető a GitHubon.