Skip to content

Cooking with CQL Q&A: Date and Time Calculations

rhondaschwartz edited this page Mar 10, 2021 · 24 revisions

Each Q&A has the Cooking with CQL session number and date. For the most current and accurate information, please check the CQL Qs&As for a more recent answer to your question.

authorDatetime: With regard to the QDM attribute author dateTime, if that’s the time it’s entered into the clinical software then what happens when someone goes back to edit it? Is it the last modified time or the original creation time and do we have a way of handling that? (Session 35 - 5/23/19)
  • Thank you for this question. The issue is something the implementer needs to address. The QDM attribute author dateTime is defined as “The time the data element was entered into the clinical software.” This timing should be equivalent to a time stamp in the software. Any edits to the information entered might update the relevant dateTime or relevantPeriod to address the actual time an action occurred will have a new timestamp for the edits, but the original timestamp to indicate the activity should remain. All changes are new revisions with their own timestamps. While the answer may depend on the activity desired by the measure, the author dateTime should most likely be the time originally documented. Note that another use of author dateTime is to identify the timestamp for documenting negationRationale, the reason an action was not taken. Even if the negationRationale reason was modified, the original time documenting an action that did not happen for a reason should be the timestamp used for the measure concept. In this example, the “Medication, Dispensed” relevant dateTime is the time dispensed (in FHIR, whenHandedOver). If that were edited in a pharmacy system the actual relevant dateTime would be used for the calculation (i.e., the revised version). Implementers will need to determine if the edits are valid and acceptable as part of routine local data maintenance rules.
Calculating the cumulative period or start date for a single medication request in FHIR: When calculating the cumulative period or start date for a single medication request in Fast Healthcare Interoperability Resources® (FHIR)®, which would be best to use within the code, the start of validityPeriod or authoredOn? (Session 51 - 2/25/2021)
  • When calculating the MedicationRequestPeriod, the validityPeriod and authoredOn anchors provide a similar, and often same, result. As background, if a physician writes a prescription for a patient on ‘x’ date (authoredOn), they do not know exactly when the patient will fill the prescription. Note that validityPeriod definition is the “Time period supply is authorized for ,“ in other words, the time period after which the prescription can no longer be filled. Commonly, the pharmacist determines the validity of the prescription based on the ‘x’ date the prescription was written by the physician, commonly it is one year but it may be less for specific medications. After the end of the validityPeriod the pharmacist will no longer fill the prescription deeming it invalid and will ask the patient to provide a new prescription from their physician. If the start of validityPeriod is known, it will be used as the earliest dispensable date. If the validityPeriod is not known, authoredOn is the best anchor to use.

Interval[earliestDispensable, earliestDispensable + expectedSupplyDuration]

earliestDispensable: Coalesce(start of validityPeriod, authoredOn)


Calculating the overall expected duration (days) of a medication request in FHIR: In calculating the overall expected duration (days) of a medication request in Fast Healthcare Interoperability Resources® (FHIR)®, would the logic expression used for variable frequency and periodUnit still apply if the prescription is an absolute order, such as one dosage a day or one dosage every 12 hours? For a prescription that is an absolute order, such as that described, does the logic of using a variable frequency and periodUnit still apply?

(quantity / (dosage * frequency)) * (1 + numberOfRepeatsAllowed)

dosage: Coalesce(end of doseAndRate.doseRange, doseAndRate.doseQuantity)
frequency: Coalesce(frequencyMax, frequency)
period: Quantity(period, periodUnit)

(Session 51 - 2/25/2021)

  • The variable logic expression would still apply for defined medication orders (e.g., defined quantity, specified duration). The frequencyMax would be empty and period max would not be defined. The calculation would only return the frequency and period.
Coalesce: In the Coalesce expression, if the patient record has an order performed date of 12/12 but the performed author DateTime is 12/07 what is the result?

Coalesce(start of ComfortMeasures.relevantPeriod, ComfortMeasures.authorDatetime)

(Session 31 - 1/31/2019)

  • For Coalesce, each argument is considered in order, and the first one with a value is returned. The use of “first” in this description is referring to the list of arguments to the Coalesce function. So in the example of a performed date of 12/12 and an author date of 12/07, since the performed date (start of relevantPeriod) is first in the list of arguments and has a value, that will be returned as the result.
Collapse with Null Entry Boundary: In the example test expressions for collapse with null ending boundary, if you define a third test as successor maximum, would that throw an error?

define Test1:
	  collapse(
	    {
	      Interval[@2021-01-06, @2021-01-08],
	      Interval[@2021-01-08, null]
	    }
	  )

define Test2:
	  collapse(
	    {
	      Interval[@2021-01-06, @2021-01-08],
	      Interval[@2021-01-08, null],
	      Interval[@2021-01-15, @2021-01-18]
	    }
	  )


/*
	Results:
	Test1=[Interval[2021-01-06, 9999-12-31]]
	Test2=[Interval[2021-01-06, 9999-12-31]]
	*/

(Session 50 - 1/21/2021)

  • Yes. A third test, successor of maximum DateTime, does throw an error. The Java and Java Script implementations are mostly likely testing the boundary first. The eCQM Standards Team will confirm what the Java and Java Script implementations are testing. The pseudo code used to test this function is: http://build.fhir.org/ig/HL7/cql/09-b-cqlreference.html#collapse.

Define Test 3: successor of maximum DateTime – when tested presented an error

Cumulative Medication Duration: In the example of the QDM documentation illustrating the Cumulative Medication Duration calculation, if the second date is prior to the first date, does that always get to negative? Does this uncertainty play into that calculation? (Session 34 - 4/24/2019)
  • Yes, if the second date is before the first date then you will get a negative number out of it. You will still get the same number, it would just be in the other direction.
Cumulative Medication Duration: In the example of the QDM documentation illustrating the Cumulative Medication Duration calculation, what if the first date is only at the day level but the second level precision is at the time level, do you still end up with an indecision? (Session 34 - 4/24/2019)
  • The engines do all the calculations so the lowest value of the less precise to the highest possible value of the less precise and they do the duration calculation between those and that gives them the result as an interval. In the example below, it would calculate from the earliest possible time, midnight, and the latest possible time, 11:59 PM, on the first date, giving you the same result. In general, it is okay for the format to be different between the 2 days. The actual result will be an uncertainty.

define DurationInDays: days between @2017-08-07T and @2017-08-14T17:00 // [6, 7]

Cumulative Medication Duration: For the interval function of the example of the QDM documentation illustrating the Cumulative Medication Duration calculation, is it required that the first parameter has to be less than or equal to the second parameter? (Session 34 - 4/24/2019)
  • Yes, that is true of intervals. In the example below, that would be an error because it’s not a valid interval. Interval [@2018-02-01, @2018-01-01]
Date vs DateTime: For the glucocorticoid dosage expression, is using Date appropriate in place of DateTime? (Session 31 - 1/31/2019)
define function "Glucocorticoids Dosage Per Day"(glucocorticoids List<Tuple {
  code Code,
  daysInPeriod List<DateTime>,
  dailyDosage Quantity
}>):

  • Yes, since CQL 1.3, the Date type can be used for the daysInPeriod argument (i.e., List<Date> instead of List<DateTime>).
DifferenceInDays vs DurationInDays: Using the DifferenceInDays example below: is this the same as calendar days? Would the DurationInDays give you the uncertainty result or would it be different in this situation?

define DifferenceInDays: difference in days between @2017-01-01T22:00:00 and @2017-01-02T02:00:00 // 1

define DifferenceInDays: duration in days between @2017-01-01T22:00:00 and @2017-01-02T02:00:00 // 0

(Session 34 - 4/24/2019)

  • The distinction between Difference and Duration is that Difference is counting the boundaries. You can still get uncertainty in Difference calculations but note that Difference is counting the number of boundaries crossed. In this example, DifferenceInDays is 1 because midnight was crossed once but DurationInDays is 0 because 24 hours have not passed. Note that both Difference and Duration calculations can give you uncertainty but Difference is less sensitive to the time than Duration.
Estimated Due Date: Regarding estimated due date definition – how can we be sure it's the last physical exam we're interested in. Mothers can have multiple babies over a period of time so how do we know which baby it is associated with on the mother's record? For example, if a mother has 3 pregnancies but we want to reference the 2nd pregnancy, how do we link this last due date in the second pregnancy to the mother's record? (Session 33 - 3/28/2019)
  • This is a case of retrospective data. It might be possible to indicate a one-year time period prior to the delivery date of the referenced pregnancy. One might need to seek guidance from the American College of Obstetrics and Gynecology (ACOG) to get a definition of due date. Regardless, if the expectation is to perform a context-based query, the patient record and the related person might have to exist at the same time.
Interpreting time phrases: When interpreting time phrases in Clinical Quality Language (CQL), for example, an encounter started at midnight on 1/1/2020 and the diagnosis also started at midnight on 1/1/2020. In this case, did the diagnosis start during the encounter? (Session 46 - 07/30/2020)
  • Using the example provided, this expression returns true because it defines during inclusively. The diagnosis is during that interval because during hits the boundaries of this expression. Whether the diagnosis started at midnight or 10:30 am, both of those would count if we are just looking at starts during because it is an inclusive comparison.

@2020-01-01T00:00:00.0 during Interval[@2020-01-01T00:00:00.0, @2020-01-01T10:30:00:00]

Lab Tests Every Six Weeks Revisited : In the Lab Tests Every Six Weeks Revisited example where lab tests need to happen every six weeks or LESS while the therapy is ongoing, why have you chosen to use days instead of weeks?


define "Has Lab Test Intervals More Than Six Weeks":
  "Valid Lab Test Intervals" LTI
   where duration in days of LTI > 42

define "Numerator":
  Count("Valid Lab Test Intervals") >= 2
    and not exists "Has Lab Test Intervals More Than Six Weeks"


(Session 48 - 10/29/2020)

  • We do not want tests performed in the 6th week. If you have a test that is performed at 6 weeks and 1 day, the duration would be 6 weeks since it has not yet hit the 7th week. Any test that is performed up to the day before the 7th week will still render as 6 weeks and since we do not want to count tests performed in the 6th week we need to use days.
Lab Tests Every Six Weeks Revisited #2: In the Lab Tests Every Six Weeks Revisited example where lab tests need to happen every six weeks or LESS while the therapy is ongoing, why have you chosen to use days instead of weeks? (Session 48 - 10/29/2020)
  • To achieve this you can bound the start of chemotherapy to the start of the measurement period:

2019/11/01
	      |--------------|----------------|----------------|--------------|
	                |----------------------------------|
	              2020/01/01                        2020/12/31
	                                            |--------------|----------|


In this example, the measurement period is defined as:


define "Chemotherapy During Measurement Period":
  ["Medication, Active": "Chemotherapy for Advanced Cancer"] Chemotherapy
    where ( Chemotherapy.relevantPeriod starts 1 year or less before start "Measurement Period"
        //and Chemotherapy.relevantPeriod overlaps "Measurement Period"
    )

where the start of the chemotherapy (2019/11/01) is bound to the start of the measurement period (2020/01/01) and is defined as:


define "Start of Chemotherapy During Measurement Period":
  Min("Chemotherapy During Measurement Period" Chemotherapy
    return start of Chemotherapy.relevantPeriod
)

The expression for the end of the measurement period is:


define "End of Chemotherapy During Measurement Period":
Min({
    end of "Measurement Period",
    "Start of Chemotherapy During Measurement Period" + 1 year,
    Max("Chemotherapy During Measurement Period" Chemotherapy
      return end of Chemotherapy.relevantPeriod )
})

Latest Function: For interval boundary access, what is the rationale for defining the Latest function?

define function Latest(period Interval<DateTime>):
	  if (HasEnd(period)) then
	    end of period
	  Else
	    start of period

And what will this Latest normalizeInterval function return?


//Latest(NormalizeInterval(Procedure.relevantDateTime, Procedure.relevantPeriod))

(Session 48 - 10/29/2020)

  • The Latest function is only used for a dateTime interval. The Latest normalizeInterval function will return the latest point in the interval that is specified. If the dateTime interval has an end, meaning it does not have a null ending boundary, then the Latest function is going to return the end of that dateTime interval. Otherwise, the Latest function will return the start of that dateTime interval.
Latest and normalizeInterval Functions: For interval boundary access, are both the Latest and normalizeInterval functions applicable for the 2021 Annual Measure updates when we have six or seven data elements each of which have relevantDatetime and relevantPeriod? (Session 48 - 10/29/2020)
  • Yes, the Latest (used when the measure only requires one dateTime point) and NormalizeInterval functions need to be applied for any data element that has both relevantDatetime and relevantPeriod for the 2021 Annual Update. From the clinical perspective, the use of start time or end time needs to be determined by the measure author. The LatestOf and EarliestOf function can be used to apply both Latest/Earliest and NormalizeInterval. In order for measure developers to align with assessmentPerformed or procedurePerformed, the measure developers should utilize these expressions.
define function Latest(period Interval<DateTime>):
	  if (HasEnd(period)) then
	    end of period
	  Else
	    start of period

define function Earliest(period Interval<DateTime>):
	  if (HasStart(period)) then
	    start of period
	  Else
	    end of period

//Latest(NormalizeInterval(Procedure.relevantDateTime, Procedure.relevantPeriod))

define function LatestOf(pointInTime dateTime, period Interval<DateTime>):
	  Latest(NormalizeInterval(pointInTime, period))

define function EarliestOf(pointInTime dateTime, period Interval<DateTime>):
	  Earliest(NormalizeInterval(pointInTime, period))

Leap Year: CQL logic calculates an interval using both days and months. The specific line of code in question refers to: FirstIndexAssessment.authorDatetime where we can use a combination of months and days. For this line of code, are leap years accounted for if you use 14 months? (Session 34 - 4/24/2019)
  • No, because months are still by calendar year too. If you had gone through February in 2012, you would have gotten 29 days. In order to avoid the issue with leap years, you should not combine moths and days and only use days to avoid this variability.
normalizeInterval Function: When discussing the normalizeInterval function, if the period is not known and the period only contains low with high as null flavor, will this function use the low to populate both periods?

define function "NormalizeInterval"(pointInTime DateTime, period Interval<DateTime>):
  if pointInTime is not null then Interval[pointInTime, pointInTime]
    else if period is not null then period
    else null as Interval<DateTime>

(Session 48 - 10/29/2020)

  • No because this function does not look inside the period that is provided. If a period is provided, it will return a result such as: if pointInTime is not null then Interval[pointInTime, pointInTime]. If the end point is null, it will stay as null. Even if the interval provided has null for both high and low, this function will still return this type of result since it is not a null interval; it is an interval with null boundaries.
normalizeInterval Function #2: When utilizing the normalizeInterval guidance, how do you clearly convey to the person retrieving the information how they should calculate the timing criteria? (Session 48 - 10/29/20)
  • You need to specify how you want the comparison to happen (e.g., start of or end of the interval). The example is concerned with the start of the interval; it starts 12 months or less before the start of “Measurement Period”.
 where Global."NormalizeInterval"(TKAProcedure.relevantDatetime, TKAProcedure.relevantPeriod)
  starts 12 months or less before start of "Measurement Period"

Given that this "NormalizeInterval" will return an interval, the authoring environment will ensure that your timing phrase makes sense for that type. If you are comparing to a date, you have to consider the question of whether the comparison is to the start or end of the interval returned from NormalizeInterval.

normalizeInterval Function vs relevantPeriod: The 2021 HL7 and CMS QRDA Implementation Guides are not using the normalizeInterval function, but are using relevantPeriod and the period could be a dateTime or a period. If the QRDA file only includes a period, but the criteria is looking for a point of time, should we always pick the start of the period, end of the period, or consult the measure author to see which one is the intent of the measure? (Session 48 - 10/29/20)
  • The guidance would be to consult the measure author to confirm the intent of the measure. There are variations in the use of every data type such that either representation should be considered as part of the criteria in every case. Please submit all questions through the eCQM JIRA Issue Tracker by creating an issue ticket using the following link: https://oncprojectracking.healthit.gov/support/secure/CreateIssue!default.jspa.
Relevant Period: Referring to CMS52v7, does the laboratory test always have a relevant period? (Session 35 - 5/23/19)
  • Since QDM 5.5, a “Laboratory Test, Performed” uses relevant dateTime to represent an activity that occurs at a single point in time (e.g., a fasting blood glucose with a single point in time collection), and relevantPeriod start and stop times for a laboratory test that occurs over a time interval (e.g., a 24-hour urine collection for creatinine clearance).

Note, a measure developer should work with implementers to determine if timed collections are truly documented as a period or as a point in time to determine the appropriate representation in a measure.

Subtraction of one hour when there is a leap second: When interpreting time phrases in Clinical Quality Language (CQL), what is the subtraction of one hour when there is a leap second? (Session 46 - 7/30/20)
  • The definition of a calendar hour is the same time in the next hour so that effectively allows you to treat hours like calendar durations in the same way that we do for leap days. We say that the month is the same date in the next month if that date exists, otherwise it is the previous day. Because leap seconds are so foreign to human experience and our goal is natural language expression for humans, we do not call out leap seconds specifically, but leap seconds are the reason that Unified Code for Units of Measure (UCUM) units and calendar durations units are only equal up to the second. A UCUM unit is not comparable to the calendar duration unit for anything above a second.

Wiki Index

Home

Authoring Patterns - QICore v4.1.1

Authoring Patterns - QICore v5.0.0

Authoring Patterns - QICore v6.0.0

Authoring Measures in CQL

Composite Measure Development

Cooking with CQL Examples

Cooking with CQL Q&A All Categories
Additional Q&A Examples

CQL 1.3 Impact Guidance

CQL Error Messages

Developers Introduction to CQL

Discussion Items

Example Measures

Formatting and Usage Topics

Formatting Conventions

Library Versioning

Negation in QDM

QDM Known Issues

Specific Occurrences

Specifying Population Criteria

Supplemental Data Elements

Terminology in CQL

Translator Options For Measure Development

Unions in CQL

Clone this wiki locally