docs← Back to article

Markdown for LLMs

Keep interval bounds open

The source Markdown for this article. Copy it into your assistant or download it as a text file.

Download this articlePlain text ↗
# Keep interval bounds open

## Intention

I want to include the start date in full and exclude the end date in full.

## Incorrect form and why it stays silent

A zone in context does not replace a Date→Instant policy:

```text title="Incorrect form"
// CivilDay удалена; окно Date сравнивается с legal_time Instant.
```
An undeclared name boundary instead of a date is a separate compiler rejection.

## Correct form

```law
language "law.core" version "0.2";
package recipes.e.r12 version "0.1.0";
namespace "urn:recipe:e-time:12";

entity Person;
relation registered(p: Person);
temporal_resolution_policy CivilDay {
    utc_offset "+05:00";
    day_boundary "00:00:00";
    timezone "Asia/Almaty";
}
relation submitted(p: Person);
rule Report strict {
    for p: Person;
    when registered(p);
    then duty File {
        bearer p;
        goal achievement {
            condition submitted(p);
            window [@2026-03-10, @2026-03-11);
        }
    };
}
rule ClosedRule strict {
    for p: Person;
    when registered(p);
    then duty Closed {
        bearer p;
        goal achievement {
            condition submitted(p);
            window [@2026-03-10, @2026-03-11];
        }
    };
}

rule OpenLeftRule strict {
    for p: Person;
    when registered(p);
    then duty OpenLeft {
        bearer p;
        goal achievement {
            condition submitted(p);
            window (@2026-03-10, @2026-03-12];
        }
    };
}

rule OpenBothRule strict {
    for p: Person;
    when registered(p);
    then duty OpenBoth {
        bearer p;
        goal achievement {
            condition submitted(p);
            window (@2026-03-10, @2026-03-12);
        }
    };
}

```

## Frozen execution scene



| Facts / cut | Question | Answer |
|---|---|---|
| 10.03 00:00 | File | ACTIVE |
| 10.03 23:59 | File | ACTIVE |
| 11.03 00:00 | File | UNDETERMINED |
| legal_time Date 11.03, closed end | Closed | ACTIVE |
| legal_time Date 10.03, open start | OpenLeft, OpenBoth | PENDING |
| without CivilDay, cut at an instant | positions | ACTIVE, COMPUTED without issue — divergence from the required fatal rejection |

```law
test "included start activates" {
    given {
        context {
            legal_time @2026-03-10T00:00:00+05:00;
            decision_time @2026-03-10T00:00:00+05:00;
            knowledge_time @2027-12-31T09:00:00+05:00;
            timezone "Asia/Almaty";
        }
        assert registered(entity_ref("urn:recipe:e-time:12:a"));
    }
    evaluate positions();
    expect position(File, ACTIVE);
}
```

```law
test "last minute stays active" {
    given {
        context {
            legal_time @2026-03-10T23:59:00+05:00;
            decision_time @2026-03-10T23:59:00+05:00;
            knowledge_time @2027-12-31T09:00:00+05:00;
            timezone "Asia/Almaty";
        }
        assert registered(entity_ref("urn:recipe:e-time:12:a"));
    }
    evaluate positions();
    expect position(File, ACTIVE);
}
```

```law
test "excluded end releases duty" {
    given {
        context {
            legal_time @2026-03-11T00:00:00+05:00;
            decision_time @2026-03-11T00:00:00+05:00;
            knowledge_time @2027-12-31T09:00:00+05:00;
            timezone "Asia/Almaty";
        }
        assert registered(entity_ref("urn:recipe:e-time:12:a"));
    }
    evaluate positions();
    expect position(File, UNDETERMINED);
}
```

```law
test "unresolved granularity still answers" {
    given {
        context {
            legal_time @2026-03-10T12:00:00+05:00;
            decision_time @2026-03-10T12:00:00+05:00;
            knowledge_time @2027-12-31T09:00:00+05:00;
            timezone "Asia/Almaty";
        }
        assert registered(entity_ref("urn:recipe:e-time:12:a"));
    }
    evaluate positions();
    expect position(File, ACTIVE);
    expect not issue(TEMPORAL_RESOLUTION_POLICY_MISSING);
}
```

```law
test "closed date includes full day" {
    given {
        context {
            legal_time @2026-03-11;
            decision_time @2026-03-11T12:00:00+05:00;
            knowledge_time @2027-12-31T09:00:00+05:00;
            timezone "Asia/Almaty";
        }
        assert registered(entity_ref("urn:recipe:e-time:12:a"));
    }
    evaluate positions();
    expect position(Closed, ACTIVE);
}
```

```law
test "open start excludes first day" {
    given {
        context {
            legal_time @2026-03-10;
            decision_time @2026-03-10T12:00:00+05:00;
            knowledge_time @2027-12-31T09:00:00+05:00;
            timezone "Asia/Almaty";
        }
        assert registered(entity_ref("urn:recipe:e-time:12:a"));
    }
    evaluate positions();
    expect position(OpenLeft, PENDING);
    expect position(OpenBoth, PENDING);
}
```

## Counterfactual

runs.without removes CivilDay. A fatal missing-policy refusal is required, but both implementations answer ACTIVE with empty issues — remeasured with the decision date named explicitly. The scene records the observation and does not treat it as the norm. This is a defect of both implementations, still live. teaches separately substitutes an unresolved name for a date and requires E2115.

## Boundary

For [D1,D2] day D2 is included in full; for [D1,D2) it is not included by any instant. infinity is allowed for an ordered extension, as with immunity in [Limit a legal change with immunity](/recipes/e-time/retroactivity-immunity/). A mixed window comparison without a policy cannot be treated as correct because of a green answer: the current check gap is documented in the counterfactual. The corrected form always presents CivilDay.

## Pitfall

A closed date includes the civil day, an open one excludes it; mixed comparison without a policy is inadmissible. The probe checks exactly midnight of the excluded day.