Repository navigation
Send an evaluation request timestamp, defaulting to UTC, with every test - #142
Open
bryantaustin13 wants to merge 2 commits into
Open
bryantaustin13 wants to merge 2 commits into
bryantaustin13 wants to merge 2 commits into
Conversation
CQL evaluates each request against an evaluation request timestamp: Now(), Today() and TimeOfDay() return it, and a DateTime written without an offset takes its offset. The runner sent no timestamp and no timezone, so every result was computed on the server's clock and in the server's zone, and the same suite gave different DateTime results depending on where it ran. This is the request side of #138 (from cqframework/cql-tests#28): - A test may set evaluationDateTime, or only evaluationTimezoneOffset. With neither, it is evaluated at the start of the run in UTC. A test that sets both, or an unusable value, is scored as an error and not sent. cql-tests#28 does not fix an offset format, so both `Z` / `±HH:MM` and CQL decimal hours (`-6.0`) are accepted. - The timestamp is sent as the `timestamp` input of $cql and Library/$evaluate (Using CQL With FHIR 3.0.0-ballot OperationDefinitions), and as the `Timezone` client-timezone header (FHIR R5 http.html#timezones). - At the start of a run the server is probed once, and the results record whether it honours each mechanism (`evaluationRequest`) and the timestamp each test was sent (`evaluationTimestamp`). Both are added to the results schema. Comparison is unchanged. Interpreting offset-less expected DateTimes at the evaluation offset, and honouring time-hasOffset, is the follow-up step, so this change on its own moves no test from fail to pass on any engine. Against HAPI FHIR 8.10.0 / CQFramework engine 4.1.0, which ignores both mechanisms without error (probe: no / no), the full cql-tests suite is unchanged at 1639/170/14/0, with no status or actual value changing across 1823 records. Library/$evaluate likewise accepts and ignores them. 252 unit tests pass (235 before, 17 new). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 1, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #138. Replaces the approach of #119 (closed).
Problem
CQL evaluates every request against an evaluation request timestamp.
Now(),Today()andTimeOfDay()return it, and a DateTime written without an offset takes its offset. In the CQL Author's Guide: "If no timezone offset is specified, the timezone offset of the evaluation request timestamp is used."The runner sent neither a timestamp nor a timezone. For
$cqlthe request carried onlyexpression, so every result was computed on the server's clock and in the server's zone. The same suite therefore gave different DateTime results depending on where the server ran. Against a server in-06:00:Change
This is the request side of #138. Comparison is not changed here (see Not in this PR).
Per-test evaluation timing (cqframework/cql-tests#28):
evaluationDateTime(the timestamp itself) orevaluationTimezoneOffset(only the offset).errorwith a clear message and is not sent.Z/±HH:MMand CQL's decimal hours (-6.0) are accepted, since the two cannot be confused. The cql-tests schema change could settle on one.Sent to the server, using both mechanisms Using CQL With FHIR describes (3.0.0-ballot, Timezone and Timezone Offset Handling, FHIR-56046):
timestampinput parameter of$cqlandLibrary/$evaluate, as defined by the IG's OperationDefinitions (0..1 dateTime, "The timestamp of the evaluation request");Timezoneclient-timezone header from FHIR's Client Timezone section (R5http.html#timezones), e.g.Timezone: 2026-09-28T17:12:04.586Z.A server that supports neither ignores both. This was verified on HAPI FHIR 8.10.0 for
$cqlandLibrary/$evaluate.Reported:
Now()sent with a fixedtimestampshows whether the parameter is used;+05:45shows whether the header is used.Evaluation requests default to timezone offset Z; server honours timestamp parameter: no, Timezone header: no.evaluationRequest, and each result records theevaluationTimestampit was sent. Both are optional in the results schema.Library/$evaluateconfiguration (which cannot be probed without publishing a library), recordsnull, meaning unknown.This matters for reading DateTime failures: against a server that honours neither mechanism, results are in the server's own zone, whatever the test requested.
The README documents the attributes, the defaults, and what is sent.
Verification
Against HAPI FHIR 8.10.0 (CQL engine 5.1.0 via clinical-reasoning 4.10.0), full cql-tests suite:
maintimestampParameterHonored: false,timezoneHeaderHonored: false, which matches direct requests to the server.evaluationTimestamp. The 14 skips carry none, as they are skipped before a request is built.Timezoneheader sent byrunTest;test/run-tests.test.tscounts and sequencesfetchcalls, so it replaces the probe with a fixed answer.Not in this PR
Comparison. On its own, this change moves no test from fail to pass on any engine, including one that follows the IG. The comparator still compares DateTimes as text, so the expected
@2005-05-10T10:20:30does not match a compliant engine's2005-05-10T10:20:30Z. The follow-up would:time-hasOffset: falseon actual values (@brynrhodes's request on Functionality to support testing of Time zone offset #77/Functionality to support testing of Time zone offset #119).It is kept separate because it changes scoring, needs decisions (for example, how to report a result from a server that ignored the requested offset), and overlaps #132 (
Z/+00:00equivalence).time-hasOffsetalso has no engine that emits it to test against yet.The test attributes. Neither attribute is in
testSchema.xsdor used by any test yet. That is cqframework/cql-tests#28.Notes for the IG
Two small defects in Using CQL With FHIR 3.0.0-ballot, found while implementing this:
requestTimestamp, while the OperationDefinitions name ittimestamp;tsc --noEmitstill reports the two pre-existingrest-routes.tserrors onmain, which #139 fixes.🤖 Generated with Claude Code