docs← Back to article

Markdown for LLMs

Separate a monthly step from a working-day roll

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

Download this articlePlain text ↗
# Separate a monthly step from a working-day roll

## Intention

I want to resolve month-end explicitly and roll a non-working cutoff separately.

## Incorrect form and why it stays silent

A monthly step needs a policy carrying month_end:

```text title="Incorrect form"
// Days без month_end
add_calendar_period(@2026-01-31, 1 calendar_month)
```
Monthly and yearly units still require the month_end field; a daily unit does not read that field at all. Without the required roll, the policy declaration itself is also incomplete.

## Correct form

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

source SyntheticCalendar { kind standard; jurisdiction "none"; number "E-CALENDAR"; }
calendar Calendar {
    timezone "Asia/Almaty";
    timezone_db "iana-tzdb@2026a";
    period [@2024-01-01, @2028-01-01);
    source SyntheticCalendar;
    resource "resources/calendar-2024-2027.json";
    format "law.calendar/0.1";
    content_hash "sha256:dfd0181e1347cc2fd48b5fd81d27f3551cabae10eaefbf8b4dffb70bcbb3cd12";
}
deadline policy Months {
    start_count same_day;
    include_end true;
    roll no_roll;
    month_end last_day_of_month;
}
deadline policy Days {
    start_count next_day;
    include_end true;
    roll next_working_day;
}
relation marker();
```

## Frozen execution scene



| Facts / cut | Question | Answer |
|---|---|---|
| Months: 31.01.2026 + 1 month | date | 28.02.2026 |
| Days: end of February, roll by zero business days | date | 02.03.2026 |
| Months: step 1 calendar_day | date | 2026-02-01, COMPUTED — a daily unit does not read month_end |

```law
test "nonexistent day resolves to month end" {
    given {
        context {
            legal_time @2026-03-10;
            decision_time @2027-12-31T09:00:00+05:00;
            knowledge_time @2027-12-31T09:00:00+05:00;
            timezone "Asia/Almaty";
            deadline_policy Months;
        }

    }
    evaluate add_calendar_period(@2026-01-31, 1 calendar_month);
    expect value == @2026-02-28;
    expect evaluation_status == COMPUTED;
}
```

```law
test "month end rolls to working day" {
    given {
        context {
            legal_time @2026-03-10;
            decision_time @2027-12-31T09:00:00+05:00;
            knowledge_time @2027-12-31T09:00:00+05:00;
            timezone "Asia/Almaty";
            deadline_policy Days;
        }

    }
    evaluate add_business_days(month_end_of(@2026-02-10), 0 business_day);
    expect value == @2026-03-02;
}
```

```law
test "daily step under monthly policy computes" {
    given {
        context {
            legal_time @2026-03-10;
            decision_time @2027-12-31T09:00:00+05:00;
            knowledge_time @2027-12-31T09:00:00+05:00;
            timezone "Asia/Almaty";
            deadline_policy Months;
        }

    }
    evaluate add_calendar_period(@2026-01-31, 1 calendar_day);
    expect value == @2026-02-01;
    expect evaluation_status == COMPUTED;
}
```

The calendar is synthetic: Mon–Fri, 9 March 2026 is a conventional non-working day; this is not an official calendar.

## Counterfactual

The third scene shows a daily step under a monthly policy: the computation goes through and month_end is not read. teaches removes roll from Months and gets E1307.

## Boundary

One policy applies to the whole case. A shared composition “month and roll” cannot be promised under two different policies of one query. Here the second query rolls a known month-end through month_end_of; an arbitrary monthly term and its roll need separate explicitly pinned computations.

## Pitfall

A monthly step still requires month_end in the policy, while a daily step ignores the field; the scenario keeps that split and does not substitute a date from outside.