dicom_core::value::range

Trait AsRange

Source
pub trait AsRange {
    type PreciseValue: PartialEq + PartialOrd;
    type Range;

    // Required methods
    fn is_precise(&self) -> bool;
    fn earliest(&self) -> Result<Self::PreciseValue, Error>;
    fn latest(&self) -> Result<Self::PreciseValue, Error>;
    fn range(&self) -> Result<Self::Range, Error>;

    // Provided method
    fn exact(&self) -> Result<Self::PreciseValue, Error> { ... }
}
Expand description

The DICOM protocol accepts date (DA) / time (TM) / date-time (DT) values with null components.

Imprecise values are to be handled as ranges.

This trait is implemented by date / time structures with partial precision.

AsRange::is_precise() method will check if the given value has full precision. If so, it can be converted with AsRange::exact() to a precise value. If not, AsRange::range() will yield a date / time / date-time range.

Please note that precision does not equal validity. A precise ‘YYYYMMDD’ DicomDate can still fail to produce a valid chrono::NaiveDate

§Examples

use chrono::{NaiveDate, NaiveTime};
use dicom_core::value::{AsRange, DicomDate, DicomTime, DateRange, TimeRange};

let dicom_date = DicomDate::from_ym(2010,1)?;
assert_eq!(dicom_date.is_precise(), false);
assert_eq!(
    Some(dicom_date.earliest()?),
    NaiveDate::from_ymd_opt(2010,1,1)
);
assert_eq!(
    Some(dicom_date.latest()?),
    NaiveDate::from_ymd_opt(2010,1,31)
);

let dicom_time = DicomTime::from_hm(10,0)?;
assert_eq!(
    dicom_time.range()?,
    TimeRange::from_start_to_end(NaiveTime::from_hms(10, 0, 0),
        NaiveTime::from_hms_micro_opt(10, 0, 59, 999_999).unwrap())?
);
// only a time with 6 digits second fraction is considered precise
assert!(dicom_time.exact().is_err());

let primitive = PrimitiveValue::from("199402");

// This is the fastest way to get to a useful date value, but it fails not only for invalid
// dates but for imprecise ones as well.
assert!(primitive.to_naive_date().is_err());

// Take intermediate steps:

// Retrieve a DicomDate.
// The parser now checks for basic year and month value ranges here.
// But, it would not detect invalid dates like 30th of february etc.
let dicom_date : DicomDate = primitive.to_date()?;

// as we have a valid DicomDate value, let's check if it's precise.
if dicom_date.is_precise(){
        // no components are missing, we can proceed by calling .exact()
        // which calls the `chrono` library
        let precise_date: NaiveDate = dicom_date.exact()?;
}
else{
        // day / month are missing, no need to call the expensive .exact() method - it will fail
        // retrieve the earliest possible value directly from DicomDate
        let earliest: NaiveDate = dicom_date.earliest()?;

        // or convert the date to a date range instead
        let date_range: DateRange = dicom_date.range()?;

        if let Some(start)  = date_range.start(){
            // the range has a given lower date bound
        }

}

Required Associated Types§

Required Methods§

Source

fn is_precise(&self) -> bool

returns true if value has all possible date / time components

Source

fn earliest(&self) -> Result<Self::PreciseValue, Error>

Returns the earliest possible value from a partial precision structure. Missing components default to 1 (days, months) or 0 (hours, minutes, …) If structure contains invalid combination of DateComponents, it fails.

Source

fn latest(&self) -> Result<Self::PreciseValue, Error>

Returns the latest possible value from a partial precision structure. If structure contains invalid combination of DateComponents, it fails.

Source

fn range(&self) -> Result<Self::Range, Error>

Returns a tuple of the earliest and latest possible value from a partial precision structure.

Provided Methods§

Source

fn exact(&self) -> Result<Self::PreciseValue, Error>

Returns a corresponding precise value, if the partial precision structure has full accuracy.

Implementors§