Zum Inhalt

DateTimeGenerator (EE)

Erzeugt Datum‑Zeit‑Werte für Keys und Variablen: feste oder zufällige Werte, strikte Min/Max‑Grenzen, optionale Gewichtungen, komfortable „Sugar“-Filter, deterministische Seeds sowie Epoch‑Konvertierungen. Dieses Dokument beschreibt Funktionsumfang, API und Nutzung (EE).

Modi

  • Fester Wert: value='<date string>', geparst mit input_format.
  • Zufallsfenster: random=True (oder random_mode=True) optional mit min/max.
  • Aktuelle Zeit: beides weglassen → aktuelle Systemzeit.

Standard ohne Grenzwerte: start=1970-01-01 00:00:00, end=2020-01-01 00:00:00 (50 Jahre).

Kernparameter

  • min / max (str): optionale Grenzen, geparst via input_format (Standard %Y-%m-%d %H:%M:%S).
  • value (str): fester Zeitpunkt per input_format.
  • random / random_mode (bool): Zufallsmodus aktivieren.
  • input_format (str): Parse‑Format für min, max, value.
  • seed (int): deterministischer RNG‑Seed; gleicher Seed + gleiche Parameter ⇒ gleiche Folge.

Grenzen gelten sekundengenau. Fällt der gezogene Tag auf min/max, werden Stunde/Minute/Sekunde in den zulässigen Teilbereich geklemmt.

Zeitgewichtungen (innerhalb eines Tages)

  • hour_weights (Liste[24] von float)
  • minute_weights (Liste[60] von float)
  • second_weights (Liste[60] von float)

Regeln: - Länge muss passen (24/60/60). Werte ≥ 0 und Summe > 0 (falls gesetzt). - Wenn weggelassen und keine Tagesgewichtung aktiv ist, ist die Verteilung innerhalb des Tages uniform.

Tagesauswahl‑Gewichtungen (zwischen Tagen)

  • month_weights (Liste[12] von float)
  • weekday_weights (Liste[7] von float) – Montag=0, Sonntag=6
  • dom_weights (Liste[31] von float) – Tag‑im‑Monat 1..31

Ablauf: - Alle zulässigen Tage im Fenster [min, max] werden vorab ermittelt. - Tagesgewicht = month_weight × weekday_weight × dom_weight. - Zuerst Monat proportional zu seiner Tagessumme ziehen, dann Tag anhand der Taggewichte des Monats.

Validierung: - Korrekte Längen, keine negativen Zahlen, Gesamtgewicht > 0. - Kein zulässiger Tag ⇒ ValueError.

Sugar (komfortable Kurzschreibweise)

Gilt nur, wenn für die Dimension keine expliziten Gewichte angegeben sind.

  • months / months_exclude: Monatsfilter.
  • Beispiele: months='3,7-9', months_exclude='2,4'.
  • Quartale: months='Q1' (Jan–Mrz), months='Q2,Q4' (Apr–Jun, Okt–Dez).
  • weekdays: Namen, Bereiche, Presets (Mo=0, So=6).
  • Namen/Bereiche: weekdays='Mon-Fri', weekdays='Fri-Mon' (mit Umbruch).
  • Presets: weekdays='Weekend', weekdays='Weekdays'/Business/Workdays, weekdays='All'.
  • dom: Filter Tag‑im‑Monat.
  • Beispiele: dom='1-5,15,31', dom='last' (letzter Tag eines Monats).
  • hours_preset: office (09–17 hoch), night (22–05 hoch), flat (keine Bevorzugung).
  • minute_granularity / second_granularity (int): nur Ticks nutzen, die durch die Granularität teilbar sind (z. B. 15 → 0,15,30,45).

Priorität: explizite Gewichte (*_weights) überschreiben Sugar derselben Dimension.

Epoch‑Support

Zwei Wege, mit Epoch zu arbeiten:

1) Über Key‑Formate (empfohlen in XML): - inDateFormat="epoch" wandelt konstante Epoch (Sek./ms/µs/ns) in datetime. - outDateFormat="epoch|epoch_millis|epoch_micros|epoch_nanos|%Nf" wandelt datetime ins gewünschte Ziel.

2) Über Python‑API (Generator‑Optionen): - as_epoch=True mit epoch_unit='seconds'|'milliseconds' liefert Integer‑Epoch aus .generate(); .generate_date() gibt Datum auf Basis der Epoch zurück.

Determinismus & Performance

  • Deterministische Ziehungen über privaten RNG mit seed.
  • Fast‑Path (Rust), wenn kein seed und keine Gewichte/Sugar gesetzt sind. Für Durchsatz wird ein kleiner Puffer vorab gefüllt.
  • Runtime‑Flags: rust_fast_generators (Standard true), rust_fast_buffer_size (Standard 8192).
  • Gewichtete/Sugar/Determinismus‑Fälle laufen in Python mit O(1) pro Sample nach einmaligem Aufbau der Tagesverteilung.

Fehlerbehandlung

  • Ungültige Längen, negative Werte oder Gesamtgewicht 0 ⇒ ValueError.
  • Sugar ergibt im Fenster keine zulässigen Tage ⇒ ValueError.
  • Ungültige Granularität (≤0 oder >60) ⇒ ValueError.
  • Unbekanntes hours_presetValueError.

XML‑Beispiele

Formatierung und Epoch‑Konvertierung:

1
2
3
4
5
6
7
8
<generate name="InOutDatetimeFormat" count="10">
  <key name="datetime_with_in" constant="2021-02-01 12:08:04.376188" inDateFormat="%Y-%m-%d %H:%M:%S.%f"/>
  <key name="datetime_with_out" generator="DateTimeGenerator" outDateFormat="%d.%m.%Y %H:%M:%S.%f"/>
  <key name="date_with_in_out" constant="2022-02-01" inDateFormat="%Y-%m-%d" outDateFormat="%d.%m.%Y"/>
  <key name="day_out" generator="DateTimeGenerator" outDateFormat="%d"/>
  <key name="epoch_in_seconds" constant="1692967891" inDateFormat="epoch" outDateFormat="%Y-%m-%d %H:%M:%S"/>
  <key name="to_epoch" generator="DateTimeGenerator" outDateFormat="epoch"/>
  <key name="to_epoch_millis" generator="DateTimeGenerator" outDateFormat="epoch_millis"/>

Uniformes Zeitfenster:

1
2
3
4
5
<setup>
  <generate name="uniform" count="3">
    <key name="dt" generator="DateTimeGenerator(min='2024-01-01 00:00:00', max='2024-12-31 23:59:59', random=True)"/>
  </generate>
</setup>

Sugar & Granularität:

1
2
3
<key name="office_15_10"
     generator="DateTimeGenerator(min='2024-04-01 00:00:00', max='2024-04-30 23:59:59', random=True,
                                   hours_preset='office', minute_granularity=15, second_granularity=10, seed=7)"/>

Gewichtete Monats/Wochentag/DOM‑Auswahl:

1
2
3
4
5
<key name="march_mondays_dom4"
     generator="DateTimeGenerator(min='2024-01-01 00:00:00', max='2024-12-31 23:59:59', random=True,
                                   month_weights='[0,0,1]+[0]*9',
                                   weekday_weights='[1,0,0,0,0,0,0]',
                                   dom_weights='[0,0,0,1]+[0]*27', seed=7)"/>

Filter‑Sugar:

1
2
3
<key name="biz_days" generator="DateTimeGenerator(min='2024-04-01 00:00:00', max='2024-04-30 23:59:59', random=True, weekdays='Mon-Fri')"/>
<key name="q1_only"  generator="DateTimeGenerator(min='2024-01-01 00:00:00', max='2024-12-31 23:59:59', random=True, months='Q1')"/>
<key name="dom_last" generator="DateTimeGenerator(min='2024-01-01 00:00:00', max='2024-12-31 23:59:59', random=True, dom='last')"/>

Bias innerhalb des Tages + Abtastung Minuten/Sekunden:

1
2
3
4
5
6
7
8
<key name="biased"
     generator="DateTimeGenerator(
       min='2020-02-01 0:0:0', max='2025-07-31 0:0:0',
       month_weights='[0.5] * 2 + [1] * 3 + [0.8] * 3 + [1] * 3 + [0.5]',
       hour_weights='[0.6]*6 + [0.3]*16 + [0.1]*2',
       minute_weights='[1 if m in (0,15,30,45) else 0 for m in range(60)]',
       second_weights='[1]+[0]*59', seed=123
     )"/>

Hinweise zu Listen‑Ausdrücken in XML: - Wegen XML‑Parsing Ausdrücke mit Kommata als String übergeben (quoten). - Einfache Muster wie [0]*12 funktionieren auch unquoted; List‑Comprehensions stets quoten (siehe oben).

Python‑API‑Beispiele

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
from datamimic_ee.domains.common.literal_generators.datetime_generator import DateTimeGenerator

# Deterministische Wochenenden im Januar 2024
gen = DateTimeGenerator(
    min='2024-01-01 00:00:00', max='2024-01-31 23:59:59', random=True,
    weekdays='Weekend', seed=42,
)
print(gen.generate())

# Nur Zeitgewichtungen (Tage uniform)
gen = DateTimeGenerator(random=True, hour_weights=[0.2]*6 + [0.02]*18, seed=1)
print(gen.generate())

# Epoch über Python‑API
gen = DateTimeGenerator(random=True, as_epoch=True, epoch_unit='milliseconds')
print(gen.generate())  # -> int millis

Edge Cases & Tipps

  • Schaltjahre: DOM‑Gewichte und dom='last' berücksichtigen den 29. Februar korrekt.
  • Wochenumbruch: Bereiche wie Fri-Mon laufen über Wochenränder korrekt.
  • Grenzen + Granularität: Auch bei starker Ausdünnung bleibt die Zeit innerhalb des min/max‑Fensters des gewählten Tages.
  • Priorität: Explizite Gewichte > Sugar. Kombinationen (Monat/Wochentag/DOM) so wählen, dass noch Tage übrig bleiben.
  • random_mode ist Alias von random (Kompatibilität).