14 KiB
HowTo: Der FHIR date-Suchparameter – Präfixe, Intervalle und Kombinationen richtig verstehen
Wer FHIR-Server baut oder abfragt, stolpert früher oder später über den
date-Suchparameter. Auf den ersten Blick sieht er simpel aus –
?date=2023-06-15 – aber sobald Präfixe wie ge, sa oder ap ins Spiel
kommen und mehrere date-Parameter kombiniert werden, wird es schnell
unübersichtlich. Dieser Artikel bringt Ordnung rein: Schritt für Schritt, mit
Zeitleisten-Grafiken zu jedem Fall — und als Kurzreferenz zum schnellen
Nachschlagen.
Inhaltsverzeichnis
- Kurzreferenz: Alle Präfixe auf einen Blick
- 1. Das Grundprinzip: FHIR vergleicht Intervalle, keine Zeitpunkte
- 2. Die neun Präfixe im Überblick
- 3. Matching gegen
PeriodundRange - 4. Offene (unvollständige) Periods
- 5. Mehrere
date-Parameter kombinieren - 6. Die vollständige 3×3-Matrix aller Bereichs-Kombinationen
- 7. Sonderfälle: redundant oder widersprüchlich
- 8. Praxis-Empfehlungen zum Schluss
Kurzreferenz: Alle Präfixe auf einen Blick
Für den schnellen Blick zwischendurch — Details und Grafiken zu jeder Zeile folgen in den Abschnitten unten.
| Präfix | Name | Kurzregel | Beispiel |
|---|---|---|---|
| (keins) | implizit eq |
Precision des Werts bestimmt das Intervall | date=2023-06-15 |
eq |
gleich | Resource-Intervall vollständig im Such-Intervall | date=eq2023-06-15 |
ne |
ungleich | Komplement von eq |
date=ne2023-06-15 |
gt |
größer als | Ragt über das Ende hinaus (Overlap genügt) | date=gt2023-06-15 |
lt |
kleiner als | Beginnt vor dem Anfang (Overlap genügt) | date=lt2023-06-15 |
ge |
größer/gleich | gt oder vollständig enthalten (eq) |
date=ge2023-06-15 |
le |
kleiner/gleich | lt oder vollständig enthalten (eq) |
date=le2023-06-15 |
sa |
starts after | Vollständig danach, keine Überlappung | date=sa2023-06-15 |
eb |
ends before | Vollständig davor, keine Überlappung | date=eb2023-06-15 |
ap |
approximately | Überlappung + ähnliche Größenordnung | date=ap2023-06-15 |
Fehlender start/end bei Period: fehlender start = -∞, fehlendes
end = +∞ → sa kann bei fehlendem start nie matchen, eb kann bei
fehlendem end nie matchen (Details in Abschnitt 4).
1. Das Grundprinzip: FHIR vergleicht Intervalle, keine Zeitpunkte
Der wichtigste gedankliche Reset zuerst: FHIR behandelt Datumswerte nie als exakten Zeitpunkt, sondern immer als Intervall. Wie breit dieses Intervall ist, hängt von der Precision des angegebenen Werts ab:
2023→ das ganze Jahr 20232023-06→ der ganze Juni 20232023-06-15→ der ganze 15. Juni 2023 (00:00–24:00 Uhr)2023-06-15T10:00:00→ (fast) ein exakter Zeitpunkt
Jeder Vergleichsoperator vergleicht anschließend zwei Intervalle
miteinander: das Such-Intervall aus deinem Query-Parameter und das
Resource-Intervall aus dem Feld der Ressource (z. B. Patient.birthDate oder
Encounter.period).
Ohne Präfix = eq, aber die Precision entscheidet mit
Gibst du kein Präfix an, nimmt der Server eq an. Das Resource-Datum muss
dann vollständig innerhalb deines Such-Intervalls liegen. Je gröber die
Precision, desto breiter das Intervall – und desto mehr Resource-Werte passen
hinein:
date=2023-06-15 matched nur diesen einen Tag. date=2023-06 matched dagegen
jeden Tag im Juni – auch den 15. Das ist der häufigste Stolperstein für
Einsteiger: eine „ungenaue" Suchanfrage ist nicht strenger, sondern lockerer.
2. Die neun Präfixe im Überblick
FHIR definiert insgesamt neun Präfixe für date. Jeder davon beschreibt eine
andere Beziehung zwischen Such-Intervall (rot gestrichelt in der Grafik) und
Treffer-Bereich (grün/farbig schattiert):
| Präfix | Name | Bedeutung |
|---|---|---|
eq |
gleich | Resource-Intervall liegt vollständig im Such-Intervall |
ne |
ungleich | Komplement von eq |
gt |
größer als | Resource-Intervall ragt über das Ende des Such-Intervalls hinaus |
lt |
kleiner als | Resource-Intervall beginnt vor dem Anfang des Such-Intervalls |
ge |
größer/gleich | gt oder vollständig im Such-Intervall enthalten (eq) |
le |
kleiner/gleich | lt oder vollständig im Such-Intervall enthalten (eq) |
sa |
starts after | Beginnt vollständig nach dem Ende des Such-Intervalls, keine Überlappung |
eb |
ends before | Endet vollständig vor dem Beginn des Such-Intervalls, keine Überlappung |
ap |
approximately | Überlappung, plus ähnliche Größenordnung der Intervalle |
Wichtig — Containment vs. Overlap: Nur eq (und implizit sa/eb)
verlangen, dass das Resource-Intervall vollständig innerhalb bzw.
vollständig getrennt vom Such-Intervall liegt. Bei gt, lt, ge
und le reicht dagegen eine Überlappung — das Resource-Intervall muss
nicht komplett außerhalb des Suchbereichs liegen, es genügt, dass es über
die jeweilige Grenze hinausragt. Details dazu im nächsten Abschnitt.
3. Matching gegen Period und Range
Die Grafiken oben zeigen das Resource-Datum als schmalen roten Marker – das
passt für einfache date/dateTime-Felder wie Patient.birthDate. Sobald
das Zielfeld selbst ein Intervall ist (Period, z. B.
Encounter.period, Condition.onsetPeriod, oder Range), wird die
Unterscheidung zwischen Containment (vollständiges Enthaltensein) und
Overlap (bloße Überlappung) entscheidend:
eqverlangt Containment: das gesamte Resource-Intervall muss im Such-Intervall liegen.gt/lt/ge/leverlangen nur Overlap: es reicht, wenn das Resource-Intervall über die jeweilige Grenze hinausragt – auch wenn ein Teil davon auf der "falschen" Seite liegt.sa/ebverlangen das Gegenteil von Overlap: das Resource-Intervall muss vollständig und ohne jede Überlappung auf der jeweiligen Seite liegen.
Bei einem einfachen Zeitpunkt-Feld (kein Period) fällt dieser Unterschied
praktisch nicht auf, da Resource-Start und -Ende (fast) identisch sind — dort
verhalten sich gt und sa de facto gleich. Der Unterschied wird erst bei
echten Zeitspannen relevant. Das ist auch der Grund, warum sa/eb
laut Spezifikation in erster Linie für Period/Range-Werte gedacht sind.
Beispiel: Ein Encounter läuft vom 10. bis 20. Juni. Die Suche
date=gt2023-06-15 soll ihn finden, obwohl der Encounter vor dem 15.
begonnen hat — entscheidend ist nur, dass er über den 15. hinausreicht
(Overlap mit dem Bereich "nach dem 15."). Bei date=sa2023-06-15 würde
derselbe Encounter dagegen nicht matchen, weil er nicht vollständig nach
dem 15. liegt — genau das ist der praktische Unterschied zwischen gt und
sa.
Die folgende Grafik macht das für alle vier "einseitigen" Präfixe (gt,
sa, lt, eb) an denselben drei Beispiel-Periods sichtbar — einer
Period komplett davor, einer, die die Suchgrenze überlappt, und einer
komplett danach:
Man sieht deutlich: gt und lt (blau schattierter Bereich, durchgezogene
Grenzlinie) lassen die überlappende Period B als Treffer durch, während sa
und eb (gestrichelte Grenzlinie) sie ablehnen — nur eine Period, die
komplett auf der richtigen Seite liegt, zählt dort.
| Encounter-Zeitraum | date=gt2023-06-15 |
date=sa2023-06-15 |
|---|---|---|
| 10.–20. Juni (überlappt die Grenze) | ✅ Treffer (Overlap) | ❌ kein Treffer (nicht vollständig danach) |
| 16.–20. Juni (komplett danach) | ✅ Treffer | ✅ Treffer |
| 01.–10. Juni (komplett davor) | ❌ kein Treffer | ❌ kein Treffer |
4. Offene (unvollständige) Periods
In der Praxis sind Periods oft nicht abgeschlossen — z. B. ein laufender
Encounter ohne end, oder ein importierter Datensatz mit unbekanntem
start. Der FHIR-Standard regelt das eindeutig:
Ein fehlender unterer Rand (
start) gilt implizit als kleiner als jedes reale Datum (also-∞). Ein fehlender oberer Rand (end) gilt implizit als größer als jedes reale Datum (also+∞).
Das hat spürbare Konsequenzen, gerade für sa und eb:
- Ein laufender Encounter (
startgesetzt,endfehlt →end = +∞) kann niemalseb(ends before) matchen — sein Ende liegt ja nie vor irgendeinem endlichen Datum. Er matcht aber sehr wohlgt, weil sein (unendliches) Ende immer über jede Suchgrenze hinausragt. - Ein Encounter mit unbekanntem Start (
startfehlt →start = -∞) kann niemalssa(starts after) matchen — sein Beginn liegt ja nie nach irgendeinem endlichen Datum. Er matcht aberlt, weil sein (unendlicher) Anfang immer vor jede Suchgrenze hineinreicht. - Eine Period ganz ohne
startundendüberlappt praktisch jeden overlap-basierten Filter (gt,lt,ge,le) — sie „reicht" ja per Definition über jede Grenze hinaus.
Dieselben vier Präfixe wie in Abschnitt 3, jetzt mit offenen statt geschlossenen Periods:
Praktische Konsequenz: Wenn du „laufende" Ressourcen (z. B. aktive
Encounter, offene Verordnungen) gezielt aus einer Zeitraumsuche ausschließen
willst, reicht eb/sa allein nicht — du musst zusätzlich nach dem Status
oder explizit nach end:missing=true/start:missing=true filtern, je
nachdem, was dein Server unterstützt.
5. Mehrere date-Parameter kombinieren
In der Praxis reicht ein einzelner Präfix selten – meist willst du einen
Bereich definieren. FHIR-Server verknüpfen mehrere date-Parameter in
derselben Query immer per UND. Vier typische Muster:
| Kombination | Beispiel | Charakter |
|---|---|---|
ge + le |
ge2023-01-01&le2023-12-31 |
Geschlossenes Intervall (beide Grenzen inklusive) |
gt + lt |
gt2023-01-01<2023-12-31 |
Offenes Intervall (beide Grenzen exklusive) |
sa + eb |
sa2023-01-01&eb2023-12-31 |
Strikt getrennter Bereich, primär für Period-Werte |
ge + lt |
ge2023-06-01<2023-07-01 |
Halboffenes Intervall [start, ende) – Standardmuster für „genau ein Monat" |
Wenn du in Timestamp-lastigen ETL-Pipelines mit [start, ende) arbeitest,
kommt dir ge + lt bekannt vor – es ist exakt dasselbe Muster wie bei
klassischen Zeitfenster-Queries in SQL.
6. Die vollständige 3×3-Matrix aller Bereichs-Kombinationen
Die vier Muster oben sind nur die gebräuchlichsten. Tatsächlich lässt sich jede Untergrenze mit jeder Obergrenze kombinieren:
- Untergrenzen:
ge,gt,sa - Obergrenzen:
le,lt,eb
Das ergibt 3 × 3 = 9 mögliche Kombinationen, alle spec-konform:
Sie unterscheiden sich nur darin, ob die jeweilige Grenze inklusiv
(durchgezogene Linie) oder exklusiv (gestrichelte Linie) ist, und ob es sich
um einen einfachen Werte-Vergleich (ge/gt/le/lt) oder einen strengen
Period-Vergleich (sa/eb) handelt. Es gibt keine explizite
Ausschluss-Regel im FHIR-Standard – jede Zelle dieser Matrix ist eine
gültige, funktionierende Query.
7. Sonderfälle: Wenn Kombinationen redundant oder widersprüchlich werden
Nicht jede syntaktisch gültige Kombination ist auch praktisch sinnvoll. Drei Kategorien solltest du kennen, bevor du sie versehentlich in einer generierten Query landen lässt:
a) Redundante Kombinationen
Ändern nichts am Ergebnis, sind aber technisch kein Fehler:
eq+ eine Grenze, die vomeq-Intervall ohnehin erfüllt wird (eq2023-06-15&ge2020-01-01) – die Zusatzbedingung ist überflüssig.- Zwei Bedingungen desselben Richtungstyps
(
ge2020-01-01&ge2023-01-01) – nur die strengere (spätere) Untergrenze wirkt effektiv.
b) Kombinationen mit garantiert leerem Ergebnis
Strukturell unmöglich zu erfüllen:
eq+neauf denselben Wert (eq2023-06-15&ne2023-06-15) – sich gegenseitig ausschließende Bedingungen.- Untergrenze liegt zeitlich nach der Obergrenze
(
ge2023-06-01&le2023-01-01) – kein Datum erfüllt beides gleichzeitig.
Der Server wird solche Queries syntaktisch akzeptieren und einfach eine leere Ergebnismenge zurückgeben – kein Fehler, aber auch keine hilfreiche Rückmeldung. Es lohnt sich, so etwas clientseitig vorab zu validieren.
c) Ungewöhnliche, aber gültige Sonderfälle
- Drei oder mehr
date-Parameter, z. B. ein Jahresbereich mit ausgeschlossenem Einzeltag:ge2023-01-01&le2023-12-31&ne2023-06-15. apkombiniert mit einer Grenze, z. B.ap2023-06-15&ge2023-01-01– selten genutzt, daapselbst schon unscharf ist und die Toleranzberechnung serverabhängig bleibt.
8. Praxis-Empfehlungen zum Schluss
- Für einfache Bereichsfilter ist
ge+lt(halboffenes Intervall) meist das robusteste Muster – es vermeidet Rundungsprobleme an der Precision-Grenze (kein Off-by-one bei „bis einschließlich 31.12."). sa/ebbewusst einsetzen, wenn du beiPeriod/Range-Feldern eine vollständige Trennung brauchst (siehe Abschnitt 3) – z. B. „Encounter vollständig nach Entlassung X". Für einen simplen „ab Datum X"-Filter ist meistge/gtgemeint, nichtsa.- Bei
Period-Feldern mit möglichen offenen Enden (siehe Abschnitt 4) nicht vergessen:sa/ebgreifen dort strukturell nie — ggf. zusätzlich:missingoder Status filtern. - Vor dem Absetzen einer Multi-Parameter-Query lohnt sich ein kurzer Check auf logische Konsistenz zwischen Unter- und Obergrenze, um leere Ergebnisse durch Konfigurationsfehler in der eigenen Pipeline zu vermeiden.
Mit der Kurzreferenz oben und den sechs Grafiken im Hinterkopf – ohne Präfix,
alle neun Präfixe einzeln, Containment vs. Overlap bei Period/Range (offen
wie geschlossen), typische Kombinationen, die volle 3×3-Matrix und die
Sonderfälle – sollte die nächste date-Query im FHIR-Suchparameter kein
Rätsel mehr sein.