Skip to content

FHIR Types Utilities

Utility classes and functions for getting and validating FHIR types.

FHIRTypeError

Path: fhircraft.fhir.resources.datatypes.utils.FHIRTypeError

Bases: Exception

Raised when type checking or conversion fails.

is_fhir_complex_type

is_fhir_complex_type(value: Any, fhir_type: type[FHIRBaseModel] | type | TypeAliasType | str, release: str | None = None) -> bool

Check if a value conforms to a complex FHIR type.

Parameters:

Name Type Description Default
value Any

The value to check

required
fhir_type type[FHIRBaseModel] | type | TypeAliasType | str

The complex FHIR type (or name thereof) to check against

required

Returns:

Name Type Description
bool bool

True if the value conforms to the type, False otherwise

Raises:

Type Description
FHIRTypeError

If the fhir_type is a string and does not correspond to a known complex type

Source code in fhircraft/fhir/resources/datatypes/utils.py
def is_fhir_complex_type(
    value: Any,
    fhir_type: "type[FHIRBaseModel] | type | TypeAliasType | str",
    release: str | None = None,
) -> bool:
    """
    Check if a value conforms to a complex FHIR type.

    Args:
        value: The value to check
        fhir_type: The complex FHIR type (or name thereof) to check against

    Returns:
        bool: `True` if the value conforms to the type, `False` otherwise

    Raises:
        FHIRTypeError: If the fhir_type is a string and does not correspond to a known complex type
    """
    if isinstance(fhir_type, str):
        if not release:
            raise FHIRTypeError(
                f"Release must be specified when fhir_type is given as a string: '{fhir_type}'"
            )
        fhir_type = get_fhir_type(fhir_type, release)  # type: ignore

    if isinstance(fhir_type, type) and issubclass(fhir_type, BaseModel):
        if getattr(fhir_type, "_kind", None) != "complex-type":
            return False
        elif isinstance(value, fhir_type):
            return True
        else:
            try:
                fhir_type.model_validate(value)
                return True
            except ValidationError as e:
                return False
    else:
        return False

is_fhir_primitive

is_fhir_primitive(value: Any) -> bool

Check if a value is a FHIR primitive type.

Source code in fhircraft/fhir/resources/datatypes/utils.py
def is_fhir_primitive(value: Any) -> bool:
    """Check if a value is a FHIR primitive type."""
    from fhircraft.fhir.resources.base import FHIRPrimitiveModel

    if isinstance(value, FHIRPrimitiveModel) and value.value is not None:
        return True
    if isinstance(value, (str | int | float | bool | date | datetime | time)):
        return True
    else:
        return False

is_fhir_primitive_type

is_fhir_primitive_type(value: Any, fhir_type: type[FHIRBaseModel] | type | TypeAliasType | str, release: str | None = None) -> bool

Check if a value conforms to a primitive FHIR type.

Parameters:

Name Type Description Default
value Any

The value to check

required
fhir_type type[FHIRBaseModel] | type | TypeAliasType | str

The primitive FHIR type (or name thereof) to check against

required

Returns:

Name Type Description
bool bool

True if the value conforms to the type, False otherwise

Raises:

Type Description
FHIRTypeError

If the fhir_type is a string and does not correspond to a known primitive type

Source code in fhircraft/fhir/resources/datatypes/utils.py
def is_fhir_primitive_type(
    value: Any,
    fhir_type: "type[FHIRBaseModel] | type | TypeAliasType | str",
    release: str | None = None,
) -> bool:
    """
    Check if a value conforms to a primitive FHIR type.

    Args:
        value: The value to check
        fhir_type: The primitive FHIR type (or name thereof) to check against

    Returns:
        bool: `True` if the value conforms to the type, `False` otherwise

    Raises:
        FHIRTypeError: If the fhir_type is a string and does not correspond to a known primitive type
    """
    if isinstance(fhir_type, str):
        if not release:
            raise FHIRTypeError(
                f"Release must be specified when fhir_type is given as a string: '{fhir_type}'"
            )
        fhir_type = get_fhir_type(fhir_type, release)  # type: ignore

    if isinstance(fhir_type, type) and issubclass(fhir_type, BaseModel):
        if getattr(fhir_type, "_kind", None) != "primitive-type":
            return False
        elif isinstance(value, fhir_type):
            return True
        else:
            try:
                fhir_type.model_validate(value)
                return True
            except ValidationError as e:
                return False
    else:
        return False

is_fhir_resource_type

is_fhir_resource_type(value: Any, fhir_type: type[FHIRBaseModel] | type | TypeAliasType | str, release: str | None = None) -> bool

Check if a value conforms to a FHIR resource.

Parameters:

Name Type Description Default
value Any

The value to check

required
fhir_type type[FHIRBaseModel] | type | TypeAliasType | str

The complex FHIR type (or name thereof) to check against

required
raise_on_error

Whether to raise FHIRTypeError on unknown type (default: True)

required

Returns:

Name Type Description
bool bool

True if the value conforms to the type, False otherwise

Raises:

Type Description
FHIRTypeError

If the fhir_type is a string and does not correspond to a known resource type

Source code in fhircraft/fhir/resources/datatypes/utils.py
def is_fhir_resource_type(
    value: Any,
    fhir_type: "type[FHIRBaseModel] | type | TypeAliasType | str",
    release: str | None = None,
) -> bool:
    """
    Check if a value conforms to a FHIR resource.

    Args:
        value: The value to check
        fhir_type: The complex FHIR type (or name thereof) to check against
        raise_on_error: Whether to raise FHIRTypeError on unknown type (default: True)

    Returns:
        bool: `True` if the value conforms to the type, `False` otherwise

    Raises:
        FHIRTypeError: If the fhir_type is a string and does not correspond to a known resource type
    """
    if isinstance(fhir_type, str):
        if not release:
            raise FHIRTypeError(
                f"Release must be specified when fhir_type is given as a string: '{fhir_type}'"
            )
        fhir_type = get_fhir_type(fhir_type, release)  # type: ignore

    if isinstance(fhir_type, type) and issubclass(fhir_type, BaseModel):
        if getattr(fhir_type, "_kind", None) != "resource":
            return False
        elif isinstance(value, fhir_type):
            return True
        else:
            try:
                fhir_type.model_validate(value)
                return True
            except ValidationError as e:
                return False
    else:
        return False

to_boolean

to_boolean(value: Any) -> Union[bool, None]

Convert value to FHIR Boolean.

Parameters:

Name Type Description Default
value Any

Value to convert

required

Returns:

Type Description
Union[bool, None]

bool or None: Converted boolean value or None if conversion fails

Examples:

>>> to_boolean("true")
True
>>> to_boolean("1")
True
>>> to_boolean("invalid")
None
Source code in fhircraft/fhir/resources/datatypes/utils.py
def to_boolean(value: Any) -> Union[bool, None]:
    """
    Convert value to FHIR Boolean.

    Args:
        value: Value to convert

    Returns:
        bool or None: Converted boolean value or None if conversion fails

    Examples:
        >>> to_boolean("true")
        True
        >>> to_boolean("1")
        True
        >>> to_boolean("invalid")
        None
    """
    from fhircraft.fhir.resources.base import FHIRPrimitiveModel

    if isinstance(value, FHIRPrimitiveModel):
        value = value.value
    if isinstance(value, bool):
        return value
    elif isinstance(value, str):
        lower_val = value.lower()
        if lower_val in ["true", "t", "yes", "y", "1", "1.0"]:
            return True
        elif lower_val in ["false", "f", "no", "n", "0", "0.0"]:
            return False
        else:
            return None
    elif isinstance(value, (int, float)):
        return bool(value)
    else:
        return None

to_date

to_date(value: Any) -> Union[str, None]

Convert value to FHIR Date.

Parameters:

Name Type Description Default
value Any

Value to convert

required

Returns:

Type Description
Union[str, None]

str or None: Converted date string or None if conversion fails

Source code in fhircraft/fhir/resources/datatypes/utils.py
def to_date(value: Any) -> Union[str, None]:
    """
    Convert value to FHIR Date.

    Args:
        value: Value to convert

    Returns:
        str or None: Converted date string or None if conversion fails
    """
    from fhircraft.fhir.resources.base import FHIRPrimitiveModel

    if isinstance(value, FHIRPrimitiveModel):
        value = value.value
    if isinstance(value, str):
        # Check if it's already a valid date
        date_pattern = rf"^{constants.YEAR_REGEX}(-{constants.MONTH_REGEX}(-{constants.DAY_REGEX})?)?$"
        if re.match(date_pattern, value):
            return value

        # Check if it's a datetime that we can extract date from
        datetime_pattern = rf"^({constants.YEAR_REGEX}(-{constants.MONTH_REGEX}(-{constants.DAY_REGEX})?)?)(T{constants.HOUR_REGEX}(:{constants.MINUTES_REGEX}(:{constants.SECONDS_REGEX}({constants.TIMEZONE_REGEX})?)?)?)?$"
        datetime_match = re.match(datetime_pattern, value)
        if datetime_match:
            return datetime_match.group(1)  # Extract date part

        return None
    else:
        return None

to_datetime

to_datetime(value: Any) -> Union[str, None]

Convert value to FHIR DateTime.

Parameters:

Name Type Description Default
value Any

Value to convert

required

Returns:

Type Description
Union[str, None]

str or None: Converted datetime string or None if conversion fails

Source code in fhircraft/fhir/resources/datatypes/utils.py
def to_datetime(value: Any) -> Union[str, None]:
    """
    Convert value to FHIR DateTime.

    Args:
        value: Value to convert

    Returns:
        str or None: Converted datetime string or None if conversion fails
    """
    from fhircraft.fhir.resources.base import FHIRPrimitiveModel

    if isinstance(value, FHIRPrimitiveModel):
        value = value.value
    if isinstance(value, str):
        # Check if it's already a valid datetime
        datetime_pattern = rf"^{constants.YEAR_REGEX}(-{constants.MONTH_REGEX}(-{constants.DAY_REGEX})?)?(T{constants.HOUR_REGEX}(:{constants.MINUTES_REGEX}(:{constants.SECONDS_REGEX}({constants.TIMEZONE_REGEX})?)?)?)?$"
        if re.match(datetime_pattern, value):
            return value

        # Check if it's a date that we can convert to datetime
        date_pattern = rf"^{constants.YEAR_REGEX}(-{constants.MONTH_REGEX}(-{constants.DAY_REGEX})?)?$"
        if re.match(date_pattern, value):
            return value  # Date is a valid partial datetime

        return None
    else:
        return None

to_decimal

to_decimal(value: Any) -> Union[float, None]

Convert value to FHIR Decimal.

Parameters:

Name Type Description Default
value Any

Value to convert

required

Returns:

Type Description
Union[float, None]

float or None: Converted decimal value or None if conversion fails

Source code in fhircraft/fhir/resources/datatypes/utils.py
def to_decimal(value: Any) -> Union[float, None]:
    """
    Convert value to FHIR Decimal.

    Args:
        value: Value to convert

    Returns:
        float or None: Converted decimal value or None if conversion fails
    """
    from fhircraft.fhir.resources.base import FHIRPrimitiveModel

    if isinstance(value, FHIRPrimitiveModel):
        value = value.value
    elif isinstance(value, (int, float)):
        return float(value)
    elif isinstance(value, bool):
        return float(value)
    elif isinstance(value, str):
        try:
            # Check if it matches decimal pattern
            if re.match(r"^[+-]?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?$", value.strip()):
                return float(value)
            else:
                return None
        except ValueError:
            return None
    else:
        return None

to_integer

to_integer(value: Any) -> Union[int, None]

Convert value to FHIR Integer.

Parameters:

Name Type Description Default
value Any

Value to convert

required

Returns:

Type Description
Union[int, None]

int or None: Converted integer value or None if conversion fails

Source code in fhircraft/fhir/resources/datatypes/utils.py
def to_integer(value: Any) -> Union[int, None]:
    """
    Convert value to FHIR Integer.

    Args:
        value: Value to convert

    Returns:
        int or None: Converted integer value or None if conversion fails
    """
    from fhircraft.fhir.resources.base import FHIRPrimitiveModel

    if isinstance(value, FHIRPrimitiveModel):
        value = value.value
    if isinstance(value, int):
        return value
    elif isinstance(value, bool):
        return int(value)
    elif isinstance(value, str):
        if re.match(r"^[+-]?\d+$", value.strip()):
            try:
                return int(value)
            except ValueError:
                return None
        else:
            return None
    else:
        return None

to_string

to_string(value: Any) -> Union[str, None]

Convert value to string representation.

Parameters:

Name Type Description Default
value Any

Value to convert

required

Returns:

Type Description
Union[str, None]

str or None: String representation or None if conversion fails

Source code in fhircraft/fhir/resources/datatypes/utils.py
def to_string(value: Any) -> Union[str, None]:
    """
    Convert value to string representation.

    Args:
        value: Value to convert

    Returns:
        str or None: String representation or None if conversion fails
    """
    from fhircraft.fhir.resources.base import FHIRPrimitiveModel

    if isinstance(value, FHIRPrimitiveModel):
        value = value.value
    if isinstance(value, str):
        return value
    elif isinstance(value, (int, float, bool)):
        return str(value)
    elif hasattr(value, "__str__"):
        try:
            return str(value)
        except Exception:
            return None
    else:
        return None

to_time

to_time(value: Any) -> Union[str, None]

Convert value to FHIR Time.

Parameters:

Name Type Description Default
value Any

Value to convert

required

Returns:

Type Description
Union[str, None]

str or None: Converted time string or None if conversion fails

Source code in fhircraft/fhir/resources/datatypes/utils.py
def to_time(value: Any) -> Union[str, None]:
    """
    Convert value to FHIR Time.

    Args:
        value: Value to convert

    Returns:
        str or None: Converted time string or None if conversion fails
    """
    from fhircraft.fhir.resources.base import FHIRPrimitiveModel

    if isinstance(value, FHIRPrimitiveModel):
        value = value.value
    if isinstance(value, str):
        # Check if it's already a valid time
        time_pattern = rf"^{constants.HOUR_REGEX}(:{constants.MINUTES_REGEX}(:{constants.SECONDS_REGEX}({constants.TIMEZONE_REGEX})?)?)?$"
        if re.match(time_pattern, value):
            return value

        # Check if it's a datetime/date that contains time info we can extract
        datetime_pattern = rf"^({constants.YEAR_REGEX}(-{constants.MONTH_REGEX}(-{constants.DAY_REGEX})?)?)(T({constants.HOUR_REGEX}(:{constants.MINUTES_REGEX}(:{constants.SECONDS_REGEX}({constants.TIMEZONE_REGEX})?)?)?))$"
        datetime_match = re.match(datetime_pattern, value)
        if datetime_match:
            return datetime_match.group(4)  # Extract time part

        return None
    else:
        return None