DateTime ordering can be incorrect for mixed precision operands with fractional time zone differences

オープン
#397 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

評価

難易度
5/5
見積もり時間
1週間以上
初心者へのやさしさ
35/100
issue の種類
バグ
明瞭さ
おおむね明確
活発さ
活発
技術スタック
javascript
領域
backend

調査の方向性

Start with the comparison and uncertainty code in src/datatypes/datetime.ts and src/datatypes/uncertainty.ts, then read the linked CQL date and time comparison guidance. Reproduce the A/B example and check the existing DateTime comparison tests. Done means the comparison operators handle mixed precision and fractional time zone offsets consistently while preserving CQL precision semantics.

索引モデルが issue の本文から書いたものです。

説明

As noted in https://github.com/cqframework/cql-execution/pull/392#discussion_r4359959264 , ordering DateTimes that have mixed precision, and whose time zone offsets differ by a fractional amount (eg +3:30) can result in asymmetric results, where one operation is correct but its inverse is incorrect

Consider examples
A = @2025-01-02T05-03:30 and
B = @2025-01-02T08:15:00.000Z:

A before B returns false (correct, every possible precise value for A is after B), but then
B after A returns null (incorrect, should be true)

The issue is that 2025-01-02T05-03:30 has a timezone offset with greater precision (minutes) than the DateTime itself (minutes unspecified). As of now when we convert this to a timezone with 0-minute offset like UTC, it becomes 2025-01-02T08+00:00 which is not equivalent, and I don't think it would be correct to change it to 2025-01-02T08:30+00:00 since that's a finer precision than the original DateTime.
The way to get around this would be to treat the not-fully-specified DateTime as an uncertainty instead, as the spec does suggest here https://cql.hl7.org/02-authorsguide.html#comparing-dates-and-times .

In general, CQL treats Date and Time values that are only known to some specific precision as an uncertainty over the range at the first unspecified precision.

The fix for this should involve using uncertainty to model an imprecise DateTime as a range of values. Because the issue only occurs for the combination of mixed precision and time zones differing by a non-full-hour value, we can decide at what level we want to implement the fix: either

  • anytime we compare DateTimes of mixed precision
  • anytime we compare DateTimes of mixed precision and different timezones, or
  • anytime we compare DateTimes of mixed precision and a fractional timezone difference

Codex also suggests the following:

  1. Reuse the existing range machinery, with comparison-specific adjustments. toLuxonUncertainty() (src/datatypes/datetime.ts:638) already constructs lower and upper bounds in the original offset. The existing Uncertainty (src/datatypes/uncertainty.ts:143) comparison methods already implement these boundary rules. Numeric endpoint values would allow their use without recursively invoking DateTime comparisons.
    However, comparison range construction must preserve CQL’s special treatment of seconds and milliseconds: for an implicit-precision comparison, a specified second with omitted milliseconds behaves as a decimal second, rather than an uncertainty spanning that second.

  2. Apply requested precision after normalizing the endpoints. For an explicit hour comparison, for example, convert both endpoints to the evaluation request’s offset and truncate them to hours. Your a then spans hour buckets [08, 09], while b occupies [08, 08], so ordering at hour precision is uncertain. With no explicit precision, preserve the endpoints through the finest relevant precision, producing the definite ordering above. For day or coarser comparisons, retain local calendar fields because those comparisons ignore offsets.

  3. Reconsider the single compareTo() result. Today all comparison operators derive their answer from -1, 0, 1, or null. General uncertainty needs operator-specific answers. For example:

A = [08:30, 09:30]
B = [08:30, 08:30]

A.before(B)       → false
A.after(B)        → null
A.sameOrAfter(B)  → true

One comparison code cannot express all three results. A shared helper returning prepared ranges, followed by separate relational operations, would fit better

主要言語
JavaScript
スター
85
フォーク
40
平均マージ
5日 4時間
マージ済み PR(30日)
3

環境構築

  • Dockerfile・Docker Compose ファイルなし
  • プルリクエストのテンプレートあり
  • コントリビューションガイドなし

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

cqframework/cql-execution のほかの issue

cqframework/cql-execution の issue をすべて見る

似ている issue

JavaScript の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。