# QiCore Common - CMS FHIR Prototype Measure Calculation Tool IG v0.1.0

* [**Table of Contents**](toc.md)
* [**Artifacts Summary**](artifacts.md)
* **QiCore Common**

## Library: QiCore Common 

| | |
| :--- | :--- |
| *Official URL*:http://cms.gov/fhir/mct/Library/QICoreCommon | *Version*:0.1.0 |
| Draft as of 2026-02-27 | *Computable Name*:QICoreCommon |

* * **Content: **text/cql: ````/* @author: Stan Rankins @description: Common terminologies and functions used in QI-Core-based CQL artifacts @update: Fashioned after FHIRCommon Version 4.0.012 for use in ecqm-content-qicore-2022 repos */ library QICoreCommon version '1.0.000' using QICore version '4.1.1' include FHIRHelpers version '4.0.013' codesystem &quot;LOINC&quot;: 'http://loinc.org' codesystem &quot;SNOMEDCT&quot;: 'http://snomed.info/sct' codesystem &quot;ICD10CM&quot;: 'http://hl7.org/fhir/sid/icd-10-cm' codesystem &quot;RoleCode&quot;: 'http://terminology.hl7.org/CodeSystem/v3-RoleCode' codesystem &quot;Diagnosis Role&quot;: 'http://terminology.hl7.org/CodeSystem/diagnosis-role' codesystem &quot;RequestIntent&quot;: 'http://terminology.hl7.org/CodeSystem/request-intent' codesystem &quot;MedicationRequestCategory&quot;: 'http://terminology.hl7.org/CodeSystem/medicationrequest-category' codesystem &quot;ConditionClinicalStatusCodes&quot;: 'http://terminology.hl7.org/CodeSystem/condition-clinical' codesystem &quot;ConditionVerificationStatusCodes&quot;: 'http://terminology.hl7.org/CodeSystem/condition-ver-status' codesystem &quot;AllergyIntoleranceClinicalStatusCodes&quot;: 'http://terminology.hl7.org/CodeSystem/allergyintolerance-clinical' codesystem &quot;AllergyIntoleranceVerificationStatusCodes&quot;: 'http://terminology.hl7.org/CodeSystem/allergyintolerance-verification' codesystem &quot;ConditionCategoryCodes&quot;: 'http://terminology.hl7.org/CodeSystem/condition-category' codesystem &quot;ObservationCategoryCodes&quot;: 'http://terminology.hl7.org/CodeSystem/observation-category' valueset &quot;Active Condition&quot;: 'http://fhir.org/guides/cqf/common/ValueSet/active-condition' valueset &quot;Inactive Condition&quot;: 'http://fhir.org/guides/cqf/common/ValueSet/inactive-condition' code &quot;Birthdate&quot;: '21112-8' from &quot;LOINC&quot; display 'Birth date' code &quot;Dead&quot;: '419099009' from &quot;SNOMEDCT&quot; display 'Dead' code &quot;ER&quot;: 'ER' from &quot;RoleCode&quot; display 'Emergency room' code &quot;ICU&quot;: 'ICU' from &quot;RoleCode&quot; display 'Intensive care unit' code &quot;Billing&quot;: 'billing' from &quot;Diagnosis Role&quot; display 'Billing' // Condition Clinical Status Codes - Consider value sets for these code &quot;active&quot;: 'active' from &quot;ConditionClinicalStatusCodes&quot; code &quot;recurrence&quot;: 'recurrence' from &quot;ConditionClinicalStatusCodes&quot; code &quot;relapse&quot;: 'relapse' from &quot;ConditionClinicalStatusCodes&quot; code &quot;inactive&quot;: 'inactive' from &quot;ConditionClinicalStatusCodes&quot; code &quot;remission&quot;: 'remission' from &quot;ConditionClinicalStatusCodes&quot; code &quot;resolved&quot;: 'resolved' from &quot;ConditionClinicalStatusCodes&quot; // Condition Verification Status Codes - Consider value sets for these code &quot;unconfirmed&quot;: 'unconfirmed' from ConditionVerificationStatusCodes code &quot;provisional&quot;: 'provisional' from ConditionVerificationStatusCodes code &quot;differential&quot;: 'differential' from ConditionVerificationStatusCodes code &quot;confirmed&quot;: 'confirmed' from ConditionVerificationStatusCodes code &quot;refuted&quot;: 'refuted' from ConditionVerificationStatusCodes code &quot;entered-in-error&quot;: 'entered-in-error' from ConditionVerificationStatusCodes code &quot;allergy-active&quot;: 'active' from &quot;AllergyIntoleranceClinicalStatusCodes&quot; code &quot;allergy-inactive&quot;: 'inactive' from &quot;AllergyIntoleranceClinicalStatusCodes&quot; code &quot;allergy-resolved&quot;: 'resolved' from &quot;AllergyIntoleranceClinicalStatusCodes&quot; // Allergy/Intolerance Verification Status Codes - Consider value sets for these code &quot;allergy-unconfirmed&quot;: 'unconfirmed' from AllergyIntoleranceVerificationStatusCodes code &quot;allergy-confirmed&quot;: 'confirmed' from AllergyIntoleranceVerificationStatusCodes code &quot;allergy-refuted&quot;: 'refuted' from AllergyIntoleranceVerificationStatusCodes // MedicationRequest Category Codes code &quot;Community&quot;: 'community' from &quot;MedicationRequestCategory&quot; display 'Community' code &quot;Discharge&quot;: 'discharge' from &quot;MedicationRequestCategory&quot; display 'Discharge' // Diagnosis Role Codes code &quot;AD&quot;: 'AD' from &quot;Diagnosis Role&quot; display 'Admission diagnosis' code &quot;DD&quot;: 'DD' from &quot;Diagnosis Role&quot; display 'Discharge diagnosis' code &quot;CC&quot;: 'CC' from &quot;Diagnosis Role&quot; display 'Chief complaint' code &quot;CM&quot;: 'CM' from &quot;Diagnosis Role&quot; display 'Comorbidity diagnosis' code &quot;pre-op&quot;: 'pre-op' from &quot;Diagnosis Role&quot; display 'pre-op diagnosis' code &quot;post-op&quot;: 'post-op' from &quot;Diagnosis Role&quot; display 'post-op diagnosis' code &quot;billing&quot;: 'billing' from &quot;Diagnosis Role&quot; display 'billing diagnosis' // Observation Category Codes code &quot;social-history&quot;: 'social-history' from &quot;ObservationCategoryCodes&quot; display 'Social History' code &quot;vital-signs&quot;: 'vital-signs' from &quot;ObservationCategoryCodes&quot; display 'Vital Signs' code &quot;imaging&quot;: 'imaging' from &quot;ObservationCategoryCodes&quot; display 'Imaging' code &quot;laboratory&quot;: 'laboratory' from &quot;ObservationCategoryCodes&quot; display 'Laboratory' code &quot;procedure&quot;: 'procedure' from &quot;ObservationCategoryCodes&quot; display 'Procedure' code &quot;survey&quot;: 'survey' from &quot;ObservationCategoryCodes&quot; display 'Survey' code &quot;exam&quot;: 'exam' from &quot;ObservationCategoryCodes&quot; display 'Exam' code &quot;therapy&quot;: 'therapy' from &quot;ObservationCategoryCodes&quot; display 'Therapy' code &quot;activity&quot;: 'activity' from &quot;ObservationCategoryCodes&quot; display 'Activity' // Condition Category Codes code &quot;problem-list-item&quot;: 'problem-list-item' from &quot;ConditionCategoryCodes&quot; display 'Problem List Item' code &quot;encounter-diagnosis&quot;: 'encounter-diagnosis' from &quot;ConditionCategoryCodes&quot; display 'Encounter Diagnosis' context Patient /* @description: Normalizes a value that is a choice of timing-valued types to an equivalent interval @comment: Normalizes a choice type of DateTime, Quanitty, Interval&lt;DateTime&gt;, or Interval&lt;Quantity&gt; types to an equivalent interval. This selection of choice types is a superset of the majority of choice types that are used as possible representations for timing-valued elements in QICore, allowing this function to be used across any resource. The input can be provided as a DateTime, Quantity, Interval&lt;DateTime&gt; or Interval&lt;Quantity&gt;. The intent of this function is to provide a clear and concise mechanism to treat single elements that have multiple possible representations as intervals so that logic doesn't have to account for the variability. More complex calculations (such as medication request period or dispense period calculation) need specific guidance and consideration. That guidance may make use of this function, but the focus of this function is on single element calculations where the semantics are unambiguous. If the input is a DateTime, the result a DateTime Interval beginning and ending on that DateTime. If the input is a Quantity, the quantity is expected to be a calendar-duration interpreted as an Age, and the result is a DateTime Interval beginning on the Date the patient turned that age and ending immediately before one year later. If the input is a DateTime Interval, the result is the input. If the input is a Quantity Interval, the quantities are expected to be calendar-durations interpreted as an Age, and the result is a DateTime Interval beginning on the date the patient turned the age given as the start of the quantity interval, and ending immediately before one year later than the date the patient turned the age given as the end of the quantity interval. Any other input will reslt in a null DateTime Interval */ define function ToInterval(choice Choice&lt;DateTime, Quantity, Interval&lt;DateTime&gt;, Interval&lt;Quantity&gt;&gt;): case when choice is DateTime then Interval[choice as DateTime, choice as DateTime] when choice is Interval&lt;DateTime&gt; then choice as Interval&lt;DateTime&gt; when choice is Quantity then Interval[Patient.birthDate + (choice as Quantity), Patient.birthDate + (choice as Quantity) + 1 year) when choice is Interval&lt;Quantity&gt; then Interval[Patient.birthDate + (choice.low as Quantity), Patient.birthDate + (choice.high as Quantity) + 1 year) else null as Interval&lt;DateTime&gt; end /* @description: Normalizes a value that is a choice of timing-valued types to an equivalent interval @comment: Normalizes a choice type of DateTime, Quanitty, Interval&lt;DateTime&gt;, or Interval&lt;Quantity&gt; types to an equivalent interval. This selection of choice types is a superset of the majority of choice types that are used as possible representations for timing-valued elements in QICore, allowing this function to be used across any resource. The input can be provided as a DateTime, Quantity, Interval&lt;DateTime&gt; or Interval&lt;Quantity&gt;. The intent of this function is to provide a clear and concise mechanism to treat single elements that have multiple possible representations as intervals so that logic doesn't have to account for the variability. More complex calculations (such as medication request period or dispense period calculation) need specific guidance and consideration. That guidance may make use of this function, but the focus of this function is on single element calculations where the semantics are unambiguous. If the input is a DateTime, the result a DateTime Interval beginning and ending on that DateTime. If the input is a Quantity, the quantity is expected to be a calendar-duration interpreted as an Age, and the result is a DateTime Interval beginning on the Date the patient turned that age and ending immediately before one year later. If the input is a DateTime Interval, the result is the input. If the input is a Quantity Interval, the quantities are expected to be calendar-durations interpreted as an Age, and the result is a DateTime Interval beginning on the date the patient turned the age given as the start of the quantity interval, and ending immediately before one year later than the date the patient turned the age given as the end of the quantity interval. Any other input will reslt in a null DateTime Interval */ define fluent function toInterval(choice Choice&lt;DateTime, Quantity, Interval&lt;DateTime&gt;, Interval&lt;Quantity&gt;&gt;): case when choice is DateTime then Interval[choice as DateTime, choice as DateTime] when choice is Interval&lt;DateTime&gt; then choice as Interval&lt;DateTime&gt; when choice is Quantity then Interval[Patient.birthDate + (choice as Quantity), Patient.birthDate + (choice as Quantity) + 1 year) when choice is Interval&lt;Quantity&gt; then Interval[Patient.birthDate + (choice.low as Quantity), Patient.birthDate + (choice.high as Quantity) + 1 year) else null as Interval&lt;DateTime&gt; end /* @description: Returns an interval representing the normalized abatement of a given Condition. @comment: If the abatement element of the Condition is represented as a DateTime, the result is an interval beginning and ending on that DateTime. If the abatement is represented as a Quantity, the quantity is expected to be a calendar-duration and is interpreted as the age of the patient. The result is an interval from the date the patient turned that age to immediately before one year later. If the abatement is represented as a Quantity Interval, the quantities are expected to be calendar-durations and are interpreted as an age range during which the abatement occurred. The result is an interval from the date the patient turned the starting age of the quantity interval, and ending immediately before one year later than the date the patient turned the ending age of the quantity interval. */ define function ToAbatementInterval(condition Condition): if condition.abatement is DateTime then Interval[condition.abatement as DateTime, condition.abatement as DateTime] else if condition.abatement is Quantity then Interval[Patient.birthDate + (condition.abatement as Quantity), Patient.birthDate + (condition.abatement as Quantity) + 1 year) else if condition.abatement is Interval&lt;Quantity&gt; then Interval[Patient.birthDate + (condition.abatement.low as Quantity), Patient.birthDate + (condition.abatement.high as Quantity) + 1 year) else if condition.abatement is Interval&lt;DateTime&gt; then Interval[condition.abatement.low, condition.abatement.high) else null as Interval&lt;DateTime&gt; /* @description: Returns an interval representing the normalized abatement of a given Condition. @comment: If the abatement element of the Condition is represented as a DateTime, the result is an interval beginning and ending on that DateTime. If the abatement is represented as a Quantity, the quantity is expected to be a calendar-duration and is interpreted as the age of the patient. The result is an interval from the date the patient turned that age to immediately before one year later. If the abatement is represented as a Quantity Interval, the quantities are expected to be calendar-durations and are interpreted as an age range during which the abatement occurred. The result is an interval from the date the patient turned the starting age of the quantity interval, and ending immediately before one year later than the date the patient turned the ending age of the quantity interval. */ define fluent function toAbatementInterval(condition Condition): if condition.abatement is DateTime then Interval[condition.abatement as DateTime, condition.abatement as DateTime] else if condition.abatement is Quantity then Interval[Patient.birthDate + (condition.abatement as Quantity), Patient.birthDate + (condition.abatement as Quantity) + 1 year) else if condition.abatement is Interval&lt;Quantity&gt; then Interval[Patient.birthDate + (condition.abatement.low as Quantity), Patient.birthDate + (condition.abatement.high as Quantity) + 1 year) else if condition.abatement is Interval&lt;DateTime&gt; then Interval[condition.abatement.low, condition.abatement.high) else null as Interval&lt;DateTime&gt; /* @description: Returns an interval representing the normalized prevalence period of a given Condition. @comment: Uses the ToInterval and ToAbatementInterval functions to determine the widest potential interval from onset to abatement as specified in the given Condition. If the condition is active, the resulting interval will have a closed ending boundary. If the condition is not active, the resulting interval will have an open ending boundary. */ define function ToPrevalenceInterval(condition Condition): if condition.clinicalStatus ~ &quot;active&quot; or condition.clinicalStatus ~ &quot;recurrence&quot; or condition.clinicalStatus ~ &quot;relapse&quot; then Interval[start of ToInterval(condition.onset), end of ToAbatementInterval(condition)] else Interval[start of ToInterval(condition.onset), end of ToAbatementInterval(condition)) /* @description: Returns an interval representing the normalized prevalence period of a given Condition. @comment: Uses the ToInterval and ToAbatementInterval functions to determine the widest potential interval from onset to abatement as specified in the given Condition. If the condition is active, the resulting interval will have a closed ending boundary. If the condition is not active, the resulting interval will have an open ending boundary. */ define fluent function toPrevalenceInterval(condition Condition): if condition.clinicalStatus ~ &quot;active&quot; or condition.clinicalStatus ~ &quot;recurrence&quot; or condition.clinicalStatus ~ &quot;relapse&quot; then Interval[start of ToInterval(condition.onset), end of ToAbatementInterval(condition)] else Interval[start of ToInterval(condition.onset), end of ToAbatementInterval(condition)) /* @description: Returns the tail of the given uri (i.e. everything after the last slash in the URI). @comment: This function can be used to determine the logical id of a given resource. It can be used in a single-server environment to trace references. However, this function does not attempt to resolve or distinguish the base of the given url, and so cannot be used safely in multi-server environments. */ define function GetId(uri String ): Last(Split(uri, '/')) /* @description: Returns the tail of the given uri (i.e. everything after the last slash in the URI). @comment: This function can be used to determine the logical id of a given resource. It can be used in a single-server environment to trace references. However, this function does not attempt to resolve or distinguish the base of the given url, and so cannot be used safely in multi-server environments. */ define fluent function getId(uri String): Last(Split(uri, '/')) /* @description: Given an interval, return true if the interval has a starting boundary specified (i.e. the start of the interval is not null and not the minimum DateTime value) */ define function &quot;HasStart&quot;(period Interval&lt;DateTime&gt; ): not ( start of period is null or start of period = minimum DateTime ) /* @description: Given an interval, return true if the interval has a starting boundary specified (i.e. the start of the interval is not null and not the minimum DateTime value) */ define fluent function hasStart(period Interval&lt;DateTime&gt; ): not ( start of period is null or start of period = minimum DateTime ) /* @description: Given an interval, returns true if the interval has an ending boundary specified (i.e. the end of the interval is not null and not the maximum DateTime value) */ define function &quot;HasEnd&quot;(period Interval&lt;DateTime&gt; ): not ( end of period is null or end of period = maximum DateTime ) /* @description: Given an interval, returns true if the interval has an ending boundary specified (i.e. the end of the interval is not null and not the maximum DateTime value) */ define fluent function hasEnd(period Interval&lt;DateTime&gt; ): not ( end of period is null or end of period = maximum DateTime ) /* @description: Given an interval, returns the ending point if the interval has an ending boundary specified, otherwise, returns the starting point */ define function &quot;Latest&quot;(choice Choice&lt;DateTime, Quantity, Interval&lt;DateTime&gt;, Interval&lt;Quantity&gt;&gt; ): (choice.toInterval()) period return if (HasEnd(period)) then end of period else start of period /* @description: Given an interval, returns the ending point if the interval has an ending boundary specified, otherwise, returns the starting point */ define fluent function latest(choice Choice&lt;DateTime, Quantity, Interval&lt;DateTime&gt;, Interval&lt;Quantity&gt;&gt; ): (choice.toInterval()) period return if (HasEnd(period)) then end of period else start of period /* @description: Given an interval, return the starting point if the interval has a starting boundary specified, otherwise, return the ending point */ define function &quot;Earliest&quot;(choice Choice&lt;DateTime, Quantity, Interval&lt;DateTime&gt;, Interval&lt;Quantity&gt;&gt; ): (choice.toInterval()) period return if (HasStart(period)) then start of period else end of period /* @description: Given an interval, return the starting point if the interval has a starting boundary specified, otherwise, return the ending point */ define fluent function earliest(choice Choice&lt;DateTime, Quantity, Interval&lt;DateTime&gt;, Interval&lt;Quantity&gt;&gt; ): (choice.toInterval()) period return if (HasStart(period)) then start of period else end of period /* @description: Creates a list of integers from 1 to how many days are in the interval. Note, this wont create an index for the final day if it is less than 24 hours. This also includes the first 24 hour period. */ define function &quot;Interval To Day Numbers&quot;(Period Interval&lt;DateTime&gt;): ( expand { Interval[1, duration in days between start of Period and end of Period]} ) DayNumber return end of DayNumber /* @description: Creates a list of integers from 1 to how many days are in the interval. Note, this wont create an index for the final day if it is less than 24 hours. This also includes the first 24 hour period. */ define fluent function toDayNumbers(Period Interval&lt;DateTime&gt;): ( expand { Interval[1, duration in days between start of Period and end of Period]} ) DayNumber return end of DayNumber /* @description: Creates a list of 24 hour long intervals in an interval paired with the index (1 indexed) to which 24 hour interval it is. Note that the result will include intervals that are closed at the beginning and open at the end */ define function &quot;Days In Period&quot;(Period Interval&lt;DateTime&gt;): ( &quot;Interval To Day Numbers&quot;(Period)) DayIndex let startPeriod: start of Period + (24 hours * (DayIndex - 1)), endPeriod: if (hours between startPeriod and end of Period &lt; 24) then startPeriod else start of Period + (24 hours * DayIndex) return Tuple { dayIndex: DayIndex, dayPeriod: Interval[startPeriod, endPeriod) } /* @description: Creates a list of 24 hour long intervals in an interval paired with the index (1 indexed) to which 24 hour interval it is. Note that the result will include intervals that are closed at the beginning and open at the end */ define fluent function daysInPeriod(Period Interval&lt;DateTime&gt;): ( &quot;Interval To Day Numbers&quot;(Period)) DayIndex let startPeriod: start of Period + (24 hours * (DayIndex - 1)), endPeriod: if (hours between startPeriod and end of Period &lt; 24) then startPeriod else start of Period + (24 hours * DayIndex) return Tuple { dayIndex: DayIndex, dayPeriod: Interval[startPeriod, endPeriod) }````: **Url: **
  * ?: [QiCore Common](Library-QICoreCommon.md)
* * **Content: **text/cql: ````/* @author: Stan Rankins @description: Common terminologies and functions used in QI-Core-based CQL artifacts @update: Fashioned after FHIRCommon Version 4.0.012 for use in ecqm-content-qicore-2022 repos */ library QICoreCommon version '1.0.000' using QICore version '4.1.1' include FHIRHelpers version '4.0.013' codesystem &quot;LOINC&quot;: 'http://loinc.org' codesystem &quot;SNOMEDCT&quot;: 'http://snomed.info/sct' codesystem &quot;ICD10CM&quot;: 'http://hl7.org/fhir/sid/icd-10-cm' codesystem &quot;RoleCode&quot;: 'http://terminology.hl7.org/CodeSystem/v3-RoleCode' codesystem &quot;Diagnosis Role&quot;: 'http://terminology.hl7.org/CodeSystem/diagnosis-role' codesystem &quot;RequestIntent&quot;: 'http://terminology.hl7.org/CodeSystem/request-intent' codesystem &quot;MedicationRequestCategory&quot;: 'http://terminology.hl7.org/CodeSystem/medicationrequest-category' codesystem &quot;ConditionClinicalStatusCodes&quot;: 'http://terminology.hl7.org/CodeSystem/condition-clinical' codesystem &quot;ConditionVerificationStatusCodes&quot;: 'http://terminology.hl7.org/CodeSystem/condition-ver-status' codesystem &quot;AllergyIntoleranceClinicalStatusCodes&quot;: 'http://terminology.hl7.org/CodeSystem/allergyintolerance-clinical' codesystem &quot;AllergyIntoleranceVerificationStatusCodes&quot;: 'http://terminology.hl7.org/CodeSystem/allergyintolerance-verification' codesystem &quot;ConditionCategoryCodes&quot;: 'http://terminology.hl7.org/CodeSystem/condition-category' codesystem &quot;ObservationCategoryCodes&quot;: 'http://terminology.hl7.org/CodeSystem/observation-category' valueset &quot;Active Condition&quot;: 'http://fhir.org/guides/cqf/common/ValueSet/active-condition' valueset &quot;Inactive Condition&quot;: 'http://fhir.org/guides/cqf/common/ValueSet/inactive-condition' code &quot;Birthdate&quot;: '21112-8' from &quot;LOINC&quot; display 'Birth date' code &quot;Dead&quot;: '419099009' from &quot;SNOMEDCT&quot; display 'Dead' code &quot;ER&quot;: 'ER' from &quot;RoleCode&quot; display 'Emergency room' code &quot;ICU&quot;: 'ICU' from &quot;RoleCode&quot; display 'Intensive care unit' code &quot;Billing&quot;: 'billing' from &quot;Diagnosis Role&quot; display 'Billing' // Condition Clinical Status Codes - Consider value sets for these code &quot;active&quot;: 'active' from &quot;ConditionClinicalStatusCodes&quot; code &quot;recurrence&quot;: 'recurrence' from &quot;ConditionClinicalStatusCodes&quot; code &quot;relapse&quot;: 'relapse' from &quot;ConditionClinicalStatusCodes&quot; code &quot;inactive&quot;: 'inactive' from &quot;ConditionClinicalStatusCodes&quot; code &quot;remission&quot;: 'remission' from &quot;ConditionClinicalStatusCodes&quot; code &quot;resolved&quot;: 'resolved' from &quot;ConditionClinicalStatusCodes&quot; // Condition Verification Status Codes - Consider value sets for these code &quot;unconfirmed&quot;: 'unconfirmed' from ConditionVerificationStatusCodes code &quot;provisional&quot;: 'provisional' from ConditionVerificationStatusCodes code &quot;differential&quot;: 'differential' from ConditionVerificationStatusCodes code &quot;confirmed&quot;: 'confirmed' from ConditionVerificationStatusCodes code &quot;refuted&quot;: 'refuted' from ConditionVerificationStatusCodes code &quot;entered-in-error&quot;: 'entered-in-error' from ConditionVerificationStatusCodes code &quot;allergy-active&quot;: 'active' from &quot;AllergyIntoleranceClinicalStatusCodes&quot; code &quot;allergy-inactive&quot;: 'inactive' from &quot;AllergyIntoleranceClinicalStatusCodes&quot; code &quot;allergy-resolved&quot;: 'resolved' from &quot;AllergyIntoleranceClinicalStatusCodes&quot; // Allergy/Intolerance Verification Status Codes - Consider value sets for these code &quot;allergy-unconfirmed&quot;: 'unconfirmed' from AllergyIntoleranceVerificationStatusCodes code &quot;allergy-confirmed&quot;: 'confirmed' from AllergyIntoleranceVerificationStatusCodes code &quot;allergy-refuted&quot;: 'refuted' from AllergyIntoleranceVerificationStatusCodes // MedicationRequest Category Codes code &quot;Community&quot;: 'community' from &quot;MedicationRequestCategory&quot; display 'Community' code &quot;Discharge&quot;: 'discharge' from &quot;MedicationRequestCategory&quot; display 'Discharge' // Diagnosis Role Codes code &quot;AD&quot;: 'AD' from &quot;Diagnosis Role&quot; display 'Admission diagnosis' code &quot;DD&quot;: 'DD' from &quot;Diagnosis Role&quot; display 'Discharge diagnosis' code &quot;CC&quot;: 'CC' from &quot;Diagnosis Role&quot; display 'Chief complaint' code &quot;CM&quot;: 'CM' from &quot;Diagnosis Role&quot; display 'Comorbidity diagnosis' code &quot;pre-op&quot;: 'pre-op' from &quot;Diagnosis Role&quot; display 'pre-op diagnosis' code &quot;post-op&quot;: 'post-op' from &quot;Diagnosis Role&quot; display 'post-op diagnosis' code &quot;billing&quot;: 'billing' from &quot;Diagnosis Role&quot; display 'billing diagnosis' // Observation Category Codes code &quot;social-history&quot;: 'social-history' from &quot;ObservationCategoryCodes&quot; display 'Social History' code &quot;vital-signs&quot;: 'vital-signs' from &quot;ObservationCategoryCodes&quot; display 'Vital Signs' code &quot;imaging&quot;: 'imaging' from &quot;ObservationCategoryCodes&quot; display 'Imaging' code &quot;laboratory&quot;: 'laboratory' from &quot;ObservationCategoryCodes&quot; display 'Laboratory' code &quot;procedure&quot;: 'procedure' from &quot;ObservationCategoryCodes&quot; display 'Procedure' code &quot;survey&quot;: 'survey' from &quot;ObservationCategoryCodes&quot; display 'Survey' code &quot;exam&quot;: 'exam' from &quot;ObservationCategoryCodes&quot; display 'Exam' code &quot;therapy&quot;: 'therapy' from &quot;ObservationCategoryCodes&quot; display 'Therapy' code &quot;activity&quot;: 'activity' from &quot;ObservationCategoryCodes&quot; display 'Activity' // Condition Category Codes code &quot;problem-list-item&quot;: 'problem-list-item' from &quot;ConditionCategoryCodes&quot; display 'Problem List Item' code &quot;encounter-diagnosis&quot;: 'encounter-diagnosis' from &quot;ConditionCategoryCodes&quot; display 'Encounter Diagnosis' context Patient /* @description: Normalizes a value that is a choice of timing-valued types to an equivalent interval @comment: Normalizes a choice type of DateTime, Quanitty, Interval&lt;DateTime&gt;, or Interval&lt;Quantity&gt; types to an equivalent interval. This selection of choice types is a superset of the majority of choice types that are used as possible representations for timing-valued elements in QICore, allowing this function to be used across any resource. The input can be provided as a DateTime, Quantity, Interval&lt;DateTime&gt; or Interval&lt;Quantity&gt;. The intent of this function is to provide a clear and concise mechanism to treat single elements that have multiple possible representations as intervals so that logic doesn't have to account for the variability. More complex calculations (such as medication request period or dispense period calculation) need specific guidance and consideration. That guidance may make use of this function, but the focus of this function is on single element calculations where the semantics are unambiguous. If the input is a DateTime, the result a DateTime Interval beginning and ending on that DateTime. If the input is a Quantity, the quantity is expected to be a calendar-duration interpreted as an Age, and the result is a DateTime Interval beginning on the Date the patient turned that age and ending immediately before one year later. If the input is a DateTime Interval, the result is the input. If the input is a Quantity Interval, the quantities are expected to be calendar-durations interpreted as an Age, and the result is a DateTime Interval beginning on the date the patient turned the age given as the start of the quantity interval, and ending immediately before one year later than the date the patient turned the age given as the end of the quantity interval. Any other input will reslt in a null DateTime Interval */ define function ToInterval(choice Choice&lt;DateTime, Quantity, Interval&lt;DateTime&gt;, Interval&lt;Quantity&gt;&gt;): case when choice is DateTime then Interval[choice as DateTime, choice as DateTime] when choice is Interval&lt;DateTime&gt; then choice as Interval&lt;DateTime&gt; when choice is Quantity then Interval[Patient.birthDate + (choice as Quantity), Patient.birthDate + (choice as Quantity) + 1 year) when choice is Interval&lt;Quantity&gt; then Interval[Patient.birthDate + (choice.low as Quantity), Patient.birthDate + (choice.high as Quantity) + 1 year) else null as Interval&lt;DateTime&gt; end /* @description: Normalizes a value that is a choice of timing-valued types to an equivalent interval @comment: Normalizes a choice type of DateTime, Quanitty, Interval&lt;DateTime&gt;, or Interval&lt;Quantity&gt; types to an equivalent interval. This selection of choice types is a superset of the majority of choice types that are used as possible representations for timing-valued elements in QICore, allowing this function to be used across any resource. The input can be provided as a DateTime, Quantity, Interval&lt;DateTime&gt; or Interval&lt;Quantity&gt;. The intent of this function is to provide a clear and concise mechanism to treat single elements that have multiple possible representations as intervals so that logic doesn't have to account for the variability. More complex calculations (such as medication request period or dispense period calculation) need specific guidance and consideration. That guidance may make use of this function, but the focus of this function is on single element calculations where the semantics are unambiguous. If the input is a DateTime, the result a DateTime Interval beginning and ending on that DateTime. If the input is a Quantity, the quantity is expected to be a calendar-duration interpreted as an Age, and the result is a DateTime Interval beginning on the Date the patient turned that age and ending immediately before one year later. If the input is a DateTime Interval, the result is the input. If the input is a Quantity Interval, the quantities are expected to be calendar-durations interpreted as an Age, and the result is a DateTime Interval beginning on the date the patient turned the age given as the start of the quantity interval, and ending immediately before one year later than the date the patient turned the age given as the end of the quantity interval. Any other input will reslt in a null DateTime Interval */ define fluent function toInterval(choice Choice&lt;DateTime, Quantity, Interval&lt;DateTime&gt;, Interval&lt;Quantity&gt;&gt;): case when choice is DateTime then Interval[choice as DateTime, choice as DateTime] when choice is Interval&lt;DateTime&gt; then choice as Interval&lt;DateTime&gt; when choice is Quantity then Interval[Patient.birthDate + (choice as Quantity), Patient.birthDate + (choice as Quantity) + 1 year) when choice is Interval&lt;Quantity&gt; then Interval[Patient.birthDate + (choice.low as Quantity), Patient.birthDate + (choice.high as Quantity) + 1 year) else null as Interval&lt;DateTime&gt; end /* @description: Returns an interval representing the normalized abatement of a given Condition. @comment: If the abatement element of the Condition is represented as a DateTime, the result is an interval beginning and ending on that DateTime. If the abatement is represented as a Quantity, the quantity is expected to be a calendar-duration and is interpreted as the age of the patient. The result is an interval from the date the patient turned that age to immediately before one year later. If the abatement is represented as a Quantity Interval, the quantities are expected to be calendar-durations and are interpreted as an age range during which the abatement occurred. The result is an interval from the date the patient turned the starting age of the quantity interval, and ending immediately before one year later than the date the patient turned the ending age of the quantity interval. */ define function ToAbatementInterval(condition Condition): if condition.abatement is DateTime then Interval[condition.abatement as DateTime, condition.abatement as DateTime] else if condition.abatement is Quantity then Interval[Patient.birthDate + (condition.abatement as Quantity), Patient.birthDate + (condition.abatement as Quantity) + 1 year) else if condition.abatement is Interval&lt;Quantity&gt; then Interval[Patient.birthDate + (condition.abatement.low as Quantity), Patient.birthDate + (condition.abatement.high as Quantity) + 1 year) else if condition.abatement is Interval&lt;DateTime&gt; then Interval[condition.abatement.low, condition.abatement.high) else null as Interval&lt;DateTime&gt; /* @description: Returns an interval representing the normalized abatement of a given Condition. @comment: If the abatement element of the Condition is represented as a DateTime, the result is an interval beginning and ending on that DateTime. If the abatement is represented as a Quantity, the quantity is expected to be a calendar-duration and is interpreted as the age of the patient. The result is an interval from the date the patient turned that age to immediately before one year later. If the abatement is represented as a Quantity Interval, the quantities are expected to be calendar-durations and are interpreted as an age range during which the abatement occurred. The result is an interval from the date the patient turned the starting age of the quantity interval, and ending immediately before one year later than the date the patient turned the ending age of the quantity interval. */ define fluent function toAbatementInterval(condition Condition): if condition.abatement is DateTime then Interval[condition.abatement as DateTime, condition.abatement as DateTime] else if condition.abatement is Quantity then Interval[Patient.birthDate + (condition.abatement as Quantity), Patient.birthDate + (condition.abatement as Quantity) + 1 year) else if condition.abatement is Interval&lt;Quantity&gt; then Interval[Patient.birthDate + (condition.abatement.low as Quantity), Patient.birthDate + (condition.abatement.high as Quantity) + 1 year) else if condition.abatement is Interval&lt;DateTime&gt; then Interval[condition.abatement.low, condition.abatement.high) else null as Interval&lt;DateTime&gt; /* @description: Returns an interval representing the normalized prevalence period of a given Condition. @comment: Uses the ToInterval and ToAbatementInterval functions to determine the widest potential interval from onset to abatement as specified in the given Condition. If the condition is active, the resulting interval will have a closed ending boundary. If the condition is not active, the resulting interval will have an open ending boundary. */ define function ToPrevalenceInterval(condition Condition): if condition.clinicalStatus ~ &quot;active&quot; or condition.clinicalStatus ~ &quot;recurrence&quot; or condition.clinicalStatus ~ &quot;relapse&quot; then Interval[start of ToInterval(condition.onset), end of ToAbatementInterval(condition)] else Interval[start of ToInterval(condition.onset), end of ToAbatementInterval(condition)) /* @description: Returns an interval representing the normalized prevalence period of a given Condition. @comment: Uses the ToInterval and ToAbatementInterval functions to determine the widest potential interval from onset to abatement as specified in the given Condition. If the condition is active, the resulting interval will have a closed ending boundary. If the condition is not active, the resulting interval will have an open ending boundary. */ define fluent function toPrevalenceInterval(condition Condition): if condition.clinicalStatus ~ &quot;active&quot; or condition.clinicalStatus ~ &quot;recurrence&quot; or condition.clinicalStatus ~ &quot;relapse&quot; then Interval[start of ToInterval(condition.onset), end of ToAbatementInterval(condition)] else Interval[start of ToInterval(condition.onset), end of ToAbatementInterval(condition)) /* @description: Returns the tail of the given uri (i.e. everything after the last slash in the URI). @comment: This function can be used to determine the logical id of a given resource. It can be used in a single-server environment to trace references. However, this function does not attempt to resolve or distinguish the base of the given url, and so cannot be used safely in multi-server environments. */ define function GetId(uri String ): Last(Split(uri, '/')) /* @description: Returns the tail of the given uri (i.e. everything after the last slash in the URI). @comment: This function can be used to determine the logical id of a given resource. It can be used in a single-server environment to trace references. However, this function does not attempt to resolve or distinguish the base of the given url, and so cannot be used safely in multi-server environments. */ define fluent function getId(uri String): Last(Split(uri, '/')) /* @description: Given an interval, return true if the interval has a starting boundary specified (i.e. the start of the interval is not null and not the minimum DateTime value) */ define function &quot;HasStart&quot;(period Interval&lt;DateTime&gt; ): not ( start of period is null or start of period = minimum DateTime ) /* @description: Given an interval, return true if the interval has a starting boundary specified (i.e. the start of the interval is not null and not the minimum DateTime value) */ define fluent function hasStart(period Interval&lt;DateTime&gt; ): not ( start of period is null or start of period = minimum DateTime ) /* @description: Given an interval, returns true if the interval has an ending boundary specified (i.e. the end of the interval is not null and not the maximum DateTime value) */ define function &quot;HasEnd&quot;(period Interval&lt;DateTime&gt; ): not ( end of period is null or end of period = maximum DateTime ) /* @description: Given an interval, returns true if the interval has an ending boundary specified (i.e. the end of the interval is not null and not the maximum DateTime value) */ define fluent function hasEnd(period Interval&lt;DateTime&gt; ): not ( end of period is null or end of period = maximum DateTime ) /* @description: Given an interval, returns the ending point if the interval has an ending boundary specified, otherwise, returns the starting point */ define function &quot;Latest&quot;(choice Choice&lt;DateTime, Quantity, Interval&lt;DateTime&gt;, Interval&lt;Quantity&gt;&gt; ): (choice.toInterval()) period return if (HasEnd(period)) then end of period else start of period /* @description: Given an interval, returns the ending point if the interval has an ending boundary specified, otherwise, returns the starting point */ define fluent function latest(choice Choice&lt;DateTime, Quantity, Interval&lt;DateTime&gt;, Interval&lt;Quantity&gt;&gt; ): (choice.toInterval()) period return if (HasEnd(period)) then end of period else start of period /* @description: Given an interval, return the starting point if the interval has a starting boundary specified, otherwise, return the ending point */ define function &quot;Earliest&quot;(choice Choice&lt;DateTime, Quantity, Interval&lt;DateTime&gt;, Interval&lt;Quantity&gt;&gt; ): (choice.toInterval()) period return if (HasStart(period)) then start of period else end of period /* @description: Given an interval, return the starting point if the interval has a starting boundary specified, otherwise, return the ending point */ define fluent function earliest(choice Choice&lt;DateTime, Quantity, Interval&lt;DateTime&gt;, Interval&lt;Quantity&gt;&gt; ): (choice.toInterval()) period return if (HasStart(period)) then start of period else end of period /* @description: Creates a list of integers from 1 to how many days are in the interval. Note, this wont create an index for the final day if it is less than 24 hours. This also includes the first 24 hour period. */ define function &quot;Interval To Day Numbers&quot;(Period Interval&lt;DateTime&gt;): ( expand { Interval[1, duration in days between start of Period and end of Period]} ) DayNumber return end of DayNumber /* @description: Creates a list of integers from 1 to how many days are in the interval. Note, this wont create an index for the final day if it is less than 24 hours. This also includes the first 24 hour period. */ define fluent function toDayNumbers(Period Interval&lt;DateTime&gt;): ( expand { Interval[1, duration in days between start of Period and end of Period]} ) DayNumber return end of DayNumber /* @description: Creates a list of 24 hour long intervals in an interval paired with the index (1 indexed) to which 24 hour interval it is. Note that the result will include intervals that are closed at the beginning and open at the end */ define function &quot;Days In Period&quot;(Period Interval&lt;DateTime&gt;): ( &quot;Interval To Day Numbers&quot;(Period)) DayIndex let startPeriod: start of Period + (24 hours * (DayIndex - 1)), endPeriod: if (hours between startPeriod and end of Period &lt; 24) then startPeriod else start of Period + (24 hours * DayIndex) return Tuple { dayIndex: DayIndex, dayPeriod: Interval[startPeriod, endPeriod) } /* @description: Creates a list of 24 hour long intervals in an interval paired with the index (1 indexed) to which 24 hour interval it is. Note that the result will include intervals that are closed at the beginning and open at the end */ define fluent function daysInPeriod(Period Interval&lt;DateTime&gt;): ( &quot;Interval To Day Numbers&quot;(Period)) DayIndex let startPeriod: start of Period + (24 hours * (DayIndex - 1)), endPeriod: if (hours between startPeriod and end of Period &lt; 24) then startPeriod else start of Period + (24 hours * DayIndex) return Tuple { dayIndex: DayIndex, dayPeriod: Interval[startPeriod, endPeriod) }````: **Version: **
  * ?: 0.1.0
* * **Content: **text/cql: ````/* @author: Stan Rankins @description: Common terminologies and functions used in QI-Core-based CQL artifacts @update: Fashioned after FHIRCommon Version 4.0.012 for use in ecqm-content-qicore-2022 repos */ library QICoreCommon version '1.0.000' using QICore version '4.1.1' include FHIRHelpers version '4.0.013' codesystem &quot;LOINC&quot;: 'http://loinc.org' codesystem &quot;SNOMEDCT&quot;: 'http://snomed.info/sct' codesystem &quot;ICD10CM&quot;: 'http://hl7.org/fhir/sid/icd-10-cm' codesystem &quot;RoleCode&quot;: 'http://terminology.hl7.org/CodeSystem/v3-RoleCode' codesystem &quot;Diagnosis Role&quot;: 'http://terminology.hl7.org/CodeSystem/diagnosis-role' codesystem &quot;RequestIntent&quot;: 'http://terminology.hl7.org/CodeSystem/request-intent' codesystem &quot;MedicationRequestCategory&quot;: 'http://terminology.hl7.org/CodeSystem/medicationrequest-category' codesystem &quot;ConditionClinicalStatusCodes&quot;: 'http://terminology.hl7.org/CodeSystem/condition-clinical' codesystem &quot;ConditionVerificationStatusCodes&quot;: 'http://terminology.hl7.org/CodeSystem/condition-ver-status' codesystem &quot;AllergyIntoleranceClinicalStatusCodes&quot;: 'http://terminology.hl7.org/CodeSystem/allergyintolerance-clinical' codesystem &quot;AllergyIntoleranceVerificationStatusCodes&quot;: 'http://terminology.hl7.org/CodeSystem/allergyintolerance-verification' codesystem &quot;ConditionCategoryCodes&quot;: 'http://terminology.hl7.org/CodeSystem/condition-category' codesystem &quot;ObservationCategoryCodes&quot;: 'http://terminology.hl7.org/CodeSystem/observation-category' valueset &quot;Active Condition&quot;: 'http://fhir.org/guides/cqf/common/ValueSet/active-condition' valueset &quot;Inactive Condition&quot;: 'http://fhir.org/guides/cqf/common/ValueSet/inactive-condition' code &quot;Birthdate&quot;: '21112-8' from &quot;LOINC&quot; display 'Birth date' code &quot;Dead&quot;: '419099009' from &quot;SNOMEDCT&quot; display 'Dead' code &quot;ER&quot;: 'ER' from &quot;RoleCode&quot; display 'Emergency room' code &quot;ICU&quot;: 'ICU' from &quot;RoleCode&quot; display 'Intensive care unit' code &quot;Billing&quot;: 'billing' from &quot;Diagnosis Role&quot; display 'Billing' // Condition Clinical Status Codes - Consider value sets for these code &quot;active&quot;: 'active' from &quot;ConditionClinicalStatusCodes&quot; code &quot;recurrence&quot;: 'recurrence' from &quot;ConditionClinicalStatusCodes&quot; code &quot;relapse&quot;: 'relapse' from &quot;ConditionClinicalStatusCodes&quot; code &quot;inactive&quot;: 'inactive' from &quot;ConditionClinicalStatusCodes&quot; code &quot;remission&quot;: 'remission' from &quot;ConditionClinicalStatusCodes&quot; code &quot;resolved&quot;: 'resolved' from &quot;ConditionClinicalStatusCodes&quot; // Condition Verification Status Codes - Consider value sets for these code &quot;unconfirmed&quot;: 'unconfirmed' from ConditionVerificationStatusCodes code &quot;provisional&quot;: 'provisional' from ConditionVerificationStatusCodes code &quot;differential&quot;: 'differential' from ConditionVerificationStatusCodes code &quot;confirmed&quot;: 'confirmed' from ConditionVerificationStatusCodes code &quot;refuted&quot;: 'refuted' from ConditionVerificationStatusCodes code &quot;entered-in-error&quot;: 'entered-in-error' from ConditionVerificationStatusCodes code &quot;allergy-active&quot;: 'active' from &quot;AllergyIntoleranceClinicalStatusCodes&quot; code &quot;allergy-inactive&quot;: 'inactive' from &quot;AllergyIntoleranceClinicalStatusCodes&quot; code &quot;allergy-resolved&quot;: 'resolved' from &quot;AllergyIntoleranceClinicalStatusCodes&quot; // Allergy/Intolerance Verification Status Codes - Consider value sets for these code &quot;allergy-unconfirmed&quot;: 'unconfirmed' from AllergyIntoleranceVerificationStatusCodes code &quot;allergy-confirmed&quot;: 'confirmed' from AllergyIntoleranceVerificationStatusCodes code &quot;allergy-refuted&quot;: 'refuted' from AllergyIntoleranceVerificationStatusCodes // MedicationRequest Category Codes code &quot;Community&quot;: 'community' from &quot;MedicationRequestCategory&quot; display 'Community' code &quot;Discharge&quot;: 'discharge' from &quot;MedicationRequestCategory&quot; display 'Discharge' // Diagnosis Role Codes code &quot;AD&quot;: 'AD' from &quot;Diagnosis Role&quot; display 'Admission diagnosis' code &quot;DD&quot;: 'DD' from &quot;Diagnosis Role&quot; display 'Discharge diagnosis' code &quot;CC&quot;: 'CC' from &quot;Diagnosis Role&quot; display 'Chief complaint' code &quot;CM&quot;: 'CM' from &quot;Diagnosis Role&quot; display 'Comorbidity diagnosis' code &quot;pre-op&quot;: 'pre-op' from &quot;Diagnosis Role&quot; display 'pre-op diagnosis' code &quot;post-op&quot;: 'post-op' from &quot;Diagnosis Role&quot; display 'post-op diagnosis' code &quot;billing&quot;: 'billing' from &quot;Diagnosis Role&quot; display 'billing diagnosis' // Observation Category Codes code &quot;social-history&quot;: 'social-history' from &quot;ObservationCategoryCodes&quot; display 'Social History' code &quot;vital-signs&quot;: 'vital-signs' from &quot;ObservationCategoryCodes&quot; display 'Vital Signs' code &quot;imaging&quot;: 'imaging' from &quot;ObservationCategoryCodes&quot; display 'Imaging' code &quot;laboratory&quot;: 'laboratory' from &quot;ObservationCategoryCodes&quot; display 'Laboratory' code &quot;procedure&quot;: 'procedure' from &quot;ObservationCategoryCodes&quot; display 'Procedure' code &quot;survey&quot;: 'survey' from &quot;ObservationCategoryCodes&quot; display 'Survey' code &quot;exam&quot;: 'exam' from &quot;ObservationCategoryCodes&quot; display 'Exam' code &quot;therapy&quot;: 'therapy' from &quot;ObservationCategoryCodes&quot; display 'Therapy' code &quot;activity&quot;: 'activity' from &quot;ObservationCategoryCodes&quot; display 'Activity' // Condition Category Codes code &quot;problem-list-item&quot;: 'problem-list-item' from &quot;ConditionCategoryCodes&quot; display 'Problem List Item' code &quot;encounter-diagnosis&quot;: 'encounter-diagnosis' from &quot;ConditionCategoryCodes&quot; display 'Encounter Diagnosis' context Patient /* @description: Normalizes a value that is a choice of timing-valued types to an equivalent interval @comment: Normalizes a choice type of DateTime, Quanitty, Interval&lt;DateTime&gt;, or Interval&lt;Quantity&gt; types to an equivalent interval. This selection of choice types is a superset of the majority of choice types that are used as possible representations for timing-valued elements in QICore, allowing this function to be used across any resource. The input can be provided as a DateTime, Quantity, Interval&lt;DateTime&gt; or Interval&lt;Quantity&gt;. The intent of this function is to provide a clear and concise mechanism to treat single elements that have multiple possible representations as intervals so that logic doesn't have to account for the variability. More complex calculations (such as medication request period or dispense period calculation) need specific guidance and consideration. That guidance may make use of this function, but the focus of this function is on single element calculations where the semantics are unambiguous. If the input is a DateTime, the result a DateTime Interval beginning and ending on that DateTime. If the input is a Quantity, the quantity is expected to be a calendar-duration interpreted as an Age, and the result is a DateTime Interval beginning on the Date the patient turned that age and ending immediately before one year later. If the input is a DateTime Interval, the result is the input. If the input is a Quantity Interval, the quantities are expected to be calendar-durations interpreted as an Age, and the result is a DateTime Interval beginning on the date the patient turned the age given as the start of the quantity interval, and ending immediately before one year later than the date the patient turned the age given as the end of the quantity interval. Any other input will reslt in a null DateTime Interval */ define function ToInterval(choice Choice&lt;DateTime, Quantity, Interval&lt;DateTime&gt;, Interval&lt;Quantity&gt;&gt;): case when choice is DateTime then Interval[choice as DateTime, choice as DateTime] when choice is Interval&lt;DateTime&gt; then choice as Interval&lt;DateTime&gt; when choice is Quantity then Interval[Patient.birthDate + (choice as Quantity), Patient.birthDate + (choice as Quantity) + 1 year) when choice is Interval&lt;Quantity&gt; then Interval[Patient.birthDate + (choice.low as Quantity), Patient.birthDate + (choice.high as Quantity) + 1 year) else null as Interval&lt;DateTime&gt; end /* @description: Normalizes a value that is a choice of timing-valued types to an equivalent interval @comment: Normalizes a choice type of DateTime, Quanitty, Interval&lt;DateTime&gt;, or Interval&lt;Quantity&gt; types to an equivalent interval. This selection of choice types is a superset of the majority of choice types that are used as possible representations for timing-valued elements in QICore, allowing this function to be used across any resource. The input can be provided as a DateTime, Quantity, Interval&lt;DateTime&gt; or Interval&lt;Quantity&gt;. The intent of this function is to provide a clear and concise mechanism to treat single elements that have multiple possible representations as intervals so that logic doesn't have to account for the variability. More complex calculations (such as medication request period or dispense period calculation) need specific guidance and consideration. That guidance may make use of this function, but the focus of this function is on single element calculations where the semantics are unambiguous. If the input is a DateTime, the result a DateTime Interval beginning and ending on that DateTime. If the input is a Quantity, the quantity is expected to be a calendar-duration interpreted as an Age, and the result is a DateTime Interval beginning on the Date the patient turned that age and ending immediately before one year later. If the input is a DateTime Interval, the result is the input. If the input is a Quantity Interval, the quantities are expected to be calendar-durations interpreted as an Age, and the result is a DateTime Interval beginning on the date the patient turned the age given as the start of the quantity interval, and ending immediately before one year later than the date the patient turned the age given as the end of the quantity interval. Any other input will reslt in a null DateTime Interval */ define fluent function toInterval(choice Choice&lt;DateTime, Quantity, Interval&lt;DateTime&gt;, Interval&lt;Quantity&gt;&gt;): case when choice is DateTime then Interval[choice as DateTime, choice as DateTime] when choice is Interval&lt;DateTime&gt; then choice as Interval&lt;DateTime&gt; when choice is Quantity then Interval[Patient.birthDate + (choice as Quantity), Patient.birthDate + (choice as Quantity) + 1 year) when choice is Interval&lt;Quantity&gt; then Interval[Patient.birthDate + (choice.low as Quantity), Patient.birthDate + (choice.high as Quantity) + 1 year) else null as Interval&lt;DateTime&gt; end /* @description: Returns an interval representing the normalized abatement of a given Condition. @comment: If the abatement element of the Condition is represented as a DateTime, the result is an interval beginning and ending on that DateTime. If the abatement is represented as a Quantity, the quantity is expected to be a calendar-duration and is interpreted as the age of the patient. The result is an interval from the date the patient turned that age to immediately before one year later. If the abatement is represented as a Quantity Interval, the quantities are expected to be calendar-durations and are interpreted as an age range during which the abatement occurred. The result is an interval from the date the patient turned the starting age of the quantity interval, and ending immediately before one year later than the date the patient turned the ending age of the quantity interval. */ define function ToAbatementInterval(condition Condition): if condition.abatement is DateTime then Interval[condition.abatement as DateTime, condition.abatement as DateTime] else if condition.abatement is Quantity then Interval[Patient.birthDate + (condition.abatement as Quantity), Patient.birthDate + (condition.abatement as Quantity) + 1 year) else if condition.abatement is Interval&lt;Quantity&gt; then Interval[Patient.birthDate + (condition.abatement.low as Quantity), Patient.birthDate + (condition.abatement.high as Quantity) + 1 year) else if condition.abatement is Interval&lt;DateTime&gt; then Interval[condition.abatement.low, condition.abatement.high) else null as Interval&lt;DateTime&gt; /* @description: Returns an interval representing the normalized abatement of a given Condition. @comment: If the abatement element of the Condition is represented as a DateTime, the result is an interval beginning and ending on that DateTime. If the abatement is represented as a Quantity, the quantity is expected to be a calendar-duration and is interpreted as the age of the patient. The result is an interval from the date the patient turned that age to immediately before one year later. If the abatement is represented as a Quantity Interval, the quantities are expected to be calendar-durations and are interpreted as an age range during which the abatement occurred. The result is an interval from the date the patient turned the starting age of the quantity interval, and ending immediately before one year later than the date the patient turned the ending age of the quantity interval. */ define fluent function toAbatementInterval(condition Condition): if condition.abatement is DateTime then Interval[condition.abatement as DateTime, condition.abatement as DateTime] else if condition.abatement is Quantity then Interval[Patient.birthDate + (condition.abatement as Quantity), Patient.birthDate + (condition.abatement as Quantity) + 1 year) else if condition.abatement is Interval&lt;Quantity&gt; then Interval[Patient.birthDate + (condition.abatement.low as Quantity), Patient.birthDate + (condition.abatement.high as Quantity) + 1 year) else if condition.abatement is Interval&lt;DateTime&gt; then Interval[condition.abatement.low, condition.abatement.high) else null as Interval&lt;DateTime&gt; /* @description: Returns an interval representing the normalized prevalence period of a given Condition. @comment: Uses the ToInterval and ToAbatementInterval functions to determine the widest potential interval from onset to abatement as specified in the given Condition. If the condition is active, the resulting interval will have a closed ending boundary. If the condition is not active, the resulting interval will have an open ending boundary. */ define function ToPrevalenceInterval(condition Condition): if condition.clinicalStatus ~ &quot;active&quot; or condition.clinicalStatus ~ &quot;recurrence&quot; or condition.clinicalStatus ~ &quot;relapse&quot; then Interval[start of ToInterval(condition.onset), end of ToAbatementInterval(condition)] else Interval[start of ToInterval(condition.onset), end of ToAbatementInterval(condition)) /* @description: Returns an interval representing the normalized prevalence period of a given Condition. @comment: Uses the ToInterval and ToAbatementInterval functions to determine the widest potential interval from onset to abatement as specified in the given Condition. If the condition is active, the resulting interval will have a closed ending boundary. If the condition is not active, the resulting interval will have an open ending boundary. */ define fluent function toPrevalenceInterval(condition Condition): if condition.clinicalStatus ~ &quot;active&quot; or condition.clinicalStatus ~ &quot;recurrence&quot; or condition.clinicalStatus ~ &quot;relapse&quot; then Interval[start of ToInterval(condition.onset), end of ToAbatementInterval(condition)] else Interval[start of ToInterval(condition.onset), end of ToAbatementInterval(condition)) /* @description: Returns the tail of the given uri (i.e. everything after the last slash in the URI). @comment: This function can be used to determine the logical id of a given resource. It can be used in a single-server environment to trace references. However, this function does not attempt to resolve or distinguish the base of the given url, and so cannot be used safely in multi-server environments. */ define function GetId(uri String ): Last(Split(uri, '/')) /* @description: Returns the tail of the given uri (i.e. everything after the last slash in the URI). @comment: This function can be used to determine the logical id of a given resource. It can be used in a single-server environment to trace references. However, this function does not attempt to resolve or distinguish the base of the given url, and so cannot be used safely in multi-server environments. */ define fluent function getId(uri String): Last(Split(uri, '/')) /* @description: Given an interval, return true if the interval has a starting boundary specified (i.e. the start of the interval is not null and not the minimum DateTime value) */ define function &quot;HasStart&quot;(period Interval&lt;DateTime&gt; ): not ( start of period is null or start of period = minimum DateTime ) /* @description: Given an interval, return true if the interval has a starting boundary specified (i.e. the start of the interval is not null and not the minimum DateTime value) */ define fluent function hasStart(period Interval&lt;DateTime&gt; ): not ( start of period is null or start of period = minimum DateTime ) /* @description: Given an interval, returns true if the interval has an ending boundary specified (i.e. the end of the interval is not null and not the maximum DateTime value) */ define function &quot;HasEnd&quot;(period Interval&lt;DateTime&gt; ): not ( end of period is null or end of period = maximum DateTime ) /* @description: Given an interval, returns true if the interval has an ending boundary specified (i.e. the end of the interval is not null and not the maximum DateTime value) */ define fluent function hasEnd(period Interval&lt;DateTime&gt; ): not ( end of period is null or end of period = maximum DateTime ) /* @description: Given an interval, returns the ending point if the interval has an ending boundary specified, otherwise, returns the starting point */ define function &quot;Latest&quot;(choice Choice&lt;DateTime, Quantity, Interval&lt;DateTime&gt;, Interval&lt;Quantity&gt;&gt; ): (choice.toInterval()) period return if (HasEnd(period)) then end of period else start of period /* @description: Given an interval, returns the ending point if the interval has an ending boundary specified, otherwise, returns the starting point */ define fluent function latest(choice Choice&lt;DateTime, Quantity, Interval&lt;DateTime&gt;, Interval&lt;Quantity&gt;&gt; ): (choice.toInterval()) period return if (HasEnd(period)) then end of period else start of period /* @description: Given an interval, return the starting point if the interval has a starting boundary specified, otherwise, return the ending point */ define function &quot;Earliest&quot;(choice Choice&lt;DateTime, Quantity, Interval&lt;DateTime&gt;, Interval&lt;Quantity&gt;&gt; ): (choice.toInterval()) period return if (HasStart(period)) then start of period else end of period /* @description: Given an interval, return the starting point if the interval has a starting boundary specified, otherwise, return the ending point */ define fluent function earliest(choice Choice&lt;DateTime, Quantity, Interval&lt;DateTime&gt;, Interval&lt;Quantity&gt;&gt; ): (choice.toInterval()) period return if (HasStart(period)) then start of period else end of period /* @description: Creates a list of integers from 1 to how many days are in the interval. Note, this wont create an index for the final day if it is less than 24 hours. This also includes the first 24 hour period. */ define function &quot;Interval To Day Numbers&quot;(Period Interval&lt;DateTime&gt;): ( expand { Interval[1, duration in days between start of Period and end of Period]} ) DayNumber return end of DayNumber /* @description: Creates a list of integers from 1 to how many days are in the interval. Note, this wont create an index for the final day if it is less than 24 hours. This also includes the first 24 hour period. */ define fluent function toDayNumbers(Period Interval&lt;DateTime&gt;): ( expand { Interval[1, duration in days between start of Period and end of Period]} ) DayNumber return end of DayNumber /* @description: Creates a list of 24 hour long intervals in an interval paired with the index (1 indexed) to which 24 hour interval it is. Note that the result will include intervals that are closed at the beginning and open at the end */ define function &quot;Days In Period&quot;(Period Interval&lt;DateTime&gt;): ( &quot;Interval To Day Numbers&quot;(Period)) DayIndex let startPeriod: start of Period + (24 hours * (DayIndex - 1)), endPeriod: if (hours between startPeriod and end of Period &lt; 24) then startPeriod else start of Period + (24 hours * DayIndex) return Tuple { dayIndex: DayIndex, dayPeriod: Interval[startPeriod, endPeriod) } /* @description: Creates a list of 24 hour long intervals in an interval paired with the index (1 indexed) to which 24 hour interval it is. Note that the result will include intervals that are closed at the beginning and open at the end */ define fluent function daysInPeriod(Period Interval&lt;DateTime&gt;): ( &quot;Interval To Day Numbers&quot;(Period)) DayIndex let startPeriod: start of Period + (24 hours * (DayIndex - 1)), endPeriod: if (hours between startPeriod and end of Period &lt; 24) then startPeriod else start of Period + (24 hours * DayIndex) return Tuple { dayIndex: DayIndex, dayPeriod: Interval[startPeriod, endPeriod) }````: **Name: **
  * ?: QICoreCommon
* * **Content: **text/cql: ````/* @author: Stan Rankins @description: Common terminologies and functions used in QI-Core-based CQL artifacts @update: Fashioned after FHIRCommon Version 4.0.012 for use in ecqm-content-qicore-2022 repos */ library QICoreCommon version '1.0.000' using QICore version '4.1.1' include FHIRHelpers version '4.0.013' codesystem &quot;LOINC&quot;: 'http://loinc.org' codesystem &quot;SNOMEDCT&quot;: 'http://snomed.info/sct' codesystem &quot;ICD10CM&quot;: 'http://hl7.org/fhir/sid/icd-10-cm' codesystem &quot;RoleCode&quot;: 'http://terminology.hl7.org/CodeSystem/v3-RoleCode' codesystem &quot;Diagnosis Role&quot;: 'http://terminology.hl7.org/CodeSystem/diagnosis-role' codesystem &quot;RequestIntent&quot;: 'http://terminology.hl7.org/CodeSystem/request-intent' codesystem &quot;MedicationRequestCategory&quot;: 'http://terminology.hl7.org/CodeSystem/medicationrequest-category' codesystem &quot;ConditionClinicalStatusCodes&quot;: 'http://terminology.hl7.org/CodeSystem/condition-clinical' codesystem &quot;ConditionVerificationStatusCodes&quot;: 'http://terminology.hl7.org/CodeSystem/condition-ver-status' codesystem &quot;AllergyIntoleranceClinicalStatusCodes&quot;: 'http://terminology.hl7.org/CodeSystem/allergyintolerance-clinical' codesystem &quot;AllergyIntoleranceVerificationStatusCodes&quot;: 'http://terminology.hl7.org/CodeSystem/allergyintolerance-verification' codesystem &quot;ConditionCategoryCodes&quot;: 'http://terminology.hl7.org/CodeSystem/condition-category' codesystem &quot;ObservationCategoryCodes&quot;: 'http://terminology.hl7.org/CodeSystem/observation-category' valueset &quot;Active Condition&quot;: 'http://fhir.org/guides/cqf/common/ValueSet/active-condition' valueset &quot;Inactive Condition&quot;: 'http://fhir.org/guides/cqf/common/ValueSet/inactive-condition' code &quot;Birthdate&quot;: '21112-8' from &quot;LOINC&quot; display 'Birth date' code &quot;Dead&quot;: '419099009' from &quot;SNOMEDCT&quot; display 'Dead' code &quot;ER&quot;: 'ER' from &quot;RoleCode&quot; display 'Emergency room' code &quot;ICU&quot;: 'ICU' from &quot;RoleCode&quot; display 'Intensive care unit' code &quot;Billing&quot;: 'billing' from &quot;Diagnosis Role&quot; display 'Billing' // Condition Clinical Status Codes - Consider value sets for these code &quot;active&quot;: 'active' from &quot;ConditionClinicalStatusCodes&quot; code &quot;recurrence&quot;: 'recurrence' from &quot;ConditionClinicalStatusCodes&quot; code &quot;relapse&quot;: 'relapse' from &quot;ConditionClinicalStatusCodes&quot; code &quot;inactive&quot;: 'inactive' from &quot;ConditionClinicalStatusCodes&quot; code &quot;remission&quot;: 'remission' from &quot;ConditionClinicalStatusCodes&quot; code &quot;resolved&quot;: 'resolved' from &quot;ConditionClinicalStatusCodes&quot; // Condition Verification Status Codes - Consider value sets for these code &quot;unconfirmed&quot;: 'unconfirmed' from ConditionVerificationStatusCodes code &quot;provisional&quot;: 'provisional' from ConditionVerificationStatusCodes code &quot;differential&quot;: 'differential' from ConditionVerificationStatusCodes code &quot;confirmed&quot;: 'confirmed' from ConditionVerificationStatusCodes code &quot;refuted&quot;: 'refuted' from ConditionVerificationStatusCodes code &quot;entered-in-error&quot;: 'entered-in-error' from ConditionVerificationStatusCodes code &quot;allergy-active&quot;: 'active' from &quot;AllergyIntoleranceClinicalStatusCodes&quot; code &quot;allergy-inactive&quot;: 'inactive' from &quot;AllergyIntoleranceClinicalStatusCodes&quot; code &quot;allergy-resolved&quot;: 'resolved' from &quot;AllergyIntoleranceClinicalStatusCodes&quot; // Allergy/Intolerance Verification Status Codes - Consider value sets for these code &quot;allergy-unconfirmed&quot;: 'unconfirmed' from AllergyIntoleranceVerificationStatusCodes code &quot;allergy-confirmed&quot;: 'confirmed' from AllergyIntoleranceVerificationStatusCodes code &quot;allergy-refuted&quot;: 'refuted' from AllergyIntoleranceVerificationStatusCodes // MedicationRequest Category Codes code &quot;Community&quot;: 'community' from &quot;MedicationRequestCategory&quot; display 'Community' code &quot;Discharge&quot;: 'discharge' from &quot;MedicationRequestCategory&quot; display 'Discharge' // Diagnosis Role Codes code &quot;AD&quot;: 'AD' from &quot;Diagnosis Role&quot; display 'Admission diagnosis' code &quot;DD&quot;: 'DD' from &quot;Diagnosis Role&quot; display 'Discharge diagnosis' code &quot;CC&quot;: 'CC' from &quot;Diagnosis Role&quot; display 'Chief complaint' code &quot;CM&quot;: 'CM' from &quot;Diagnosis Role&quot; display 'Comorbidity diagnosis' code &quot;pre-op&quot;: 'pre-op' from &quot;Diagnosis Role&quot; display 'pre-op diagnosis' code &quot;post-op&quot;: 'post-op' from &quot;Diagnosis Role&quot; display 'post-op diagnosis' code &quot;billing&quot;: 'billing' from &quot;Diagnosis Role&quot; display 'billing diagnosis' // Observation Category Codes code &quot;social-history&quot;: 'social-history' from &quot;ObservationCategoryCodes&quot; display 'Social History' code &quot;vital-signs&quot;: 'vital-signs' from &quot;ObservationCategoryCodes&quot; display 'Vital Signs' code &quot;imaging&quot;: 'imaging' from &quot;ObservationCategoryCodes&quot; display 'Imaging' code &quot;laboratory&quot;: 'laboratory' from &quot;ObservationCategoryCodes&quot; display 'Laboratory' code &quot;procedure&quot;: 'procedure' from &quot;ObservationCategoryCodes&quot; display 'Procedure' code &quot;survey&quot;: 'survey' from &quot;ObservationCategoryCodes&quot; display 'Survey' code &quot;exam&quot;: 'exam' from &quot;ObservationCategoryCodes&quot; display 'Exam' code &quot;therapy&quot;: 'therapy' from &quot;ObservationCategoryCodes&quot; display 'Therapy' code &quot;activity&quot;: 'activity' from &quot;ObservationCategoryCodes&quot; display 'Activity' // Condition Category Codes code &quot;problem-list-item&quot;: 'problem-list-item' from &quot;ConditionCategoryCodes&quot; display 'Problem List Item' code &quot;encounter-diagnosis&quot;: 'encounter-diagnosis' from &quot;ConditionCategoryCodes&quot; display 'Encounter Diagnosis' context Patient /* @description: Normalizes a value that is a choice of timing-valued types to an equivalent interval @comment: Normalizes a choice type of DateTime, Quanitty, Interval&lt;DateTime&gt;, or Interval&lt;Quantity&gt; types to an equivalent interval. This selection of choice types is a superset of the majority of choice types that are used as possible representations for timing-valued elements in QICore, allowing this function to be used across any resource. The input can be provided as a DateTime, Quantity, Interval&lt;DateTime&gt; or Interval&lt;Quantity&gt;. The intent of this function is to provide a clear and concise mechanism to treat single elements that have multiple possible representations as intervals so that logic doesn't have to account for the variability. More complex calculations (such as medication request period or dispense period calculation) need specific guidance and consideration. That guidance may make use of this function, but the focus of this function is on single element calculations where the semantics are unambiguous. If the input is a DateTime, the result a DateTime Interval beginning and ending on that DateTime. If the input is a Quantity, the quantity is expected to be a calendar-duration interpreted as an Age, and the result is a DateTime Interval beginning on the Date the patient turned that age and ending immediately before one year later. If the input is a DateTime Interval, the result is the input. If the input is a Quantity Interval, the quantities are expected to be calendar-durations interpreted as an Age, and the result is a DateTime Interval beginning on the date the patient turned the age given as the start of the quantity interval, and ending immediately before one year later than the date the patient turned the age given as the end of the quantity interval. Any other input will reslt in a null DateTime Interval */ define function ToInterval(choice Choice&lt;DateTime, Quantity, Interval&lt;DateTime&gt;, Interval&lt;Quantity&gt;&gt;): case when choice is DateTime then Interval[choice as DateTime, choice as DateTime] when choice is Interval&lt;DateTime&gt; then choice as Interval&lt;DateTime&gt; when choice is Quantity then Interval[Patient.birthDate + (choice as Quantity), Patient.birthDate + (choice as Quantity) + 1 year) when choice is Interval&lt;Quantity&gt; then Interval[Patient.birthDate + (choice.low as Quantity), Patient.birthDate + (choice.high as Quantity) + 1 year) else null as Interval&lt;DateTime&gt; end /* @description: Normalizes a value that is a choice of timing-valued types to an equivalent interval @comment: Normalizes a choice type of DateTime, Quanitty, Interval&lt;DateTime&gt;, or Interval&lt;Quantity&gt; types to an equivalent interval. This selection of choice types is a superset of the majority of choice types that are used as possible representations for timing-valued elements in QICore, allowing this function to be used across any resource. The input can be provided as a DateTime, Quantity, Interval&lt;DateTime&gt; or Interval&lt;Quantity&gt;. The intent of this function is to provide a clear and concise mechanism to treat single elements that have multiple possible representations as intervals so that logic doesn't have to account for the variability. More complex calculations (such as medication request period or dispense period calculation) need specific guidance and consideration. That guidance may make use of this function, but the focus of this function is on single element calculations where the semantics are unambiguous. If the input is a DateTime, the result a DateTime Interval beginning and ending on that DateTime. If the input is a Quantity, the quantity is expected to be a calendar-duration interpreted as an Age, and the result is a DateTime Interval beginning on the Date the patient turned that age and ending immediately before one year later. If the input is a DateTime Interval, the result is the input. If the input is a Quantity Interval, the quantities are expected to be calendar-durations interpreted as an Age, and the result is a DateTime Interval beginning on the date the patient turned the age given as the start of the quantity interval, and ending immediately before one year later than the date the patient turned the age given as the end of the quantity interval. Any other input will reslt in a null DateTime Interval */ define fluent function toInterval(choice Choice&lt;DateTime, Quantity, Interval&lt;DateTime&gt;, Interval&lt;Quantity&gt;&gt;): case when choice is DateTime then Interval[choice as DateTime, choice as DateTime] when choice is Interval&lt;DateTime&gt; then choice as Interval&lt;DateTime&gt; when choice is Quantity then Interval[Patient.birthDate + (choice as Quantity), Patient.birthDate + (choice as Quantity) + 1 year) when choice is Interval&lt;Quantity&gt; then Interval[Patient.birthDate + (choice.low as Quantity), Patient.birthDate + (choice.high as Quantity) + 1 year) else null as Interval&lt;DateTime&gt; end /* @description: Returns an interval representing the normalized abatement of a given Condition. @comment: If the abatement element of the Condition is represented as a DateTime, the result is an interval beginning and ending on that DateTime. If the abatement is represented as a Quantity, the quantity is expected to be a calendar-duration and is interpreted as the age of the patient. The result is an interval from the date the patient turned that age to immediately before one year later. If the abatement is represented as a Quantity Interval, the quantities are expected to be calendar-durations and are interpreted as an age range during which the abatement occurred. The result is an interval from the date the patient turned the starting age of the quantity interval, and ending immediately before one year later than the date the patient turned the ending age of the quantity interval. */ define function ToAbatementInterval(condition Condition): if condition.abatement is DateTime then Interval[condition.abatement as DateTime, condition.abatement as DateTime] else if condition.abatement is Quantity then Interval[Patient.birthDate + (condition.abatement as Quantity), Patient.birthDate + (condition.abatement as Quantity) + 1 year) else if condition.abatement is Interval&lt;Quantity&gt; then Interval[Patient.birthDate + (condition.abatement.low as Quantity), Patient.birthDate + (condition.abatement.high as Quantity) + 1 year) else if condition.abatement is Interval&lt;DateTime&gt; then Interval[condition.abatement.low, condition.abatement.high) else null as Interval&lt;DateTime&gt; /* @description: Returns an interval representing the normalized abatement of a given Condition. @comment: If the abatement element of the Condition is represented as a DateTime, the result is an interval beginning and ending on that DateTime. If the abatement is represented as a Quantity, the quantity is expected to be a calendar-duration and is interpreted as the age of the patient. The result is an interval from the date the patient turned that age to immediately before one year later. If the abatement is represented as a Quantity Interval, the quantities are expected to be calendar-durations and are interpreted as an age range during which the abatement occurred. The result is an interval from the date the patient turned the starting age of the quantity interval, and ending immediately before one year later than the date the patient turned the ending age of the quantity interval. */ define fluent function toAbatementInterval(condition Condition): if condition.abatement is DateTime then Interval[condition.abatement as DateTime, condition.abatement as DateTime] else if condition.abatement is Quantity then Interval[Patient.birthDate + (condition.abatement as Quantity), Patient.birthDate + (condition.abatement as Quantity) + 1 year) else if condition.abatement is Interval&lt;Quantity&gt; then Interval[Patient.birthDate + (condition.abatement.low as Quantity), Patient.birthDate + (condition.abatement.high as Quantity) + 1 year) else if condition.abatement is Interval&lt;DateTime&gt; then Interval[condition.abatement.low, condition.abatement.high) else null as Interval&lt;DateTime&gt; /* @description: Returns an interval representing the normalized prevalence period of a given Condition. @comment: Uses the ToInterval and ToAbatementInterval functions to determine the widest potential interval from onset to abatement as specified in the given Condition. If the condition is active, the resulting interval will have a closed ending boundary. If the condition is not active, the resulting interval will have an open ending boundary. */ define function ToPrevalenceInterval(condition Condition): if condition.clinicalStatus ~ &quot;active&quot; or condition.clinicalStatus ~ &quot;recurrence&quot; or condition.clinicalStatus ~ &quot;relapse&quot; then Interval[start of ToInterval(condition.onset), end of ToAbatementInterval(condition)] else Interval[start of ToInterval(condition.onset), end of ToAbatementInterval(condition)) /* @description: Returns an interval representing the normalized prevalence period of a given Condition. @comment: Uses the ToInterval and ToAbatementInterval functions to determine the widest potential interval from onset to abatement as specified in the given Condition. If the condition is active, the resulting interval will have a closed ending boundary. If the condition is not active, the resulting interval will have an open ending boundary. */ define fluent function toPrevalenceInterval(condition Condition): if condition.clinicalStatus ~ &quot;active&quot; or condition.clinicalStatus ~ &quot;recurrence&quot; or condition.clinicalStatus ~ &quot;relapse&quot; then Interval[start of ToInterval(condition.onset), end of ToAbatementInterval(condition)] else Interval[start of ToInterval(condition.onset), end of ToAbatementInterval(condition)) /* @description: Returns the tail of the given uri (i.e. everything after the last slash in the URI). @comment: This function can be used to determine the logical id of a given resource. It can be used in a single-server environment to trace references. However, this function does not attempt to resolve or distinguish the base of the given url, and so cannot be used safely in multi-server environments. */ define function GetId(uri String ): Last(Split(uri, '/')) /* @description: Returns the tail of the given uri (i.e. everything after the last slash in the URI). @comment: This function can be used to determine the logical id of a given resource. It can be used in a single-server environment to trace references. However, this function does not attempt to resolve or distinguish the base of the given url, and so cannot be used safely in multi-server environments. */ define fluent function getId(uri String): Last(Split(uri, '/')) /* @description: Given an interval, return true if the interval has a starting boundary specified (i.e. the start of the interval is not null and not the minimum DateTime value) */ define function &quot;HasStart&quot;(period Interval&lt;DateTime&gt; ): not ( start of period is null or start of period = minimum DateTime ) /* @description: Given an interval, return true if the interval has a starting boundary specified (i.e. the start of the interval is not null and not the minimum DateTime value) */ define fluent function hasStart(period Interval&lt;DateTime&gt; ): not ( start of period is null or start of period = minimum DateTime ) /* @description: Given an interval, returns true if the interval has an ending boundary specified (i.e. the end of the interval is not null and not the maximum DateTime value) */ define function &quot;HasEnd&quot;(period Interval&lt;DateTime&gt; ): not ( end of period is null or end of period = maximum DateTime ) /* @description: Given an interval, returns true if the interval has an ending boundary specified (i.e. the end of the interval is not null and not the maximum DateTime value) */ define fluent function hasEnd(period Interval&lt;DateTime&gt; ): not ( end of period is null or end of period = maximum DateTime ) /* @description: Given an interval, returns the ending point if the interval has an ending boundary specified, otherwise, returns the starting point */ define function &quot;Latest&quot;(choice Choice&lt;DateTime, Quantity, Interval&lt;DateTime&gt;, Interval&lt;Quantity&gt;&gt; ): (choice.toInterval()) period return if (HasEnd(period)) then end of period else start of period /* @description: Given an interval, returns the ending point if the interval has an ending boundary specified, otherwise, returns the starting point */ define fluent function latest(choice Choice&lt;DateTime, Quantity, Interval&lt;DateTime&gt;, Interval&lt;Quantity&gt;&gt; ): (choice.toInterval()) period return if (HasEnd(period)) then end of period else start of period /* @description: Given an interval, return the starting point if the interval has a starting boundary specified, otherwise, return the ending point */ define function &quot;Earliest&quot;(choice Choice&lt;DateTime, Quantity, Interval&lt;DateTime&gt;, Interval&lt;Quantity&gt;&gt; ): (choice.toInterval()) period return if (HasStart(period)) then start of period else end of period /* @description: Given an interval, return the starting point if the interval has a starting boundary specified, otherwise, return the ending point */ define fluent function earliest(choice Choice&lt;DateTime, Quantity, Interval&lt;DateTime&gt;, Interval&lt;Quantity&gt;&gt; ): (choice.toInterval()) period return if (HasStart(period)) then start of period else end of period /* @description: Creates a list of integers from 1 to how many days are in the interval. Note, this wont create an index for the final day if it is less than 24 hours. This also includes the first 24 hour period. */ define function &quot;Interval To Day Numbers&quot;(Period Interval&lt;DateTime&gt;): ( expand { Interval[1, duration in days between start of Period and end of Period]} ) DayNumber return end of DayNumber /* @description: Creates a list of integers from 1 to how many days are in the interval. Note, this wont create an index for the final day if it is less than 24 hours. This also includes the first 24 hour period. */ define fluent function toDayNumbers(Period Interval&lt;DateTime&gt;): ( expand { Interval[1, duration in days between start of Period and end of Period]} ) DayNumber return end of DayNumber /* @description: Creates a list of 24 hour long intervals in an interval paired with the index (1 indexed) to which 24 hour interval it is. Note that the result will include intervals that are closed at the beginning and open at the end */ define function &quot;Days In Period&quot;(Period Interval&lt;DateTime&gt;): ( &quot;Interval To Day Numbers&quot;(Period)) DayIndex let startPeriod: start of Period + (24 hours * (DayIndex - 1)), endPeriod: if (hours between startPeriod and end of Period &lt; 24) then startPeriod else start of Period + (24 hours * DayIndex) return Tuple { dayIndex: DayIndex, dayPeriod: Interval[startPeriod, endPeriod) } /* @description: Creates a list of 24 hour long intervals in an interval paired with the index (1 indexed) to which 24 hour interval it is. Note that the result will include intervals that are closed at the beginning and open at the end */ define fluent function daysInPeriod(Period Interval&lt;DateTime&gt;): ( &quot;Interval To Day Numbers&quot;(Period)) DayIndex let startPeriod: start of Period + (24 hours * (DayIndex - 1)), endPeriod: if (hours between startPeriod and end of Period &lt; 24) then startPeriod else start of Period + (24 hours * DayIndex) return Tuple { dayIndex: DayIndex, dayPeriod: Interval[startPeriod, endPeriod) }````: **Title: **
  * ?: QiCore Common
* * **Content: **text/cql: ````/* @author: Stan Rankins @description: Common terminologies and functions used in QI-Core-based CQL artifacts @update: Fashioned after FHIRCommon Version 4.0.012 for use in ecqm-content-qicore-2022 repos */ library QICoreCommon version '1.0.000' using QICore version '4.1.1' include FHIRHelpers version '4.0.013' codesystem &quot;LOINC&quot;: 'http://loinc.org' codesystem &quot;SNOMEDCT&quot;: 'http://snomed.info/sct' codesystem &quot;ICD10CM&quot;: 'http://hl7.org/fhir/sid/icd-10-cm' codesystem &quot;RoleCode&quot;: 'http://terminology.hl7.org/CodeSystem/v3-RoleCode' codesystem &quot;Diagnosis Role&quot;: 'http://terminology.hl7.org/CodeSystem/diagnosis-role' codesystem &quot;RequestIntent&quot;: 'http://terminology.hl7.org/CodeSystem/request-intent' codesystem &quot;MedicationRequestCategory&quot;: 'http://terminology.hl7.org/CodeSystem/medicationrequest-category' codesystem &quot;ConditionClinicalStatusCodes&quot;: 'http://terminology.hl7.org/CodeSystem/condition-clinical' codesystem &quot;ConditionVerificationStatusCodes&quot;: 'http://terminology.hl7.org/CodeSystem/condition-ver-status' codesystem &quot;AllergyIntoleranceClinicalStatusCodes&quot;: 'http://terminology.hl7.org/CodeSystem/allergyintolerance-clinical' codesystem &quot;AllergyIntoleranceVerificationStatusCodes&quot;: 'http://terminology.hl7.org/CodeSystem/allergyintolerance-verification' codesystem &quot;ConditionCategoryCodes&quot;: 'http://terminology.hl7.org/CodeSystem/condition-category' codesystem &quot;ObservationCategoryCodes&quot;: 'http://terminology.hl7.org/CodeSystem/observation-category' valueset &quot;Active Condition&quot;: 'http://fhir.org/guides/cqf/common/ValueSet/active-condition' valueset &quot;Inactive Condition&quot;: 'http://fhir.org/guides/cqf/common/ValueSet/inactive-condition' code &quot;Birthdate&quot;: '21112-8' from &quot;LOINC&quot; display 'Birth date' code &quot;Dead&quot;: '419099009' from &quot;SNOMEDCT&quot; display 'Dead' code &quot;ER&quot;: 'ER' from &quot;RoleCode&quot; display 'Emergency room' code &quot;ICU&quot;: 'ICU' from &quot;RoleCode&quot; display 'Intensive care unit' code &quot;Billing&quot;: 'billing' from &quot;Diagnosis Role&quot; display 'Billing' // Condition Clinical Status Codes - Consider value sets for these code &quot;active&quot;: 'active' from &quot;ConditionClinicalStatusCodes&quot; code &quot;recurrence&quot;: 'recurrence' from &quot;ConditionClinicalStatusCodes&quot; code &quot;relapse&quot;: 'relapse' from &quot;ConditionClinicalStatusCodes&quot; code &quot;inactive&quot;: 'inactive' from &quot;ConditionClinicalStatusCodes&quot; code &quot;remission&quot;: 'remission' from &quot;ConditionClinicalStatusCodes&quot; code &quot;resolved&quot;: 'resolved' from &quot;ConditionClinicalStatusCodes&quot; // Condition Verification Status Codes - Consider value sets for these code &quot;unconfirmed&quot;: 'unconfirmed' from ConditionVerificationStatusCodes code &quot;provisional&quot;: 'provisional' from ConditionVerificationStatusCodes code &quot;differential&quot;: 'differential' from ConditionVerificationStatusCodes code &quot;confirmed&quot;: 'confirmed' from ConditionVerificationStatusCodes code &quot;refuted&quot;: 'refuted' from ConditionVerificationStatusCodes code &quot;entered-in-error&quot;: 'entered-in-error' from ConditionVerificationStatusCodes code &quot;allergy-active&quot;: 'active' from &quot;AllergyIntoleranceClinicalStatusCodes&quot; code &quot;allergy-inactive&quot;: 'inactive' from &quot;AllergyIntoleranceClinicalStatusCodes&quot; code &quot;allergy-resolved&quot;: 'resolved' from &quot;AllergyIntoleranceClinicalStatusCodes&quot; // Allergy/Intolerance Verification Status Codes - Consider value sets for these code &quot;allergy-unconfirmed&quot;: 'unconfirmed' from AllergyIntoleranceVerificationStatusCodes code &quot;allergy-confirmed&quot;: 'confirmed' from AllergyIntoleranceVerificationStatusCodes code &quot;allergy-refuted&quot;: 'refuted' from AllergyIntoleranceVerificationStatusCodes // MedicationRequest Category Codes code &quot;Community&quot;: 'community' from &quot;MedicationRequestCategory&quot; display 'Community' code &quot;Discharge&quot;: 'discharge' from &quot;MedicationRequestCategory&quot; display 'Discharge' // Diagnosis Role Codes code &quot;AD&quot;: 'AD' from &quot;Diagnosis Role&quot; display 'Admission diagnosis' code &quot;DD&quot;: 'DD' from &quot;Diagnosis Role&quot; display 'Discharge diagnosis' code &quot;CC&quot;: 'CC' from &quot;Diagnosis Role&quot; display 'Chief complaint' code &quot;CM&quot;: 'CM' from &quot;Diagnosis Role&quot; display 'Comorbidity diagnosis' code &quot;pre-op&quot;: 'pre-op' from &quot;Diagnosis Role&quot; display 'pre-op diagnosis' code &quot;post-op&quot;: 'post-op' from &quot;Diagnosis Role&quot; display 'post-op diagnosis' code &quot;billing&quot;: 'billing' from &quot;Diagnosis Role&quot; display 'billing diagnosis' // Observation Category Codes code &quot;social-history&quot;: 'social-history' from &quot;ObservationCategoryCodes&quot; display 'Social History' code &quot;vital-signs&quot;: 'vital-signs' from &quot;ObservationCategoryCodes&quot; display 'Vital Signs' code &quot;imaging&quot;: 'imaging' from &quot;ObservationCategoryCodes&quot; display 'Imaging' code &quot;laboratory&quot;: 'laboratory' from &quot;ObservationCategoryCodes&quot; display 'Laboratory' code &quot;procedure&quot;: 'procedure' from &quot;ObservationCategoryCodes&quot; display 'Procedure' code &quot;survey&quot;: 'survey' from &quot;ObservationCategoryCodes&quot; display 'Survey' code &quot;exam&quot;: 'exam' from &quot;ObservationCategoryCodes&quot; display 'Exam' code &quot;therapy&quot;: 'therapy' from &quot;ObservationCategoryCodes&quot; display 'Therapy' code &quot;activity&quot;: 'activity' from &quot;ObservationCategoryCodes&quot; display 'Activity' // Condition Category Codes code &quot;problem-list-item&quot;: 'problem-list-item' from &quot;ConditionCategoryCodes&quot; display 'Problem List Item' code &quot;encounter-diagnosis&quot;: 'encounter-diagnosis' from &quot;ConditionCategoryCodes&quot; display 'Encounter Diagnosis' context Patient /* @description: Normalizes a value that is a choice of timing-valued types to an equivalent interval @comment: Normalizes a choice type of DateTime, Quanitty, Interval&lt;DateTime&gt;, or Interval&lt;Quantity&gt; types to an equivalent interval. This selection of choice types is a superset of the majority of choice types that are used as possible representations for timing-valued elements in QICore, allowing this function to be used across any resource. The input can be provided as a DateTime, Quantity, Interval&lt;DateTime&gt; or Interval&lt;Quantity&gt;. The intent of this function is to provide a clear and concise mechanism to treat single elements that have multiple possible representations as intervals so that logic doesn't have to account for the variability. More complex calculations (such as medication request period or dispense period calculation) need specific guidance and consideration. That guidance may make use of this function, but the focus of this function is on single element calculations where the semantics are unambiguous. If the input is a DateTime, the result a DateTime Interval beginning and ending on that DateTime. If the input is a Quantity, the quantity is expected to be a calendar-duration interpreted as an Age, and the result is a DateTime Interval beginning on the Date the patient turned that age and ending immediately before one year later. If the input is a DateTime Interval, the result is the input. If the input is a Quantity Interval, the quantities are expected to be calendar-durations interpreted as an Age, and the result is a DateTime Interval beginning on the date the patient turned the age given as the start of the quantity interval, and ending immediately before one year later than the date the patient turned the age given as the end of the quantity interval. Any other input will reslt in a null DateTime Interval */ define function ToInterval(choice Choice&lt;DateTime, Quantity, Interval&lt;DateTime&gt;, Interval&lt;Quantity&gt;&gt;): case when choice is DateTime then Interval[choice as DateTime, choice as DateTime] when choice is Interval&lt;DateTime&gt; then choice as Interval&lt;DateTime&gt; when choice is Quantity then Interval[Patient.birthDate + (choice as Quantity), Patient.birthDate + (choice as Quantity) + 1 year) when choice is Interval&lt;Quantity&gt; then Interval[Patient.birthDate + (choice.low as Quantity), Patient.birthDate + (choice.high as Quantity) + 1 year) else null as Interval&lt;DateTime&gt; end /* @description: Normalizes a value that is a choice of timing-valued types to an equivalent interval @comment: Normalizes a choice type of DateTime, Quanitty, Interval&lt;DateTime&gt;, or Interval&lt;Quantity&gt; types to an equivalent interval. This selection of choice types is a superset of the majority of choice types that are used as possible representations for timing-valued elements in QICore, allowing this function to be used across any resource. The input can be provided as a DateTime, Quantity, Interval&lt;DateTime&gt; or Interval&lt;Quantity&gt;. The intent of this function is to provide a clear and concise mechanism to treat single elements that have multiple possible representations as intervals so that logic doesn't have to account for the variability. More complex calculations (such as medication request period or dispense period calculation) need specific guidance and consideration. That guidance may make use of this function, but the focus of this function is on single element calculations where the semantics are unambiguous. If the input is a DateTime, the result a DateTime Interval beginning and ending on that DateTime. If the input is a Quantity, the quantity is expected to be a calendar-duration interpreted as an Age, and the result is a DateTime Interval beginning on the Date the patient turned that age and ending immediately before one year later. If the input is a DateTime Interval, the result is the input. If the input is a Quantity Interval, the quantities are expected to be calendar-durations interpreted as an Age, and the result is a DateTime Interval beginning on the date the patient turned the age given as the start of the quantity interval, and ending immediately before one year later than the date the patient turned the age given as the end of the quantity interval. Any other input will reslt in a null DateTime Interval */ define fluent function toInterval(choice Choice&lt;DateTime, Quantity, Interval&lt;DateTime&gt;, Interval&lt;Quantity&gt;&gt;): case when choice is DateTime then Interval[choice as DateTime, choice as DateTime] when choice is Interval&lt;DateTime&gt; then choice as Interval&lt;DateTime&gt; when choice is Quantity then Interval[Patient.birthDate + (choice as Quantity), Patient.birthDate + (choice as Quantity) + 1 year) when choice is Interval&lt;Quantity&gt; then Interval[Patient.birthDate + (choice.low as Quantity), Patient.birthDate + (choice.high as Quantity) + 1 year) else null as Interval&lt;DateTime&gt; end /* @description: Returns an interval representing the normalized abatement of a given Condition. @comment: If the abatement element of the Condition is represented as a DateTime, the result is an interval beginning and ending on that DateTime. If the abatement is represented as a Quantity, the quantity is expected to be a calendar-duration and is interpreted as the age of the patient. The result is an interval from the date the patient turned that age to immediately before one year later. If the abatement is represented as a Quantity Interval, the quantities are expected to be calendar-durations and are interpreted as an age range during which the abatement occurred. The result is an interval from the date the patient turned the starting age of the quantity interval, and ending immediately before one year later than the date the patient turned the ending age of the quantity interval. */ define function ToAbatementInterval(condition Condition): if condition.abatement is DateTime then Interval[condition.abatement as DateTime, condition.abatement as DateTime] else if condition.abatement is Quantity then Interval[Patient.birthDate + (condition.abatement as Quantity), Patient.birthDate + (condition.abatement as Quantity) + 1 year) else if condition.abatement is Interval&lt;Quantity&gt; then Interval[Patient.birthDate + (condition.abatement.low as Quantity), Patient.birthDate + (condition.abatement.high as Quantity) + 1 year) else if condition.abatement is Interval&lt;DateTime&gt; then Interval[condition.abatement.low, condition.abatement.high) else null as Interval&lt;DateTime&gt; /* @description: Returns an interval representing the normalized abatement of a given Condition. @comment: If the abatement element of the Condition is represented as a DateTime, the result is an interval beginning and ending on that DateTime. If the abatement is represented as a Quantity, the quantity is expected to be a calendar-duration and is interpreted as the age of the patient. The result is an interval from the date the patient turned that age to immediately before one year later. If the abatement is represented as a Quantity Interval, the quantities are expected to be calendar-durations and are interpreted as an age range during which the abatement occurred. The result is an interval from the date the patient turned the starting age of the quantity interval, and ending immediately before one year later than the date the patient turned the ending age of the quantity interval. */ define fluent function toAbatementInterval(condition Condition): if condition.abatement is DateTime then Interval[condition.abatement as DateTime, condition.abatement as DateTime] else if condition.abatement is Quantity then Interval[Patient.birthDate + (condition.abatement as Quantity), Patient.birthDate + (condition.abatement as Quantity) + 1 year) else if condition.abatement is Interval&lt;Quantity&gt; then Interval[Patient.birthDate + (condition.abatement.low as Quantity), Patient.birthDate + (condition.abatement.high as Quantity) + 1 year) else if condition.abatement is Interval&lt;DateTime&gt; then Interval[condition.abatement.low, condition.abatement.high) else null as Interval&lt;DateTime&gt; /* @description: Returns an interval representing the normalized prevalence period of a given Condition. @comment: Uses the ToInterval and ToAbatementInterval functions to determine the widest potential interval from onset to abatement as specified in the given Condition. If the condition is active, the resulting interval will have a closed ending boundary. If the condition is not active, the resulting interval will have an open ending boundary. */ define function ToPrevalenceInterval(condition Condition): if condition.clinicalStatus ~ &quot;active&quot; or condition.clinicalStatus ~ &quot;recurrence&quot; or condition.clinicalStatus ~ &quot;relapse&quot; then Interval[start of ToInterval(condition.onset), end of ToAbatementInterval(condition)] else Interval[start of ToInterval(condition.onset), end of ToAbatementInterval(condition)) /* @description: Returns an interval representing the normalized prevalence period of a given Condition. @comment: Uses the ToInterval and ToAbatementInterval functions to determine the widest potential interval from onset to abatement as specified in the given Condition. If the condition is active, the resulting interval will have a closed ending boundary. If the condition is not active, the resulting interval will have an open ending boundary. */ define fluent function toPrevalenceInterval(condition Condition): if condition.clinicalStatus ~ &quot;active&quot; or condition.clinicalStatus ~ &quot;recurrence&quot; or condition.clinicalStatus ~ &quot;relapse&quot; then Interval[start of ToInterval(condition.onset), end of ToAbatementInterval(condition)] else Interval[start of ToInterval(condition.onset), end of ToAbatementInterval(condition)) /* @description: Returns the tail of the given uri (i.e. everything after the last slash in the URI). @comment: This function can be used to determine the logical id of a given resource. It can be used in a single-server environment to trace references. However, this function does not attempt to resolve or distinguish the base of the given url, and so cannot be used safely in multi-server environments. */ define function GetId(uri String ): Last(Split(uri, '/')) /* @description: Returns the tail of the given uri (i.e. everything after the last slash in the URI). @comment: This function can be used to determine the logical id of a given resource. It can be used in a single-server environment to trace references. However, this function does not attempt to resolve or distinguish the base of the given url, and so cannot be used safely in multi-server environments. */ define fluent function getId(uri String): Last(Split(uri, '/')) /* @description: Given an interval, return true if the interval has a starting boundary specified (i.e. the start of the interval is not null and not the minimum DateTime value) */ define function &quot;HasStart&quot;(period Interval&lt;DateTime&gt; ): not ( start of period is null or start of period = minimum DateTime ) /* @description: Given an interval, return true if the interval has a starting boundary specified (i.e. the start of the interval is not null and not the minimum DateTime value) */ define fluent function hasStart(period Interval&lt;DateTime&gt; ): not ( start of period is null or start of period = minimum DateTime ) /* @description: Given an interval, returns true if the interval has an ending boundary specified (i.e. the end of the interval is not null and not the maximum DateTime value) */ define function &quot;HasEnd&quot;(period Interval&lt;DateTime&gt; ): not ( end of period is null or end of period = maximum DateTime ) /* @description: Given an interval, returns true if the interval has an ending boundary specified (i.e. the end of the interval is not null and not the maximum DateTime value) */ define fluent function hasEnd(period Interval&lt;DateTime&gt; ): not ( end of period is null or end of period = maximum DateTime ) /* @description: Given an interval, returns the ending point if the interval has an ending boundary specified, otherwise, returns the starting point */ define function &quot;Latest&quot;(choice Choice&lt;DateTime, Quantity, Interval&lt;DateTime&gt;, Interval&lt;Quantity&gt;&gt; ): (choice.toInterval()) period return if (HasEnd(period)) then end of period else start of period /* @description: Given an interval, returns the ending point if the interval has an ending boundary specified, otherwise, returns the starting point */ define fluent function latest(choice Choice&lt;DateTime, Quantity, Interval&lt;DateTime&gt;, Interval&lt;Quantity&gt;&gt; ): (choice.toInterval()) period return if (HasEnd(period)) then end of period else start of period /* @description: Given an interval, return the starting point if the interval has a starting boundary specified, otherwise, return the ending point */ define function &quot;Earliest&quot;(choice Choice&lt;DateTime, Quantity, Interval&lt;DateTime&gt;, Interval&lt;Quantity&gt;&gt; ): (choice.toInterval()) period return if (HasStart(period)) then start of period else end of period /* @description: Given an interval, return the starting point if the interval has a starting boundary specified, otherwise, return the ending point */ define fluent function earliest(choice Choice&lt;DateTime, Quantity, Interval&lt;DateTime&gt;, Interval&lt;Quantity&gt;&gt; ): (choice.toInterval()) period return if (HasStart(period)) then start of period else end of period /* @description: Creates a list of integers from 1 to how many days are in the interval. Note, this wont create an index for the final day if it is less than 24 hours. This also includes the first 24 hour period. */ define function &quot;Interval To Day Numbers&quot;(Period Interval&lt;DateTime&gt;): ( expand { Interval[1, duration in days between start of Period and end of Period]} ) DayNumber return end of DayNumber /* @description: Creates a list of integers from 1 to how many days are in the interval. Note, this wont create an index for the final day if it is less than 24 hours. This also includes the first 24 hour period. */ define fluent function toDayNumbers(Period Interval&lt;DateTime&gt;): ( expand { Interval[1, duration in days between start of Period and end of Period]} ) DayNumber return end of DayNumber /* @description: Creates a list of 24 hour long intervals in an interval paired with the index (1 indexed) to which 24 hour interval it is. Note that the result will include intervals that are closed at the beginning and open at the end */ define function &quot;Days In Period&quot;(Period Interval&lt;DateTime&gt;): ( &quot;Interval To Day Numbers&quot;(Period)) DayIndex let startPeriod: start of Period + (24 hours * (DayIndex - 1)), endPeriod: if (hours between startPeriod and end of Period &lt; 24) then startPeriod else start of Period + (24 hours * DayIndex) return Tuple { dayIndex: DayIndex, dayPeriod: Interval[startPeriod, endPeriod) } /* @description: Creates a list of 24 hour long intervals in an interval paired with the index (1 indexed) to which 24 hour interval it is. Note that the result will include intervals that are closed at the beginning and open at the end */ define fluent function daysInPeriod(Period Interval&lt;DateTime&gt;): ( &quot;Interval To Day Numbers&quot;(Period)) DayIndex let startPeriod: start of Period + (24 hours * (DayIndex - 1)), endPeriod: if (hours between startPeriod and end of Period &lt; 24) then startPeriod else start of Period + (24 hours * DayIndex) return Tuple { dayIndex: DayIndex, dayPeriod: Interval[startPeriod, endPeriod) }````: **Status: **
  * ?: draft
* * **Content: **text/cql: ````/* @author: Stan Rankins @description: Common terminologies and functions used in QI-Core-based CQL artifacts @update: Fashioned after FHIRCommon Version 4.0.012 for use in ecqm-content-qicore-2022 repos */ library QICoreCommon version '1.0.000' using QICore version '4.1.1' include FHIRHelpers version '4.0.013' codesystem &quot;LOINC&quot;: 'http://loinc.org' codesystem &quot;SNOMEDCT&quot;: 'http://snomed.info/sct' codesystem &quot;ICD10CM&quot;: 'http://hl7.org/fhir/sid/icd-10-cm' codesystem &quot;RoleCode&quot;: 'http://terminology.hl7.org/CodeSystem/v3-RoleCode' codesystem &quot;Diagnosis Role&quot;: 'http://terminology.hl7.org/CodeSystem/diagnosis-role' codesystem &quot;RequestIntent&quot;: 'http://terminology.hl7.org/CodeSystem/request-intent' codesystem &quot;MedicationRequestCategory&quot;: 'http://terminology.hl7.org/CodeSystem/medicationrequest-category' codesystem &quot;ConditionClinicalStatusCodes&quot;: 'http://terminology.hl7.org/CodeSystem/condition-clinical' codesystem &quot;ConditionVerificationStatusCodes&quot;: 'http://terminology.hl7.org/CodeSystem/condition-ver-status' codesystem &quot;AllergyIntoleranceClinicalStatusCodes&quot;: 'http://terminology.hl7.org/CodeSystem/allergyintolerance-clinical' codesystem &quot;AllergyIntoleranceVerificationStatusCodes&quot;: 'http://terminology.hl7.org/CodeSystem/allergyintolerance-verification' codesystem &quot;ConditionCategoryCodes&quot;: 'http://terminology.hl7.org/CodeSystem/condition-category' codesystem &quot;ObservationCategoryCodes&quot;: 'http://terminology.hl7.org/CodeSystem/observation-category' valueset &quot;Active Condition&quot;: 'http://fhir.org/guides/cqf/common/ValueSet/active-condition' valueset &quot;Inactive Condition&quot;: 'http://fhir.org/guides/cqf/common/ValueSet/inactive-condition' code &quot;Birthdate&quot;: '21112-8' from &quot;LOINC&quot; display 'Birth date' code &quot;Dead&quot;: '419099009' from &quot;SNOMEDCT&quot; display 'Dead' code &quot;ER&quot;: 'ER' from &quot;RoleCode&quot; display 'Emergency room' code &quot;ICU&quot;: 'ICU' from &quot;RoleCode&quot; display 'Intensive care unit' code &quot;Billing&quot;: 'billing' from &quot;Diagnosis Role&quot; display 'Billing' // Condition Clinical Status Codes - Consider value sets for these code &quot;active&quot;: 'active' from &quot;ConditionClinicalStatusCodes&quot; code &quot;recurrence&quot;: 'recurrence' from &quot;ConditionClinicalStatusCodes&quot; code &quot;relapse&quot;: 'relapse' from &quot;ConditionClinicalStatusCodes&quot; code &quot;inactive&quot;: 'inactive' from &quot;ConditionClinicalStatusCodes&quot; code &quot;remission&quot;: 'remission' from &quot;ConditionClinicalStatusCodes&quot; code &quot;resolved&quot;: 'resolved' from &quot;ConditionClinicalStatusCodes&quot; // Condition Verification Status Codes - Consider value sets for these code &quot;unconfirmed&quot;: 'unconfirmed' from ConditionVerificationStatusCodes code &quot;provisional&quot;: 'provisional' from ConditionVerificationStatusCodes code &quot;differential&quot;: 'differential' from ConditionVerificationStatusCodes code &quot;confirmed&quot;: 'confirmed' from ConditionVerificationStatusCodes code &quot;refuted&quot;: 'refuted' from ConditionVerificationStatusCodes code &quot;entered-in-error&quot;: 'entered-in-error' from ConditionVerificationStatusCodes code &quot;allergy-active&quot;: 'active' from &quot;AllergyIntoleranceClinicalStatusCodes&quot; code &quot;allergy-inactive&quot;: 'inactive' from &quot;AllergyIntoleranceClinicalStatusCodes&quot; code &quot;allergy-resolved&quot;: 'resolved' from &quot;AllergyIntoleranceClinicalStatusCodes&quot; // Allergy/Intolerance Verification Status Codes - Consider value sets for these code &quot;allergy-unconfirmed&quot;: 'unconfirmed' from AllergyIntoleranceVerificationStatusCodes code &quot;allergy-confirmed&quot;: 'confirmed' from AllergyIntoleranceVerificationStatusCodes code &quot;allergy-refuted&quot;: 'refuted' from AllergyIntoleranceVerificationStatusCodes // MedicationRequest Category Codes code &quot;Community&quot;: 'community' from &quot;MedicationRequestCategory&quot; display 'Community' code &quot;Discharge&quot;: 'discharge' from &quot;MedicationRequestCategory&quot; display 'Discharge' // Diagnosis Role Codes code &quot;AD&quot;: 'AD' from &quot;Diagnosis Role&quot; display 'Admission diagnosis' code &quot;DD&quot;: 'DD' from &quot;Diagnosis Role&quot; display 'Discharge diagnosis' code &quot;CC&quot;: 'CC' from &quot;Diagnosis Role&quot; display 'Chief complaint' code &quot;CM&quot;: 'CM' from &quot;Diagnosis Role&quot; display 'Comorbidity diagnosis' code &quot;pre-op&quot;: 'pre-op' from &quot;Diagnosis Role&quot; display 'pre-op diagnosis' code &quot;post-op&quot;: 'post-op' from &quot;Diagnosis Role&quot; display 'post-op diagnosis' code &quot;billing&quot;: 'billing' from &quot;Diagnosis Role&quot; display 'billing diagnosis' // Observation Category Codes code &quot;social-history&quot;: 'social-history' from &quot;ObservationCategoryCodes&quot; display 'Social History' code &quot;vital-signs&quot;: 'vital-signs' from &quot;ObservationCategoryCodes&quot; display 'Vital Signs' code &quot;imaging&quot;: 'imaging' from &quot;ObservationCategoryCodes&quot; display 'Imaging' code &quot;laboratory&quot;: 'laboratory' from &quot;ObservationCategoryCodes&quot; display 'Laboratory' code &quot;procedure&quot;: 'procedure' from &quot;ObservationCategoryCodes&quot; display 'Procedure' code &quot;survey&quot;: 'survey' from &quot;ObservationCategoryCodes&quot; display 'Survey' code &quot;exam&quot;: 'exam' from &quot;ObservationCategoryCodes&quot; display 'Exam' code &quot;therapy&quot;: 'therapy' from &quot;ObservationCategoryCodes&quot; display 'Therapy' code &quot;activity&quot;: 'activity' from &quot;ObservationCategoryCodes&quot; display 'Activity' // Condition Category Codes code &quot;problem-list-item&quot;: 'problem-list-item' from &quot;ConditionCategoryCodes&quot; display 'Problem List Item' code &quot;encounter-diagnosis&quot;: 'encounter-diagnosis' from &quot;ConditionCategoryCodes&quot; display 'Encounter Diagnosis' context Patient /* @description: Normalizes a value that is a choice of timing-valued types to an equivalent interval @comment: Normalizes a choice type of DateTime, Quanitty, Interval&lt;DateTime&gt;, or Interval&lt;Quantity&gt; types to an equivalent interval. This selection of choice types is a superset of the majority of choice types that are used as possible representations for timing-valued elements in QICore, allowing this function to be used across any resource. The input can be provided as a DateTime, Quantity, Interval&lt;DateTime&gt; or Interval&lt;Quantity&gt;. The intent of this function is to provide a clear and concise mechanism to treat single elements that have multiple possible representations as intervals so that logic doesn't have to account for the variability. More complex calculations (such as medication request period or dispense period calculation) need specific guidance and consideration. That guidance may make use of this function, but the focus of this function is on single element calculations where the semantics are unambiguous. If the input is a DateTime, the result a DateTime Interval beginning and ending on that DateTime. If the input is a Quantity, the quantity is expected to be a calendar-duration interpreted as an Age, and the result is a DateTime Interval beginning on the Date the patient turned that age and ending immediately before one year later. If the input is a DateTime Interval, the result is the input. If the input is a Quantity Interval, the quantities are expected to be calendar-durations interpreted as an Age, and the result is a DateTime Interval beginning on the date the patient turned the age given as the start of the quantity interval, and ending immediately before one year later than the date the patient turned the age given as the end of the quantity interval. Any other input will reslt in a null DateTime Interval */ define function ToInterval(choice Choice&lt;DateTime, Quantity, Interval&lt;DateTime&gt;, Interval&lt;Quantity&gt;&gt;): case when choice is DateTime then Interval[choice as DateTime, choice as DateTime] when choice is Interval&lt;DateTime&gt; then choice as Interval&lt;DateTime&gt; when choice is Quantity then Interval[Patient.birthDate + (choice as Quantity), Patient.birthDate + (choice as Quantity) + 1 year) when choice is Interval&lt;Quantity&gt; then Interval[Patient.birthDate + (choice.low as Quantity), Patient.birthDate + (choice.high as Quantity) + 1 year) else null as Interval&lt;DateTime&gt; end /* @description: Normalizes a value that is a choice of timing-valued types to an equivalent interval @comment: Normalizes a choice type of DateTime, Quanitty, Interval&lt;DateTime&gt;, or Interval&lt;Quantity&gt; types to an equivalent interval. This selection of choice types is a superset of the majority of choice types that are used as possible representations for timing-valued elements in QICore, allowing this function to be used across any resource. The input can be provided as a DateTime, Quantity, Interval&lt;DateTime&gt; or Interval&lt;Quantity&gt;. The intent of this function is to provide a clear and concise mechanism to treat single elements that have multiple possible representations as intervals so that logic doesn't have to account for the variability. More complex calculations (such as medication request period or dispense period calculation) need specific guidance and consideration. That guidance may make use of this function, but the focus of this function is on single element calculations where the semantics are unambiguous. If the input is a DateTime, the result a DateTime Interval beginning and ending on that DateTime. If the input is a Quantity, the quantity is expected to be a calendar-duration interpreted as an Age, and the result is a DateTime Interval beginning on the Date the patient turned that age and ending immediately before one year later. If the input is a DateTime Interval, the result is the input. If the input is a Quantity Interval, the quantities are expected to be calendar-durations interpreted as an Age, and the result is a DateTime Interval beginning on the date the patient turned the age given as the start of the quantity interval, and ending immediately before one year later than the date the patient turned the age given as the end of the quantity interval. Any other input will reslt in a null DateTime Interval */ define fluent function toInterval(choice Choice&lt;DateTime, Quantity, Interval&lt;DateTime&gt;, Interval&lt;Quantity&gt;&gt;): case when choice is DateTime then Interval[choice as DateTime, choice as DateTime] when choice is Interval&lt;DateTime&gt; then choice as Interval&lt;DateTime&gt; when choice is Quantity then Interval[Patient.birthDate + (choice as Quantity), Patient.birthDate + (choice as Quantity) + 1 year) when choice is Interval&lt;Quantity&gt; then Interval[Patient.birthDate + (choice.low as Quantity), Patient.birthDate + (choice.high as Quantity) + 1 year) else null as Interval&lt;DateTime&gt; end /* @description: Returns an interval representing the normalized abatement of a given Condition. @comment: If the abatement element of the Condition is represented as a DateTime, the result is an interval beginning and ending on that DateTime. If the abatement is represented as a Quantity, the quantity is expected to be a calendar-duration and is interpreted as the age of the patient. The result is an interval from the date the patient turned that age to immediately before one year later. If the abatement is represented as a Quantity Interval, the quantities are expected to be calendar-durations and are interpreted as an age range during which the abatement occurred. The result is an interval from the date the patient turned the starting age of the quantity interval, and ending immediately before one year later than the date the patient turned the ending age of the quantity interval. */ define function ToAbatementInterval(condition Condition): if condition.abatement is DateTime then Interval[condition.abatement as DateTime, condition.abatement as DateTime] else if condition.abatement is Quantity then Interval[Patient.birthDate + (condition.abatement as Quantity), Patient.birthDate + (condition.abatement as Quantity) + 1 year) else if condition.abatement is Interval&lt;Quantity&gt; then Interval[Patient.birthDate + (condition.abatement.low as Quantity), Patient.birthDate + (condition.abatement.high as Quantity) + 1 year) else if condition.abatement is Interval&lt;DateTime&gt; then Interval[condition.abatement.low, condition.abatement.high) else null as Interval&lt;DateTime&gt; /* @description: Returns an interval representing the normalized abatement of a given Condition. @comment: If the abatement element of the Condition is represented as a DateTime, the result is an interval beginning and ending on that DateTime. If the abatement is represented as a Quantity, the quantity is expected to be a calendar-duration and is interpreted as the age of the patient. The result is an interval from the date the patient turned that age to immediately before one year later. If the abatement is represented as a Quantity Interval, the quantities are expected to be calendar-durations and are interpreted as an age range during which the abatement occurred. The result is an interval from the date the patient turned the starting age of the quantity interval, and ending immediately before one year later than the date the patient turned the ending age of the quantity interval. */ define fluent function toAbatementInterval(condition Condition): if condition.abatement is DateTime then Interval[condition.abatement as DateTime, condition.abatement as DateTime] else if condition.abatement is Quantity then Interval[Patient.birthDate + (condition.abatement as Quantity), Patient.birthDate + (condition.abatement as Quantity) + 1 year) else if condition.abatement is Interval&lt;Quantity&gt; then Interval[Patient.birthDate + (condition.abatement.low as Quantity), Patient.birthDate + (condition.abatement.high as Quantity) + 1 year) else if condition.abatement is Interval&lt;DateTime&gt; then Interval[condition.abatement.low, condition.abatement.high) else null as Interval&lt;DateTime&gt; /* @description: Returns an interval representing the normalized prevalence period of a given Condition. @comment: Uses the ToInterval and ToAbatementInterval functions to determine the widest potential interval from onset to abatement as specified in the given Condition. If the condition is active, the resulting interval will have a closed ending boundary. If the condition is not active, the resulting interval will have an open ending boundary. */ define function ToPrevalenceInterval(condition Condition): if condition.clinicalStatus ~ &quot;active&quot; or condition.clinicalStatus ~ &quot;recurrence&quot; or condition.clinicalStatus ~ &quot;relapse&quot; then Interval[start of ToInterval(condition.onset), end of ToAbatementInterval(condition)] else Interval[start of ToInterval(condition.onset), end of ToAbatementInterval(condition)) /* @description: Returns an interval representing the normalized prevalence period of a given Condition. @comment: Uses the ToInterval and ToAbatementInterval functions to determine the widest potential interval from onset to abatement as specified in the given Condition. If the condition is active, the resulting interval will have a closed ending boundary. If the condition is not active, the resulting interval will have an open ending boundary. */ define fluent function toPrevalenceInterval(condition Condition): if condition.clinicalStatus ~ &quot;active&quot; or condition.clinicalStatus ~ &quot;recurrence&quot; or condition.clinicalStatus ~ &quot;relapse&quot; then Interval[start of ToInterval(condition.onset), end of ToAbatementInterval(condition)] else Interval[start of ToInterval(condition.onset), end of ToAbatementInterval(condition)) /* @description: Returns the tail of the given uri (i.e. everything after the last slash in the URI). @comment: This function can be used to determine the logical id of a given resource. It can be used in a single-server environment to trace references. However, this function does not attempt to resolve or distinguish the base of the given url, and so cannot be used safely in multi-server environments. */ define function GetId(uri String ): Last(Split(uri, '/')) /* @description: Returns the tail of the given uri (i.e. everything after the last slash in the URI). @comment: This function can be used to determine the logical id of a given resource. It can be used in a single-server environment to trace references. However, this function does not attempt to resolve or distinguish the base of the given url, and so cannot be used safely in multi-server environments. */ define fluent function getId(uri String): Last(Split(uri, '/')) /* @description: Given an interval, return true if the interval has a starting boundary specified (i.e. the start of the interval is not null and not the minimum DateTime value) */ define function &quot;HasStart&quot;(period Interval&lt;DateTime&gt; ): not ( start of period is null or start of period = minimum DateTime ) /* @description: Given an interval, return true if the interval has a starting boundary specified (i.e. the start of the interval is not null and not the minimum DateTime value) */ define fluent function hasStart(period Interval&lt;DateTime&gt; ): not ( start of period is null or start of period = minimum DateTime ) /* @description: Given an interval, returns true if the interval has an ending boundary specified (i.e. the end of the interval is not null and not the maximum DateTime value) */ define function &quot;HasEnd&quot;(period Interval&lt;DateTime&gt; ): not ( end of period is null or end of period = maximum DateTime ) /* @description: Given an interval, returns true if the interval has an ending boundary specified (i.e. the end of the interval is not null and not the maximum DateTime value) */ define fluent function hasEnd(period Interval&lt;DateTime&gt; ): not ( end of period is null or end of period = maximum DateTime ) /* @description: Given an interval, returns the ending point if the interval has an ending boundary specified, otherwise, returns the starting point */ define function &quot;Latest&quot;(choice Choice&lt;DateTime, Quantity, Interval&lt;DateTime&gt;, Interval&lt;Quantity&gt;&gt; ): (choice.toInterval()) period return if (HasEnd(period)) then end of period else start of period /* @description: Given an interval, returns the ending point if the interval has an ending boundary specified, otherwise, returns the starting point */ define fluent function latest(choice Choice&lt;DateTime, Quantity, Interval&lt;DateTime&gt;, Interval&lt;Quantity&gt;&gt; ): (choice.toInterval()) period return if (HasEnd(period)) then end of period else start of period /* @description: Given an interval, return the starting point if the interval has a starting boundary specified, otherwise, return the ending point */ define function &quot;Earliest&quot;(choice Choice&lt;DateTime, Quantity, Interval&lt;DateTime&gt;, Interval&lt;Quantity&gt;&gt; ): (choice.toInterval()) period return if (HasStart(period)) then start of period else end of period /* @description: Given an interval, return the starting point if the interval has a starting boundary specified, otherwise, return the ending point */ define fluent function earliest(choice Choice&lt;DateTime, Quantity, Interval&lt;DateTime&gt;, Interval&lt;Quantity&gt;&gt; ): (choice.toInterval()) period return if (HasStart(period)) then start of period else end of period /* @description: Creates a list of integers from 1 to how many days are in the interval. Note, this wont create an index for the final day if it is less than 24 hours. This also includes the first 24 hour period. */ define function &quot;Interval To Day Numbers&quot;(Period Interval&lt;DateTime&gt;): ( expand { Interval[1, duration in days between start of Period and end of Period]} ) DayNumber return end of DayNumber /* @description: Creates a list of integers from 1 to how many days are in the interval. Note, this wont create an index for the final day if it is less than 24 hours. This also includes the first 24 hour period. */ define fluent function toDayNumbers(Period Interval&lt;DateTime&gt;): ( expand { Interval[1, duration in days between start of Period and end of Period]} ) DayNumber return end of DayNumber /* @description: Creates a list of 24 hour long intervals in an interval paired with the index (1 indexed) to which 24 hour interval it is. Note that the result will include intervals that are closed at the beginning and open at the end */ define function &quot;Days In Period&quot;(Period Interval&lt;DateTime&gt;): ( &quot;Interval To Day Numbers&quot;(Period)) DayIndex let startPeriod: start of Period + (24 hours * (DayIndex - 1)), endPeriod: if (hours between startPeriod and end of Period &lt; 24) then startPeriod else start of Period + (24 hours * DayIndex) return Tuple { dayIndex: DayIndex, dayPeriod: Interval[startPeriod, endPeriod) } /* @description: Creates a list of 24 hour long intervals in an interval paired with the index (1 indexed) to which 24 hour interval it is. Note that the result will include intervals that are closed at the beginning and open at the end */ define fluent function daysInPeriod(Period Interval&lt;DateTime&gt;): ( &quot;Interval To Day Numbers&quot;(Period)) DayIndex let startPeriod: start of Period + (24 hours * (DayIndex - 1)), endPeriod: if (hours between startPeriod and end of Period &lt; 24) then startPeriod else start of Period + (24 hours * DayIndex) return Tuple { dayIndex: DayIndex, dayPeriod: Interval[startPeriod, endPeriod) }````: **Date: **
  * ?: 2026-02-27 18:11:00+0000
* * **Content: **text/cql: ````/* @author: Stan Rankins @description: Common terminologies and functions used in QI-Core-based CQL artifacts @update: Fashioned after FHIRCommon Version 4.0.012 for use in ecqm-content-qicore-2022 repos */ library QICoreCommon version '1.0.000' using QICore version '4.1.1' include FHIRHelpers version '4.0.013' codesystem &quot;LOINC&quot;: 'http://loinc.org' codesystem &quot;SNOMEDCT&quot;: 'http://snomed.info/sct' codesystem &quot;ICD10CM&quot;: 'http://hl7.org/fhir/sid/icd-10-cm' codesystem &quot;RoleCode&quot;: 'http://terminology.hl7.org/CodeSystem/v3-RoleCode' codesystem &quot;Diagnosis Role&quot;: 'http://terminology.hl7.org/CodeSystem/diagnosis-role' codesystem &quot;RequestIntent&quot;: 'http://terminology.hl7.org/CodeSystem/request-intent' codesystem &quot;MedicationRequestCategory&quot;: 'http://terminology.hl7.org/CodeSystem/medicationrequest-category' codesystem &quot;ConditionClinicalStatusCodes&quot;: 'http://terminology.hl7.org/CodeSystem/condition-clinical' codesystem &quot;ConditionVerificationStatusCodes&quot;: 'http://terminology.hl7.org/CodeSystem/condition-ver-status' codesystem &quot;AllergyIntoleranceClinicalStatusCodes&quot;: 'http://terminology.hl7.org/CodeSystem/allergyintolerance-clinical' codesystem &quot;AllergyIntoleranceVerificationStatusCodes&quot;: 'http://terminology.hl7.org/CodeSystem/allergyintolerance-verification' codesystem &quot;ConditionCategoryCodes&quot;: 'http://terminology.hl7.org/CodeSystem/condition-category' codesystem &quot;ObservationCategoryCodes&quot;: 'http://terminology.hl7.org/CodeSystem/observation-category' valueset &quot;Active Condition&quot;: 'http://fhir.org/guides/cqf/common/ValueSet/active-condition' valueset &quot;Inactive Condition&quot;: 'http://fhir.org/guides/cqf/common/ValueSet/inactive-condition' code &quot;Birthdate&quot;: '21112-8' from &quot;LOINC&quot; display 'Birth date' code &quot;Dead&quot;: '419099009' from &quot;SNOMEDCT&quot; display 'Dead' code &quot;ER&quot;: 'ER' from &quot;RoleCode&quot; display 'Emergency room' code &quot;ICU&quot;: 'ICU' from &quot;RoleCode&quot; display 'Intensive care unit' code &quot;Billing&quot;: 'billing' from &quot;Diagnosis Role&quot; display 'Billing' // Condition Clinical Status Codes - Consider value sets for these code &quot;active&quot;: 'active' from &quot;ConditionClinicalStatusCodes&quot; code &quot;recurrence&quot;: 'recurrence' from &quot;ConditionClinicalStatusCodes&quot; code &quot;relapse&quot;: 'relapse' from &quot;ConditionClinicalStatusCodes&quot; code &quot;inactive&quot;: 'inactive' from &quot;ConditionClinicalStatusCodes&quot; code &quot;remission&quot;: 'remission' from &quot;ConditionClinicalStatusCodes&quot; code &quot;resolved&quot;: 'resolved' from &quot;ConditionClinicalStatusCodes&quot; // Condition Verification Status Codes - Consider value sets for these code &quot;unconfirmed&quot;: 'unconfirmed' from ConditionVerificationStatusCodes code &quot;provisional&quot;: 'provisional' from ConditionVerificationStatusCodes code &quot;differential&quot;: 'differential' from ConditionVerificationStatusCodes code &quot;confirmed&quot;: 'confirmed' from ConditionVerificationStatusCodes code &quot;refuted&quot;: 'refuted' from ConditionVerificationStatusCodes code &quot;entered-in-error&quot;: 'entered-in-error' from ConditionVerificationStatusCodes code &quot;allergy-active&quot;: 'active' from &quot;AllergyIntoleranceClinicalStatusCodes&quot; code &quot;allergy-inactive&quot;: 'inactive' from &quot;AllergyIntoleranceClinicalStatusCodes&quot; code &quot;allergy-resolved&quot;: 'resolved' from &quot;AllergyIntoleranceClinicalStatusCodes&quot; // Allergy/Intolerance Verification Status Codes - Consider value sets for these code &quot;allergy-unconfirmed&quot;: 'unconfirmed' from AllergyIntoleranceVerificationStatusCodes code &quot;allergy-confirmed&quot;: 'confirmed' from AllergyIntoleranceVerificationStatusCodes code &quot;allergy-refuted&quot;: 'refuted' from AllergyIntoleranceVerificationStatusCodes // MedicationRequest Category Codes code &quot;Community&quot;: 'community' from &quot;MedicationRequestCategory&quot; display 'Community' code &quot;Discharge&quot;: 'discharge' from &quot;MedicationRequestCategory&quot; display 'Discharge' // Diagnosis Role Codes code &quot;AD&quot;: 'AD' from &quot;Diagnosis Role&quot; display 'Admission diagnosis' code &quot;DD&quot;: 'DD' from &quot;Diagnosis Role&quot; display 'Discharge diagnosis' code &quot;CC&quot;: 'CC' from &quot;Diagnosis Role&quot; display 'Chief complaint' code &quot;CM&quot;: 'CM' from &quot;Diagnosis Role&quot; display 'Comorbidity diagnosis' code &quot;pre-op&quot;: 'pre-op' from &quot;Diagnosis Role&quot; display 'pre-op diagnosis' code &quot;post-op&quot;: 'post-op' from &quot;Diagnosis Role&quot; display 'post-op diagnosis' code &quot;billing&quot;: 'billing' from &quot;Diagnosis Role&quot; display 'billing diagnosis' // Observation Category Codes code &quot;social-history&quot;: 'social-history' from &quot;ObservationCategoryCodes&quot; display 'Social History' code &quot;vital-signs&quot;: 'vital-signs' from &quot;ObservationCategoryCodes&quot; display 'Vital Signs' code &quot;imaging&quot;: 'imaging' from &quot;ObservationCategoryCodes&quot; display 'Imaging' code &quot;laboratory&quot;: 'laboratory' from &quot;ObservationCategoryCodes&quot; display 'Laboratory' code &quot;procedure&quot;: 'procedure' from &quot;ObservationCategoryCodes&quot; display 'Procedure' code &quot;survey&quot;: 'survey' from &quot;ObservationCategoryCodes&quot; display 'Survey' code &quot;exam&quot;: 'exam' from &quot;ObservationCategoryCodes&quot; display 'Exam' code &quot;therapy&quot;: 'therapy' from &quot;ObservationCategoryCodes&quot; display 'Therapy' code &quot;activity&quot;: 'activity' from &quot;ObservationCategoryCodes&quot; display 'Activity' // Condition Category Codes code &quot;problem-list-item&quot;: 'problem-list-item' from &quot;ConditionCategoryCodes&quot; display 'Problem List Item' code &quot;encounter-diagnosis&quot;: 'encounter-diagnosis' from &quot;ConditionCategoryCodes&quot; display 'Encounter Diagnosis' context Patient /* @description: Normalizes a value that is a choice of timing-valued types to an equivalent interval @comment: Normalizes a choice type of DateTime, Quanitty, Interval&lt;DateTime&gt;, or Interval&lt;Quantity&gt; types to an equivalent interval. This selection of choice types is a superset of the majority of choice types that are used as possible representations for timing-valued elements in QICore, allowing this function to be used across any resource. The input can be provided as a DateTime, Quantity, Interval&lt;DateTime&gt; or Interval&lt;Quantity&gt;. The intent of this function is to provide a clear and concise mechanism to treat single elements that have multiple possible representations as intervals so that logic doesn't have to account for the variability. More complex calculations (such as medication request period or dispense period calculation) need specific guidance and consideration. That guidance may make use of this function, but the focus of this function is on single element calculations where the semantics are unambiguous. If the input is a DateTime, the result a DateTime Interval beginning and ending on that DateTime. If the input is a Quantity, the quantity is expected to be a calendar-duration interpreted as an Age, and the result is a DateTime Interval beginning on the Date the patient turned that age and ending immediately before one year later. If the input is a DateTime Interval, the result is the input. If the input is a Quantity Interval, the quantities are expected to be calendar-durations interpreted as an Age, and the result is a DateTime Interval beginning on the date the patient turned the age given as the start of the quantity interval, and ending immediately before one year later than the date the patient turned the age given as the end of the quantity interval. Any other input will reslt in a null DateTime Interval */ define function ToInterval(choice Choice&lt;DateTime, Quantity, Interval&lt;DateTime&gt;, Interval&lt;Quantity&gt;&gt;): case when choice is DateTime then Interval[choice as DateTime, choice as DateTime] when choice is Interval&lt;DateTime&gt; then choice as Interval&lt;DateTime&gt; when choice is Quantity then Interval[Patient.birthDate + (choice as Quantity), Patient.birthDate + (choice as Quantity) + 1 year) when choice is Interval&lt;Quantity&gt; then Interval[Patient.birthDate + (choice.low as Quantity), Patient.birthDate + (choice.high as Quantity) + 1 year) else null as Interval&lt;DateTime&gt; end /* @description: Normalizes a value that is a choice of timing-valued types to an equivalent interval @comment: Normalizes a choice type of DateTime, Quanitty, Interval&lt;DateTime&gt;, or Interval&lt;Quantity&gt; types to an equivalent interval. This selection of choice types is a superset of the majority of choice types that are used as possible representations for timing-valued elements in QICore, allowing this function to be used across any resource. The input can be provided as a DateTime, Quantity, Interval&lt;DateTime&gt; or Interval&lt;Quantity&gt;. The intent of this function is to provide a clear and concise mechanism to treat single elements that have multiple possible representations as intervals so that logic doesn't have to account for the variability. More complex calculations (such as medication request period or dispense period calculation) need specific guidance and consideration. That guidance may make use of this function, but the focus of this function is on single element calculations where the semantics are unambiguous. If the input is a DateTime, the result a DateTime Interval beginning and ending on that DateTime. If the input is a Quantity, the quantity is expected to be a calendar-duration interpreted as an Age, and the result is a DateTime Interval beginning on the Date the patient turned that age and ending immediately before one year later. If the input is a DateTime Interval, the result is the input. If the input is a Quantity Interval, the quantities are expected to be calendar-durations interpreted as an Age, and the result is a DateTime Interval beginning on the date the patient turned the age given as the start of the quantity interval, and ending immediately before one year later than the date the patient turned the age given as the end of the quantity interval. Any other input will reslt in a null DateTime Interval */ define fluent function toInterval(choice Choice&lt;DateTime, Quantity, Interval&lt;DateTime&gt;, Interval&lt;Quantity&gt;&gt;): case when choice is DateTime then Interval[choice as DateTime, choice as DateTime] when choice is Interval&lt;DateTime&gt; then choice as Interval&lt;DateTime&gt; when choice is Quantity then Interval[Patient.birthDate + (choice as Quantity), Patient.birthDate + (choice as Quantity) + 1 year) when choice is Interval&lt;Quantity&gt; then Interval[Patient.birthDate + (choice.low as Quantity), Patient.birthDate + (choice.high as Quantity) + 1 year) else null as Interval&lt;DateTime&gt; end /* @description: Returns an interval representing the normalized abatement of a given Condition. @comment: If the abatement element of the Condition is represented as a DateTime, the result is an interval beginning and ending on that DateTime. If the abatement is represented as a Quantity, the quantity is expected to be a calendar-duration and is interpreted as the age of the patient. The result is an interval from the date the patient turned that age to immediately before one year later. If the abatement is represented as a Quantity Interval, the quantities are expected to be calendar-durations and are interpreted as an age range during which the abatement occurred. The result is an interval from the date the patient turned the starting age of the quantity interval, and ending immediately before one year later than the date the patient turned the ending age of the quantity interval. */ define function ToAbatementInterval(condition Condition): if condition.abatement is DateTime then Interval[condition.abatement as DateTime, condition.abatement as DateTime] else if condition.abatement is Quantity then Interval[Patient.birthDate + (condition.abatement as Quantity), Patient.birthDate + (condition.abatement as Quantity) + 1 year) else if condition.abatement is Interval&lt;Quantity&gt; then Interval[Patient.birthDate + (condition.abatement.low as Quantity), Patient.birthDate + (condition.abatement.high as Quantity) + 1 year) else if condition.abatement is Interval&lt;DateTime&gt; then Interval[condition.abatement.low, condition.abatement.high) else null as Interval&lt;DateTime&gt; /* @description: Returns an interval representing the normalized abatement of a given Condition. @comment: If the abatement element of the Condition is represented as a DateTime, the result is an interval beginning and ending on that DateTime. If the abatement is represented as a Quantity, the quantity is expected to be a calendar-duration and is interpreted as the age of the patient. The result is an interval from the date the patient turned that age to immediately before one year later. If the abatement is represented as a Quantity Interval, the quantities are expected to be calendar-durations and are interpreted as an age range during which the abatement occurred. The result is an interval from the date the patient turned the starting age of the quantity interval, and ending immediately before one year later than the date the patient turned the ending age of the quantity interval. */ define fluent function toAbatementInterval(condition Condition): if condition.abatement is DateTime then Interval[condition.abatement as DateTime, condition.abatement as DateTime] else if condition.abatement is Quantity then Interval[Patient.birthDate + (condition.abatement as Quantity), Patient.birthDate + (condition.abatement as Quantity) + 1 year) else if condition.abatement is Interval&lt;Quantity&gt; then Interval[Patient.birthDate + (condition.abatement.low as Quantity), Patient.birthDate + (condition.abatement.high as Quantity) + 1 year) else if condition.abatement is Interval&lt;DateTime&gt; then Interval[condition.abatement.low, condition.abatement.high) else null as Interval&lt;DateTime&gt; /* @description: Returns an interval representing the normalized prevalence period of a given Condition. @comment: Uses the ToInterval and ToAbatementInterval functions to determine the widest potential interval from onset to abatement as specified in the given Condition. If the condition is active, the resulting interval will have a closed ending boundary. If the condition is not active, the resulting interval will have an open ending boundary. */ define function ToPrevalenceInterval(condition Condition): if condition.clinicalStatus ~ &quot;active&quot; or condition.clinicalStatus ~ &quot;recurrence&quot; or condition.clinicalStatus ~ &quot;relapse&quot; then Interval[start of ToInterval(condition.onset), end of ToAbatementInterval(condition)] else Interval[start of ToInterval(condition.onset), end of ToAbatementInterval(condition)) /* @description: Returns an interval representing the normalized prevalence period of a given Condition. @comment: Uses the ToInterval and ToAbatementInterval functions to determine the widest potential interval from onset to abatement as specified in the given Condition. If the condition is active, the resulting interval will have a closed ending boundary. If the condition is not active, the resulting interval will have an open ending boundary. */ define fluent function toPrevalenceInterval(condition Condition): if condition.clinicalStatus ~ &quot;active&quot; or condition.clinicalStatus ~ &quot;recurrence&quot; or condition.clinicalStatus ~ &quot;relapse&quot; then Interval[start of ToInterval(condition.onset), end of ToAbatementInterval(condition)] else Interval[start of ToInterval(condition.onset), end of ToAbatementInterval(condition)) /* @description: Returns the tail of the given uri (i.e. everything after the last slash in the URI). @comment: This function can be used to determine the logical id of a given resource. It can be used in a single-server environment to trace references. However, this function does not attempt to resolve or distinguish the base of the given url, and so cannot be used safely in multi-server environments. */ define function GetId(uri String ): Last(Split(uri, '/')) /* @description: Returns the tail of the given uri (i.e. everything after the last slash in the URI). @comment: This function can be used to determine the logical id of a given resource. It can be used in a single-server environment to trace references. However, this function does not attempt to resolve or distinguish the base of the given url, and so cannot be used safely in multi-server environments. */ define fluent function getId(uri String): Last(Split(uri, '/')) /* @description: Given an interval, return true if the interval has a starting boundary specified (i.e. the start of the interval is not null and not the minimum DateTime value) */ define function &quot;HasStart&quot;(period Interval&lt;DateTime&gt; ): not ( start of period is null or start of period = minimum DateTime ) /* @description: Given an interval, return true if the interval has a starting boundary specified (i.e. the start of the interval is not null and not the minimum DateTime value) */ define fluent function hasStart(period Interval&lt;DateTime&gt; ): not ( start of period is null or start of period = minimum DateTime ) /* @description: Given an interval, returns true if the interval has an ending boundary specified (i.e. the end of the interval is not null and not the maximum DateTime value) */ define function &quot;HasEnd&quot;(period Interval&lt;DateTime&gt; ): not ( end of period is null or end of period = maximum DateTime ) /* @description: Given an interval, returns true if the interval has an ending boundary specified (i.e. the end of the interval is not null and not the maximum DateTime value) */ define fluent function hasEnd(period Interval&lt;DateTime&gt; ): not ( end of period is null or end of period = maximum DateTime ) /* @description: Given an interval, returns the ending point if the interval has an ending boundary specified, otherwise, returns the starting point */ define function &quot;Latest&quot;(choice Choice&lt;DateTime, Quantity, Interval&lt;DateTime&gt;, Interval&lt;Quantity&gt;&gt; ): (choice.toInterval()) period return if (HasEnd(period)) then end of period else start of period /* @description: Given an interval, returns the ending point if the interval has an ending boundary specified, otherwise, returns the starting point */ define fluent function latest(choice Choice&lt;DateTime, Quantity, Interval&lt;DateTime&gt;, Interval&lt;Quantity&gt;&gt; ): (choice.toInterval()) period return if (HasEnd(period)) then end of period else start of period /* @description: Given an interval, return the starting point if the interval has a starting boundary specified, otherwise, return the ending point */ define function &quot;Earliest&quot;(choice Choice&lt;DateTime, Quantity, Interval&lt;DateTime&gt;, Interval&lt;Quantity&gt;&gt; ): (choice.toInterval()) period return if (HasStart(period)) then start of period else end of period /* @description: Given an interval, return the starting point if the interval has a starting boundary specified, otherwise, return the ending point */ define fluent function earliest(choice Choice&lt;DateTime, Quantity, Interval&lt;DateTime&gt;, Interval&lt;Quantity&gt;&gt; ): (choice.toInterval()) period return if (HasStart(period)) then start of period else end of period /* @description: Creates a list of integers from 1 to how many days are in the interval. Note, this wont create an index for the final day if it is less than 24 hours. This also includes the first 24 hour period. */ define function &quot;Interval To Day Numbers&quot;(Period Interval&lt;DateTime&gt;): ( expand { Interval[1, duration in days between start of Period and end of Period]} ) DayNumber return end of DayNumber /* @description: Creates a list of integers from 1 to how many days are in the interval. Note, this wont create an index for the final day if it is less than 24 hours. This also includes the first 24 hour period. */ define fluent function toDayNumbers(Period Interval&lt;DateTime&gt;): ( expand { Interval[1, duration in days between start of Period and end of Period]} ) DayNumber return end of DayNumber /* @description: Creates a list of 24 hour long intervals in an interval paired with the index (1 indexed) to which 24 hour interval it is. Note that the result will include intervals that are closed at the beginning and open at the end */ define function &quot;Days In Period&quot;(Period Interval&lt;DateTime&gt;): ( &quot;Interval To Day Numbers&quot;(Period)) DayIndex let startPeriod: start of Period + (24 hours * (DayIndex - 1)), endPeriod: if (hours between startPeriod and end of Period &lt; 24) then startPeriod else start of Period + (24 hours * DayIndex) return Tuple { dayIndex: DayIndex, dayPeriod: Interval[startPeriod, endPeriod) } /* @description: Creates a list of 24 hour long intervals in an interval paired with the index (1 indexed) to which 24 hour interval it is. Note that the result will include intervals that are closed at the beginning and open at the end */ define fluent function daysInPeriod(Period Interval&lt;DateTime&gt;): ( &quot;Interval To Day Numbers&quot;(Period)) DayIndex let startPeriod: start of Period + (24 hours * (DayIndex - 1)), endPeriod: if (hours between startPeriod and end of Period &lt; 24) then startPeriod else start of Period + (24 hours * DayIndex) return Tuple { dayIndex: DayIndex, dayPeriod: Interval[startPeriod, endPeriod) }````: **Publisher: **
  * ?: HL7 International - [Some] Work Group
* * **Content: **text/cql: ````/* @author: Stan Rankins @description: Common terminologies and functions used in QI-Core-based CQL artifacts @update: Fashioned after FHIRCommon Version 4.0.012 for use in ecqm-content-qicore-2022 repos */ library QICoreCommon version '1.0.000' using QICore version '4.1.1' include FHIRHelpers version '4.0.013' codesystem &quot;LOINC&quot;: 'http://loinc.org' codesystem &quot;SNOMEDCT&quot;: 'http://snomed.info/sct' codesystem &quot;ICD10CM&quot;: 'http://hl7.org/fhir/sid/icd-10-cm' codesystem &quot;RoleCode&quot;: 'http://terminology.hl7.org/CodeSystem/v3-RoleCode' codesystem &quot;Diagnosis Role&quot;: 'http://terminology.hl7.org/CodeSystem/diagnosis-role' codesystem &quot;RequestIntent&quot;: 'http://terminology.hl7.org/CodeSystem/request-intent' codesystem &quot;MedicationRequestCategory&quot;: 'http://terminology.hl7.org/CodeSystem/medicationrequest-category' codesystem &quot;ConditionClinicalStatusCodes&quot;: 'http://terminology.hl7.org/CodeSystem/condition-clinical' codesystem &quot;ConditionVerificationStatusCodes&quot;: 'http://terminology.hl7.org/CodeSystem/condition-ver-status' codesystem &quot;AllergyIntoleranceClinicalStatusCodes&quot;: 'http://terminology.hl7.org/CodeSystem/allergyintolerance-clinical' codesystem &quot;AllergyIntoleranceVerificationStatusCodes&quot;: 'http://terminology.hl7.org/CodeSystem/allergyintolerance-verification' codesystem &quot;ConditionCategoryCodes&quot;: 'http://terminology.hl7.org/CodeSystem/condition-category' codesystem &quot;ObservationCategoryCodes&quot;: 'http://terminology.hl7.org/CodeSystem/observation-category' valueset &quot;Active Condition&quot;: 'http://fhir.org/guides/cqf/common/ValueSet/active-condition' valueset &quot;Inactive Condition&quot;: 'http://fhir.org/guides/cqf/common/ValueSet/inactive-condition' code &quot;Birthdate&quot;: '21112-8' from &quot;LOINC&quot; display 'Birth date' code &quot;Dead&quot;: '419099009' from &quot;SNOMEDCT&quot; display 'Dead' code &quot;ER&quot;: 'ER' from &quot;RoleCode&quot; display 'Emergency room' code &quot;ICU&quot;: 'ICU' from &quot;RoleCode&quot; display 'Intensive care unit' code &quot;Billing&quot;: 'billing' from &quot;Diagnosis Role&quot; display 'Billing' // Condition Clinical Status Codes - Consider value sets for these code &quot;active&quot;: 'active' from &quot;ConditionClinicalStatusCodes&quot; code &quot;recurrence&quot;: 'recurrence' from &quot;ConditionClinicalStatusCodes&quot; code &quot;relapse&quot;: 'relapse' from &quot;ConditionClinicalStatusCodes&quot; code &quot;inactive&quot;: 'inactive' from &quot;ConditionClinicalStatusCodes&quot; code &quot;remission&quot;: 'remission' from &quot;ConditionClinicalStatusCodes&quot; code &quot;resolved&quot;: 'resolved' from &quot;ConditionClinicalStatusCodes&quot; // Condition Verification Status Codes - Consider value sets for these code &quot;unconfirmed&quot;: 'unconfirmed' from ConditionVerificationStatusCodes code &quot;provisional&quot;: 'provisional' from ConditionVerificationStatusCodes code &quot;differential&quot;: 'differential' from ConditionVerificationStatusCodes code &quot;confirmed&quot;: 'confirmed' from ConditionVerificationStatusCodes code &quot;refuted&quot;: 'refuted' from ConditionVerificationStatusCodes code &quot;entered-in-error&quot;: 'entered-in-error' from ConditionVerificationStatusCodes code &quot;allergy-active&quot;: 'active' from &quot;AllergyIntoleranceClinicalStatusCodes&quot; code &quot;allergy-inactive&quot;: 'inactive' from &quot;AllergyIntoleranceClinicalStatusCodes&quot; code &quot;allergy-resolved&quot;: 'resolved' from &quot;AllergyIntoleranceClinicalStatusCodes&quot; // Allergy/Intolerance Verification Status Codes - Consider value sets for these code &quot;allergy-unconfirmed&quot;: 'unconfirmed' from AllergyIntoleranceVerificationStatusCodes code &quot;allergy-confirmed&quot;: 'confirmed' from AllergyIntoleranceVerificationStatusCodes code &quot;allergy-refuted&quot;: 'refuted' from AllergyIntoleranceVerificationStatusCodes // MedicationRequest Category Codes code &quot;Community&quot;: 'community' from &quot;MedicationRequestCategory&quot; display 'Community' code &quot;Discharge&quot;: 'discharge' from &quot;MedicationRequestCategory&quot; display 'Discharge' // Diagnosis Role Codes code &quot;AD&quot;: 'AD' from &quot;Diagnosis Role&quot; display 'Admission diagnosis' code &quot;DD&quot;: 'DD' from &quot;Diagnosis Role&quot; display 'Discharge diagnosis' code &quot;CC&quot;: 'CC' from &quot;Diagnosis Role&quot; display 'Chief complaint' code &quot;CM&quot;: 'CM' from &quot;Diagnosis Role&quot; display 'Comorbidity diagnosis' code &quot;pre-op&quot;: 'pre-op' from &quot;Diagnosis Role&quot; display 'pre-op diagnosis' code &quot;post-op&quot;: 'post-op' from &quot;Diagnosis Role&quot; display 'post-op diagnosis' code &quot;billing&quot;: 'billing' from &quot;Diagnosis Role&quot; display 'billing diagnosis' // Observation Category Codes code &quot;social-history&quot;: 'social-history' from &quot;ObservationCategoryCodes&quot; display 'Social History' code &quot;vital-signs&quot;: 'vital-signs' from &quot;ObservationCategoryCodes&quot; display 'Vital Signs' code &quot;imaging&quot;: 'imaging' from &quot;ObservationCategoryCodes&quot; display 'Imaging' code &quot;laboratory&quot;: 'laboratory' from &quot;ObservationCategoryCodes&quot; display 'Laboratory' code &quot;procedure&quot;: 'procedure' from &quot;ObservationCategoryCodes&quot; display 'Procedure' code &quot;survey&quot;: 'survey' from &quot;ObservationCategoryCodes&quot; display 'Survey' code &quot;exam&quot;: 'exam' from &quot;ObservationCategoryCodes&quot; display 'Exam' code &quot;therapy&quot;: 'therapy' from &quot;ObservationCategoryCodes&quot; display 'Therapy' code &quot;activity&quot;: 'activity' from &quot;ObservationCategoryCodes&quot; display 'Activity' // Condition Category Codes code &quot;problem-list-item&quot;: 'problem-list-item' from &quot;ConditionCategoryCodes&quot; display 'Problem List Item' code &quot;encounter-diagnosis&quot;: 'encounter-diagnosis' from &quot;ConditionCategoryCodes&quot; display 'Encounter Diagnosis' context Patient /* @description: Normalizes a value that is a choice of timing-valued types to an equivalent interval @comment: Normalizes a choice type of DateTime, Quanitty, Interval&lt;DateTime&gt;, or Interval&lt;Quantity&gt; types to an equivalent interval. This selection of choice types is a superset of the majority of choice types that are used as possible representations for timing-valued elements in QICore, allowing this function to be used across any resource. The input can be provided as a DateTime, Quantity, Interval&lt;DateTime&gt; or Interval&lt;Quantity&gt;. The intent of this function is to provide a clear and concise mechanism to treat single elements that have multiple possible representations as intervals so that logic doesn't have to account for the variability. More complex calculations (such as medication request period or dispense period calculation) need specific guidance and consideration. That guidance may make use of this function, but the focus of this function is on single element calculations where the semantics are unambiguous. If the input is a DateTime, the result a DateTime Interval beginning and ending on that DateTime. If the input is a Quantity, the quantity is expected to be a calendar-duration interpreted as an Age, and the result is a DateTime Interval beginning on the Date the patient turned that age and ending immediately before one year later. If the input is a DateTime Interval, the result is the input. If the input is a Quantity Interval, the quantities are expected to be calendar-durations interpreted as an Age, and the result is a DateTime Interval beginning on the date the patient turned the age given as the start of the quantity interval, and ending immediately before one year later than the date the patient turned the age given as the end of the quantity interval. Any other input will reslt in a null DateTime Interval */ define function ToInterval(choice Choice&lt;DateTime, Quantity, Interval&lt;DateTime&gt;, Interval&lt;Quantity&gt;&gt;): case when choice is DateTime then Interval[choice as DateTime, choice as DateTime] when choice is Interval&lt;DateTime&gt; then choice as Interval&lt;DateTime&gt; when choice is Quantity then Interval[Patient.birthDate + (choice as Quantity), Patient.birthDate + (choice as Quantity) + 1 year) when choice is Interval&lt;Quantity&gt; then Interval[Patient.birthDate + (choice.low as Quantity), Patient.birthDate + (choice.high as Quantity) + 1 year) else null as Interval&lt;DateTime&gt; end /* @description: Normalizes a value that is a choice of timing-valued types to an equivalent interval @comment: Normalizes a choice type of DateTime, Quanitty, Interval&lt;DateTime&gt;, or Interval&lt;Quantity&gt; types to an equivalent interval. This selection of choice types is a superset of the majority of choice types that are used as possible representations for timing-valued elements in QICore, allowing this function to be used across any resource. The input can be provided as a DateTime, Quantity, Interval&lt;DateTime&gt; or Interval&lt;Quantity&gt;. The intent of this function is to provide a clear and concise mechanism to treat single elements that have multiple possible representations as intervals so that logic doesn't have to account for the variability. More complex calculations (such as medication request period or dispense period calculation) need specific guidance and consideration. That guidance may make use of this function, but the focus of this function is on single element calculations where the semantics are unambiguous. If the input is a DateTime, the result a DateTime Interval beginning and ending on that DateTime. If the input is a Quantity, the quantity is expected to be a calendar-duration interpreted as an Age, and the result is a DateTime Interval beginning on the Date the patient turned that age and ending immediately before one year later. If the input is a DateTime Interval, the result is the input. If the input is a Quantity Interval, the quantities are expected to be calendar-durations interpreted as an Age, and the result is a DateTime Interval beginning on the date the patient turned the age given as the start of the quantity interval, and ending immediately before one year later than the date the patient turned the age given as the end of the quantity interval. Any other input will reslt in a null DateTime Interval */ define fluent function toInterval(choice Choice&lt;DateTime, Quantity, Interval&lt;DateTime&gt;, Interval&lt;Quantity&gt;&gt;): case when choice is DateTime then Interval[choice as DateTime, choice as DateTime] when choice is Interval&lt;DateTime&gt; then choice as Interval&lt;DateTime&gt; when choice is Quantity then Interval[Patient.birthDate + (choice as Quantity), Patient.birthDate + (choice as Quantity) + 1 year) when choice is Interval&lt;Quantity&gt; then Interval[Patient.birthDate + (choice.low as Quantity), Patient.birthDate + (choice.high as Quantity) + 1 year) else null as Interval&lt;DateTime&gt; end /* @description: Returns an interval representing the normalized abatement of a given Condition. @comment: If the abatement element of the Condition is represented as a DateTime, the result is an interval beginning and ending on that DateTime. If the abatement is represented as a Quantity, the quantity is expected to be a calendar-duration and is interpreted as the age of the patient. The result is an interval from the date the patient turned that age to immediately before one year later. If the abatement is represented as a Quantity Interval, the quantities are expected to be calendar-durations and are interpreted as an age range during which the abatement occurred. The result is an interval from the date the patient turned the starting age of the quantity interval, and ending immediately before one year later than the date the patient turned the ending age of the quantity interval. */ define function ToAbatementInterval(condition Condition): if condition.abatement is DateTime then Interval[condition.abatement as DateTime, condition.abatement as DateTime] else if condition.abatement is Quantity then Interval[Patient.birthDate + (condition.abatement as Quantity), Patient.birthDate + (condition.abatement as Quantity) + 1 year) else if condition.abatement is Interval&lt;Quantity&gt; then Interval[Patient.birthDate + (condition.abatement.low as Quantity), Patient.birthDate + (condition.abatement.high as Quantity) + 1 year) else if condition.abatement is Interval&lt;DateTime&gt; then Interval[condition.abatement.low, condition.abatement.high) else null as Interval&lt;DateTime&gt; /* @description: Returns an interval representing the normalized abatement of a given Condition. @comment: If the abatement element of the Condition is represented as a DateTime, the result is an interval beginning and ending on that DateTime. If the abatement is represented as a Quantity, the quantity is expected to be a calendar-duration and is interpreted as the age of the patient. The result is an interval from the date the patient turned that age to immediately before one year later. If the abatement is represented as a Quantity Interval, the quantities are expected to be calendar-durations and are interpreted as an age range during which the abatement occurred. The result is an interval from the date the patient turned the starting age of the quantity interval, and ending immediately before one year later than the date the patient turned the ending age of the quantity interval. */ define fluent function toAbatementInterval(condition Condition): if condition.abatement is DateTime then Interval[condition.abatement as DateTime, condition.abatement as DateTime] else if condition.abatement is Quantity then Interval[Patient.birthDate + (condition.abatement as Quantity), Patient.birthDate + (condition.abatement as Quantity) + 1 year) else if condition.abatement is Interval&lt;Quantity&gt; then Interval[Patient.birthDate + (condition.abatement.low as Quantity), Patient.birthDate + (condition.abatement.high as Quantity) + 1 year) else if condition.abatement is Interval&lt;DateTime&gt; then Interval[condition.abatement.low, condition.abatement.high) else null as Interval&lt;DateTime&gt; /* @description: Returns an interval representing the normalized prevalence period of a given Condition. @comment: Uses the ToInterval and ToAbatementInterval functions to determine the widest potential interval from onset to abatement as specified in the given Condition. If the condition is active, the resulting interval will have a closed ending boundary. If the condition is not active, the resulting interval will have an open ending boundary. */ define function ToPrevalenceInterval(condition Condition): if condition.clinicalStatus ~ &quot;active&quot; or condition.clinicalStatus ~ &quot;recurrence&quot; or condition.clinicalStatus ~ &quot;relapse&quot; then Interval[start of ToInterval(condition.onset), end of ToAbatementInterval(condition)] else Interval[start of ToInterval(condition.onset), end of ToAbatementInterval(condition)) /* @description: Returns an interval representing the normalized prevalence period of a given Condition. @comment: Uses the ToInterval and ToAbatementInterval functions to determine the widest potential interval from onset to abatement as specified in the given Condition. If the condition is active, the resulting interval will have a closed ending boundary. If the condition is not active, the resulting interval will have an open ending boundary. */ define fluent function toPrevalenceInterval(condition Condition): if condition.clinicalStatus ~ &quot;active&quot; or condition.clinicalStatus ~ &quot;recurrence&quot; or condition.clinicalStatus ~ &quot;relapse&quot; then Interval[start of ToInterval(condition.onset), end of ToAbatementInterval(condition)] else Interval[start of ToInterval(condition.onset), end of ToAbatementInterval(condition)) /* @description: Returns the tail of the given uri (i.e. everything after the last slash in the URI). @comment: This function can be used to determine the logical id of a given resource. It can be used in a single-server environment to trace references. However, this function does not attempt to resolve or distinguish the base of the given url, and so cannot be used safely in multi-server environments. */ define function GetId(uri String ): Last(Split(uri, '/')) /* @description: Returns the tail of the given uri (i.e. everything after the last slash in the URI). @comment: This function can be used to determine the logical id of a given resource. It can be used in a single-server environment to trace references. However, this function does not attempt to resolve or distinguish the base of the given url, and so cannot be used safely in multi-server environments. */ define fluent function getId(uri String): Last(Split(uri, '/')) /* @description: Given an interval, return true if the interval has a starting boundary specified (i.e. the start of the interval is not null and not the minimum DateTime value) */ define function &quot;HasStart&quot;(period Interval&lt;DateTime&gt; ): not ( start of period is null or start of period = minimum DateTime ) /* @description: Given an interval, return true if the interval has a starting boundary specified (i.e. the start of the interval is not null and not the minimum DateTime value) */ define fluent function hasStart(period Interval&lt;DateTime&gt; ): not ( start of period is null or start of period = minimum DateTime ) /* @description: Given an interval, returns true if the interval has an ending boundary specified (i.e. the end of the interval is not null and not the maximum DateTime value) */ define function &quot;HasEnd&quot;(period Interval&lt;DateTime&gt; ): not ( end of period is null or end of period = maximum DateTime ) /* @description: Given an interval, returns true if the interval has an ending boundary specified (i.e. the end of the interval is not null and not the maximum DateTime value) */ define fluent function hasEnd(period Interval&lt;DateTime&gt; ): not ( end of period is null or end of period = maximum DateTime ) /* @description: Given an interval, returns the ending point if the interval has an ending boundary specified, otherwise, returns the starting point */ define function &quot;Latest&quot;(choice Choice&lt;DateTime, Quantity, Interval&lt;DateTime&gt;, Interval&lt;Quantity&gt;&gt; ): (choice.toInterval()) period return if (HasEnd(period)) then end of period else start of period /* @description: Given an interval, returns the ending point if the interval has an ending boundary specified, otherwise, returns the starting point */ define fluent function latest(choice Choice&lt;DateTime, Quantity, Interval&lt;DateTime&gt;, Interval&lt;Quantity&gt;&gt; ): (choice.toInterval()) period return if (HasEnd(period)) then end of period else start of period /* @description: Given an interval, return the starting point if the interval has a starting boundary specified, otherwise, return the ending point */ define function &quot;Earliest&quot;(choice Choice&lt;DateTime, Quantity, Interval&lt;DateTime&gt;, Interval&lt;Quantity&gt;&gt; ): (choice.toInterval()) period return if (HasStart(period)) then start of period else end of period /* @description: Given an interval, return the starting point if the interval has a starting boundary specified, otherwise, return the ending point */ define fluent function earliest(choice Choice&lt;DateTime, Quantity, Interval&lt;DateTime&gt;, Interval&lt;Quantity&gt;&gt; ): (choice.toInterval()) period return if (HasStart(period)) then start of period else end of period /* @description: Creates a list of integers from 1 to how many days are in the interval. Note, this wont create an index for the final day if it is less than 24 hours. This also includes the first 24 hour period. */ define function &quot;Interval To Day Numbers&quot;(Period Interval&lt;DateTime&gt;): ( expand { Interval[1, duration in days between start of Period and end of Period]} ) DayNumber return end of DayNumber /* @description: Creates a list of integers from 1 to how many days are in the interval. Note, this wont create an index for the final day if it is less than 24 hours. This also includes the first 24 hour period. */ define fluent function toDayNumbers(Period Interval&lt;DateTime&gt;): ( expand { Interval[1, duration in days between start of Period and end of Period]} ) DayNumber return end of DayNumber /* @description: Creates a list of 24 hour long intervals in an interval paired with the index (1 indexed) to which 24 hour interval it is. Note that the result will include intervals that are closed at the beginning and open at the end */ define function &quot;Days In Period&quot;(Period Interval&lt;DateTime&gt;): ( &quot;Interval To Day Numbers&quot;(Period)) DayIndex let startPeriod: start of Period + (24 hours * (DayIndex - 1)), endPeriod: if (hours between startPeriod and end of Period &lt; 24) then startPeriod else start of Period + (24 hours * DayIndex) return Tuple { dayIndex: DayIndex, dayPeriod: Interval[startPeriod, endPeriod) } /* @description: Creates a list of 24 hour long intervals in an interval paired with the index (1 indexed) to which 24 hour interval it is. Note that the result will include intervals that are closed at the beginning and open at the end */ define fluent function daysInPeriod(Period Interval&lt;DateTime&gt;): ( &quot;Interval To Day Numbers&quot;(Period)) DayIndex let startPeriod: start of Period + (24 hours * (DayIndex - 1)), endPeriod: if (hours between startPeriod and end of Period &lt; 24) then startPeriod else start of Period + (24 hours * DayIndex) return Tuple { dayIndex: DayIndex, dayPeriod: Interval[startPeriod, endPeriod) }````: **Jurisdiction: **
  * ?: US



## Resource Content

```json
{
  "resourceType" : "Library",
  "id" : "QICoreCommon",
  "extension" : [{
    "url" : "http://hl7.org/fhir/us/cqfmeasures/StructureDefinition/cqfm-softwaresystem",
    "valueReference" : {
      "reference" : "Device/cqf-tooling"
    }
  }],
  "url" : "http://cms.gov/fhir/mct/Library/QICoreCommon",
  "version" : "0.1.0",
  "name" : "QICoreCommon",
  "title" : "QiCore Common",
  "status" : "draft",
  "type" : {
    "coding" : [{
      "system" : "http://terminology.hl7.org/CodeSystem/library-type",
      "code" : "logic-library"
    }]
  },
  "date" : "2026-02-27T18:11:00+00:00",
  "publisher" : "HL7 International - [Some] Work Group",
  "contact" : [{
    "telecom" : [{
      "system" : "url",
      "value" : "http://hl7.org/Special/committees/[something]"
    }]
  }],
  "jurisdiction" : [{
    "coding" : [{
      "system" : "urn:iso:std:iso:3166",
      "code" : "US"
    }]
  }],
  "content" : [{
    "contentType" : "text/cql",
    "data" : " "
  }]
}

```
