Skip to main content
Documentation Status https://img.shields.io/pypi/v/fhirdatetime.svg https://github.com/mmabey/fhirdatetime/actions/workflows/ci.yml/badge.svg?branch=main https://coveralls.io/repos/github/mmabey/fhirdatetime/badge.svg?branch=main https://img.shields.io/badge/code%20style-ruff-000000.svg

date/datetime-compatible classes for FHIR date/datetime values.

The FHIR specification from HL7 is “a standard for health care data exchange.” The FHIR spec includes date and datetime data types that provide more flexibility than the standard Python date and datetime types. This makes sense when you consider a patient may report to their provider that they have experience a particular symptom since a particular year without knowing the month or day of onset.

This library provides two classes: FhirDate, for FHIR’s date type (year, year-month, or year-month-day precision), and FhirDateTime, for FHIR’s dateTime type (everything FhirDate supports, plus an optional time-of-day and timezone). FhirDateTime is a FhirDate (it subclasses it), so anywhere a FhirDate is expected – comparisons, sorting, type checks – a FhirDateTime works too.

FHIR version compatibility

The date and dateTime primitive definitions are equivalent across FHIR R4, R5, and the R6 ballot – same fields, same precision model, same normative rules – and this library targets all three.

R5’s published regex is looser than its own prose in two places (the prose governs, and the R6 ballot tightened the regex back), and fhirdatetime follows the prose:

  • A dateTime with a time but no timezone offset ("2021-03-15T10:30:00") is rejected with NaiveTimeError – FHIR says “if hours and minutes are specified, a timezone offset SHALL be populated.” Catch NaiveTimeError (a ValueError subclass) to single these out, or attach an offset before parsing.

  • A timezone offset on a value with no time ("2021-03-15+05:00") is rejected – it is not representable, and effectively nothing produces it.

Fractional seconds beyond microsecond precision (R5/R6 allow up to nanoseconds) are truncated on parse, since Python’s datetime stores only microseconds. FHIR instant values map onto FhirDateTime and round-trip fine, though instant’s stricter rules (seconds and offset both mandatory) are not separately enforced.

Installation

Install fhirdatetime using pip:

pip install fhirdatetime

Usage

Creation

Both classes are designed to be used to store date/datetime values from FHIR payloads (which are JSON strings), so you can create instances from str values:

>>> FhirDate("2021-03-15")
fhirdatetime.FhirDate(2021, 3, 15)
>>> FhirDateTime("2021-03-15T20:54:00+00:00")
fhirdatetime.FhirDateTime(2021, 3, 15, 20, 54, tzinfo=datetime.timezone.utc)

You can also convert native date and datetime objects directly:

>>> FhirDate(date(2021, 3, 15))
fhirdatetime.FhirDate(2021, 3, 15)
>>> FhirDateTime(datetime(2021, 3, 15, 20, 54, tzinfo=timezone.utc))
fhirdatetime.FhirDateTime(2021, 3, 15, 20, 54, tzinfo=datetime.timezone.utc)

Note that FhirDateTime requires a timezone whenever a time is given, per the FHIR dateTime spec – there’s no such thing as an hour/minute with no offset in FHIR. Values with no time at all (like the FhirDate examples above, or a date-only FhirDateTime("2021-03-15")) never need one.

One purpose of this library is to allow flexibility in granularity without sacrificing the ability to compare (using <, >, ==, etc.) against objects of the same type as well as native date and datetime objects.

Comparison

When comparing objects, only the values that are populated for both objects are considered. Consider the following examples in which only the years are compared:

>>> FhirDateTime(2021) == FhirDateTime(2021, 3, 15)
True
>>> FhirDateTime(2021) == datetime(2021, 3, 15, 23, 56)
True
>>> FhirDateTime(2021) == date(2021, 3, 15)
True
>>> FhirDateTime(2021) < FhirDateTime(2021, 3, 15)
False
>>> FhirDateTime(2021) > FhirDateTime(2021, 3, 15)
False

Since FhirDateTime is a FhirDate, the two compare against each other the same way:

>>> FhirDateTime(2021, 3, 15) == FhirDate(2021, 3, 15)
True

Sorting

Both classes have a sort_key() class method for sorting a sequence of FhirDate/FhirDateTime objects – or objects that contain one – including handling the ambiguity that comes with mixed-granularity values:

>>> sorted(
...     [FhirDateTime(2021, 4), FhirDateTime(2021), FhirDateTime(2021, 4, 12)],
...     key=FhirDateTime.sort_key()
... )
[fhirdatetime.FhirDateTime(2021), fhirdatetime.FhirDateTime(2021, 4), fhirdatetime.FhirDateTime(2021, 4, 12)]

See the full Sorting guide in the docs for sorting by an attribute path (e.g. sorting FHIR resources by period.start) and the exact ordering rules for ambiguous comparisons.

License

This project is licensed under the MIT license.

Metadata

Release files for fhirdatetime 1.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for fhirdatetime 1.1.0
File Size Uploaded
fhirdatetime-1.1.0.tar.gz 29.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for fhirdatetime 1.1.0
File Interpreter ABI Platform
fhirdatetime-1.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 61.9 kB

Release files / fhirdatetime-1.1.0.tar.gz

Download URL fhirdatetime-1.1.0.tar.gz
Size 29.8 kB
Tags Source
SHA-256 checksum
How to use checksums
7f377994186738339ed3d5a4ebacb8bf1a4dfb3832d550c1ca6f235f43bc7a8e
BLAKE2b-256 checksum
How to use checksums
f40e566a55e5344dca6a6ab9a066b851cfaa5437d9c04a3aadb58aa1b53547e2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 6, 2026.

Transparency log

Release files / fhirdatetime-1.1.0-py3-none-any.whl

Download URL fhirdatetime-1.1.0-py3-none-any.whl
Size 32.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9bc68159d2bc341c048933067a475c098dcfed1bf8ed3e6d4e10fbaa19778188
BLAKE2b-256 checksum
How to use checksums
99e092ff923a334eadcfb8295771598d1391c6a78118758e4703295618546706
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 6, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.1.0 This release

2 release files

1.0.0

2 release files

0.2.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page