# Time: effective, legal time, duration, editions **In one sentence:** time answers the question "as of which date the case is computed": `effective` switches rules on and off by legal time (`legal_time`), `days_between` measures duration in days, and an edition anchor (`@source` + `in_force`) dates a node by the act's applicability. Take them when a norm holds "from … to …", a period counts in days, or an article enters into force later than the case. Legal time switches norms on and off, durations are measured in days, and edition anchors date nodes by the act's applicability. ## 1. When to take it and when not to | Instead of | Selection rule | |---|---| | Rule `effective` vs target `window` | "Norm holds from 1 March" — `effective [@2026-03-01, infinity);` on the rule: outside the window there is no position at all. "Perform by 31 March" — target `window`: the position exists (`PENDING`/`UNDETERMINED`), the deadline has/has not passed. Different answers: "no norm yet" vs "period not started yet" | | `effective` vs edition anchor | The rule's own commencement date — `effective`. The act's commencement date — edition lifecycle (`in_force`), to whose fragment `@source` leads: the node is dated by the anchor. A rule without `effective` but anchored to a future edition does not participate at an early date | | `days_between` vs date addition | Duration is only measured: `days_between(due, paid) >= 30`. `due + 30 days` — refusal `LDC-E2108` (a date does not add a magnitude); `days_between(due, paid) >= 30 days` — the same refusal (`Quantity` vs `Integer`). A period is built by the period step (`add_calendar_period`) | | `Date` vs `Instant` | Civil date (`@2026-03-01`) — to a date; instant with offset (`@2026-03-01T09:00:00+05:00`) — to an instant. Mixing: statically `LDC-E2108`, in an execution term — `TYPE_ERROR`. Instants compare by moment, not by spelling | | Fact-date comparison in the body vs `governs` | Retroactivity in an act whose cases are written on the surface — by comparing the fact date in the body (so does the corpus). `governs event_time …` executes in the engine, but the surface does not record the axis onto a fact (`assert … { valid …; }` writes only `valid_time`), and a `.lawtest` case will never support such a rule | ## Grammar: time and dating (EBNF verbatim from the grammar) Time literals — dates, instants, their bodies, and the offset (where text and grammar differ, the grammar is canonical): ```ebnf temporal_literal = date_literal | time_literal | datetime_literal ; date_literal = "@", digit, digit, digit, digit, "-", digit, digit, "-", digit, digit ; time_literal = "@", digit, digit, ":", digit, digit, ":", digit, digit, [ ".", digit, { digit } ] ; datetime_literal = date_literal_body, "T", time_literal_body, ( "Z" | offset ) ; date_literal_body = "@", digit, digit, digit, digit, "-", digit, digit, "-", digit, digit ; time_literal_body = digit, digit, ":", digit, digit, ":", digit, digit, [ ".", digit, { digit } ] ; offset = ( "+" | "-" ), digit, digit, ":", digit, digit ; ``` Intervals — brackets and endpoints (`infinity`/`-infinity` are legal): ```ebnf interval_expression = expression ; interval_literal = interval_left, interval_endpoint, ",", interval_endpoint, interval_right ; interval_left = "[" | "(" ; interval_right = "]" | ")" ; interval_endpoint = expression | "infinity" | "-infinity" ; ``` Applicability qualifiers — the rule validity window and the regulated-event window: ```ebnf effective_clause = "effective", interval_literal, ";" ; governs_clause = "governs", identifier, interval_literal, ";" ; ``` Edition lifecycle events — dating nodes through the anchor: ```ebnf lifecycle_item = "adopted", temporal_literal, ";" | "published", temporal_literal, ";" | "in_force", interval_literal, ";" | "suspended", interval_literal, ";" | "restored", temporal_literal, ";" | "repealed", temporal_literal, ";" | "expired", temporal_literal, ";" | "invalidated", temporal_literal, ";" ; ``` ## 2. Minimal example Package `research.constructs.time_effective`: a liability regime in force since 2026. Full code — the example package. ```law rule PenaltyRegime2026 strict { effective [@2026-01-01, infinity); for p: Payer; when registered_payer(p); then penalty_regime_applies(p); } ``` Case facts: `registered_payer(alpha)`. Query: `evaluate truth(penalty_regime_applies(alpha))`. Observed engine answer (installed `law`, semantics `law.core/0.2`): ```text law test research.constructs.time_effective: мир research.constructs.time_effective ok [research.constructs.time_effective#authored] tests/01-regime-active.lawtest / urn:query:research-time-01 ok [research.constructs.time_effective#authored] tests/02-regime-inapplicable.lawtest / urn:query:research-time-02 итого: 2 проверено, 2 прошли, 0 не прошли, 0 не исполнены; код 0 ``` `law engine check` — `check OK`, no warnings. Sensitivity: changing `legal_time` from `@2026-06-01` to `@2025-06-01` with the same facts changes the answer from `TRUE_ONLY` to `NEITHER` — the rule does not participate (`NOT_APPLICABLE`), not "condition false"; removing the `registered_payer` fact at a date inside the window gives the same `NEITHER` by another route (body silence). The example is not vacuous. Nearest wrong outcome: cutting the `effective` clause — the 2025 case answers `TRUE_ONLY` instead of `NEITHER` (counterfactual: the window decides). ## 3. Example by domain - **Law:** finite disability-benefit window (package `kz.corpus.socialcode`, Kazakhstan) — three rules with `effective [@2023-07-01, @2027-01-01)`: a window with an end, not just a start (see `corpus-forms.md`). - **Law:** "no earlier than N days" as a guard (package `tr.constitution`, Türkiye) — `days_between(submitted, year_start) >= 75` and the mirrored `< 75`: a pair of thresholds on one measure. - **Standard/protocol:** timely attestation (package `us.code.apportionment`, United States) — `days_between(receipt, sent) <= 15`: "within fifteen calendar days" as a measured-duration comparison. - **Law:** period by calendar step (package `intl.vienna.succession_treaties`, international) — `during [appointed, add_calendar_period(appointed, 60 calendar_day)]`: months and years are not measured but built by the period step. - **Teaching case:** `research.constructs.time_overdue` — the "thirty or more days" threshold (`days_between(due, paid) >= 30`): 41 days — `TRUE_ONLY`, 22 days — `NEITHER` (the rule stays silent, it does not refuse). - **Law:** detention over four days (package `tr.constitution`, Türkiye) — `days_between(started, until) > 4` in a defeated rule with two `unless` provisos — delivery to a judge and extension under emergency/war: the same duration measure inside a more complex norm. ## 4. How the engine answers Table — observed runs of this directory's examples (installed `law`, semantics `law.core/0.2`): | Legal time | Facts | Question | Answer | Why | |---|---|---|---|---| | `@2026-06-01` | `registered_payer` | `penalty_regime_applies` | `TRUE_ONLY` | `effective` window contains the legal time | | `@2025-06-01` | same | same | `NEITHER` | `effective` starts `@2026-01-01` — rule does not participate | | `@2026-03-01` | due 10.01, paid 20.02 | `overdue_30` | `TRUE_ONLY` | `days_between` = 41 ≥ 30 | | `@2026-03-01` | due 10.01, paid 01.02 | `overdue_30` | `NEITHER` | 22 < 30 — silent, not refusing | - Four context axes: `legal_time` (the law in force), `decision_time` (result moment), `knowledge_time` (data boundary), `timezone`. No axis is taken from the system clock. - A window without `legal_time` gives the rule `NOT_APPLICABLE`: answer `NEITHER`, `why_not` names the candidate with this status. - A node with anchors is excluded when ALL its dating editions are inapplicable at `legal_time`: the document carries issue `EDITION_NOT_APPLICABLE` (info), `why_not` — `NOT_APPLICABLE`. An edition with only `adopted`/`published` or `timeless` is outside dating: the node is excluded on no date. - Duration: `days_between` gives an `Integer` of calendar days, negative on reversed order; hours and minutes — `hours_between`, `minutes_between` over `Instant`. Documented outcomes (earlier scenarios): | Law date | Facts | Question | Answer | Why | |---|---|---|---|---| | `@2025-06-01` | two memberships, one licence | `licensed(acme, trade)` | `FALSE_ONLY` | closure in-window — explicit negative | | `@2026-03-01` | same | same | `NEITHER` | closure window closed | | `@2026-03-01` | same, closure `effective` cut out | same | `FALSE_ONLY` | counterfactual: the window decides | | `@2026-03-01` | `debt_settled` | `penalty_waived` | `NEITHER` + `EDITION_NOT_APPLICABLE` | the 2027 edition is `not_yet` | | `@2027-03-01` | same | same | `TRUE_ONLY` | edition in force | | `@2026-03-01` | same, `@source` anchor cut out | same | `TRUE_ONLY` | counterfactual: the anchor dates the node | | — | `days_between(@2026-02-20, @2026-01-10)` | DATA | `-41` | sign follows argument order | | — | `days_between(@2026-01-10, @2026-02-20T00:00:00Z)` | DATA | `TYPE_ERROR` | `Date` versus `Instant` | | `@2026-03-01` | filing `2025-12-31T23:30:00Z` | `filed_before_2026` | `NEITHER` | by moment — 04:30 1 January Almaty | | `@2026-03-01` | filing `2025-12-31T18:00:00Z` | `filed_before_2026` | `TRUE_ONLY` | 23:00 31 December Almaty | ## 5. Common mistakes 1. Rule silent on every date: check `legal_time` against `effective` and against the `in_force` of the edition `@source` leads to (`pitfalls.md`, item 1). 2. `Date` vs `Instant`: `check` — `LDC-E2108`, execution — `TYPE_ERROR` (`pitfalls.md`, item 2). 3. "30 days" as a magnitude: `days_between(…) >= 30 days` and `due + 30 days` — `LDC-E2108` (`pitfalls.md`, item 3). 4. Name in a window bound: `effective [start, infinity)` with an undeclared name — `LDC-E1305`; a bare name in a target window — `LDC-E2115` (`pitfalls.md`, item 4). 5. `timeless` together with lifecycle — `LDC-E1305`: two incompatible models of one edition (`pitfalls.md`, item 5). 6. `during`/`overlaps`/`before`/`after` as predicates — `LDC-E2102` (RESERVED); time conditions are written as date comparisons (`pitfalls.md`, item 6). 7. Term window bound without a period policy — `MISSING_POLICY` (`pitfalls.md`, item 7). ## 6. References - Tutorials: [real article source](/tutorials/real-article-source/), [pinned edition](/tutorials/pinned-edition/), [closed world](/tutorials/closed-world/). - Neighbouring pages: [sources](/constructs/sources/) (dating through the anchor), [negation and truth statuses](/constructs/negation-and-status/) (closure window), [expressions and quantities](/constructs/expressions-quantities/) (duration measurement), [strict rules](/constructs/rule-strict/) (rule validity window).