Skip to content

lawref.calendar

Business-календарь: снапшот и операции (WP-06; SPEC §85, §85.1, §86 — подмножество).

Реализовано: проверка datasetHash до вычисления (§85: «несовпадение content_hash — ошибки до вычисления»; T039), покрытие valid-интервала с CALENDAR_OUT_OF_RANGE (§85.1; T040), is_working_day / add_business_days / previous_working_day по weeklySchedule + overrides; DeadlinePolicy §86 — compute_deadline (start_count / include_end / roll / cutoff; отсутствие policy — MISSING_POLICY, неявных вариантов нет). Отложено (по вехам): working_intervals c granularity (§85.1 CALENDAR_GRANULARITY_UNAVAILABLE), timezone-переходы (§86: политики несуществующего/неоднозначного local time — потребуют tzdb-снапшота).

Детерминизм: никакого системного времени/таймзоны — только pinned dataset (FND §7.4).

Attributes

NameDescription
WEEKDAYSNo description.

Classes

NameDescription
CalendarЗагруженный immutable снапшот (§85).
CalendarErrorОшибка календарного контракта; code — из §85/§85.1.
TermEnvОкружение вычисления термов: всё pinned-окружение одного evaluation.

Functions

NameDescription
compute_deadlineDeadline §86 по DeadlinePolicy; возвращает (due, trace для proof-атрибутов).
load_calendarЗагрузка снапшота: digest над байтами ресурса (§85; errata-редакция addendum),
needs_calendarСпрашивает ли ЭТОТ срок рабочий календарь §85.
symbol_tablesТаблицы символов TermEnv по узлам программы — чистая функция от узлов,

WEEKDAYSattributemodule attribute#

WEEKDAYS = ('monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday')

Calendarclassdataclass#

class Calendar(snapshot_id: str, start: _dt.date, end_exclusive: _dt.date, weekly_working: dict[str, bool], overrides: dict[_dt.date, bool])

Загруженный immutable снапшот (§85).

end_exclusiveattributeinstance attribute#

end_exclusive: _dt.date

overridesattributeinstance attribute#

overrides: dict[_dt.date, bool]

snapshot_idattributeinstance attribute#

snapshot_id: str

startattributeinstance attribute#

start: _dt.date

weekly_workingattributeinstance attribute#

weekly_working: dict[str, bool]

add_business_daysmethod#

def add_business_days(day: _dt.date, days: int) -> _dt.date

§85.1: обязательная операция add_business_period для business_day (§84.3).

is_working_daymethod#

def is_working_day(day: _dt.date) -> bool

§85.1: обязательный запрос is_working_day; overrides сильнее weeklySchedule.

previous_working_daymethod#

def previous_working_day(day: _dt.date) -> _dt.date

Ближайший рабочий день строго раньше day (перенос «накануне»).

§86: значение roll = previous_working_day политики срока; рабочесть дня берётся из is_working_day §85.1, а не из ambient-календаря.

CalendarErrorclass#

class CalendarError(code: str, message: str)

Bases: Exception

Ошибка календарного контракта; code — из §85/§85.1.

codeattributeinstance attribute#

code = code

messageattributeinstance attribute#

message = message

TermEnvclass#

class TermEnv(snapshot: dict[str, Any] | None, resource_bytes: bytes | None, deadline_policy: dict[str, Any] | None, legal_time: str, nodes: list[dict[str, Any]] | None = None, external_resources: list[dict[str, Any]] | None = None, effective_context: dict[str, Any] | None = None, snapshot_program_hash: str = '', tables: dict[str, dict] | None = None, semantic_version: str = '0.1.0')

Окружение вычисления термов: всё pinned-окружение одного evaluation.

Помимо календаря и DeadlinePolicy здесь находится immutable-индекс чистых FunctionDecl. Это НЕ второй интерпретатор: тела функций остаются обычными CLIR Term и исполняются values.eval_term. Индекс лишь связывает CallTerm.function с декларацией и собирает детерминированный trace для proof graph (§A3.2/§A3.6).

Существует ровно потому, что add_business_days §86 — не чистая функция аргументов: календарь и политика приходят из окружения (calendar = context.calendar, policy = context.deadline_policy в нормативном примере §86). Глобала здесь быть не может: окружение живёт одно evaluation и входит в манифест через снапшот и контекст, а не через состояние модуля.

Загрузка календаря ЛЕНИВАЯ: пакет без единого календарного терма не обязан иметь валидный датасет, а §85 «ошибки до вычисления» остаются за calendar_op-запросом (T039) — иначе hash mismatch менял бы момент отказа.

semantic_versionattributeinstance attribute#

semantic_version = semantic_version

legal_timeproperty#

legal_time: str

legalTime контекста §5.1 — обязательная ось, не системные часы.

snapshot_idproperty#

snapshot_id: str | None

Id снапшота — для relatedNodes в issue (§85.1).

calendarmethod#

def calendar() -> Calendar

calendar_periodmethod#

def calendar_period(after: _dt.date, count: int, unit: str) -> tuple[_dt.date, dict[str, Any]]

§84.2/§86 add_calendar_period(after, count, policy) — errata E-0029.

Календарь §85 не запрашивается вовсе: у этого терма пути к нему нет. До E-0029 та же операция шла через deadline() с предикатом needs_calendar, то есть требование снимка зависело от политики и не читалось в норме; на этой условности реализации молча разошлись.

roll и cutoff здесь отвергаются, а не игнорируются: допустить их значило бы вернуть снимок через политику. include_end обязан быть true по той же причине — при false итог зависит от рабочести дня.

deadlinemethod#

def deadline(after: _dt.date, count: int, unit: str, after_time: str | None) -> tuple[_dt.date, dict[str, Any]]

§86 add_business_days(after, count, calendar, policy): policy — из материализованного контекста §89; её отсутствие — MISSING_POLICY.

enum_member_typemethod#

def enum_member_type(symbol: str) -> str | None

StableId перечисления, объявившего член symbol, либо None (E-0067).

external_opaquemethod#

def external_opaque(symbol: str) -> dict[str, Any] | None

external_snapshotmethod#

def external_snapshot(symbol: str) -> dict[str, Any] | None

Граница §47.2 для честного adapter-required отказа без I/O.

functionmethod#

def function(symbol: str) -> dict[str, Any] | None

Разрешить pure FunctionDecl §46 по StableId символа §14.

function_symbolmethod#

def function_symbol(symbol: str) -> dict[str, Any] | None

Вернуть SymbolDecl для проверки return type §46.

function_tracemethod#

def function_trace() -> list[dict[str, Any]]

Копия trace §179: вызывающий не может изменить состояние evaluation.

is_a3_parametermethod#

def is_a3_parameter(symbol: str) -> bool

Функция объявлена параметром-датасетом A3 §A3.2, а не телом §46.

notemethod#

def note(issue: dict[str, Any]) -> None

Записать информационный issue вывода (§64.2) без дубликатов.

notesmethod#

def notes() -> list[dict[str, Any]]

Информационные issue, накопленные за evaluation — в порядке первого появления, дальше их сортирует канон документа §208.

read_external_snapshotmethod#

def read_external_snapshot(symbol: str, args: list[Any], where: str)

Read exactly one typed call from a supplied pinned dataset (§60).

record_function_callmethod#

def record_function_call(entry: dict[str, Any]) -> None

Записать вызов §46 в trace — посылка узла function_evaluation §179.

reset_function_tracemethod#

def reset_function_trace() -> None

Начать trace одного терм-запроса (узлы function_evaluation §179).

tables_ofmethodstaticmethod#

def tables_of(nodes: list[dict[str, Any]] | None) -> dict[str, dict]

Таблицы символов по узлам — то, что вид программы кэширует.

unit_tablemethod#

def unit_table() -> dict[str, dict[str, Any]]

Реестр объявлений единиц §49.2 закреплённого CLIR (errata E-0136).

compute_deadlinefunction#

def compute_deadline(cal: Calendar | None, after: _dt.date, count: int, policy: dict[str, Any] | None, after_time: str | None = None, unit: str = 'business_day', suspensions: Any = None, calendar_day_step: bool = False) -> tuple[_dt.date, dict[str, Any]]

Deadline §86 по DeadlinePolicy; возвращает (due, trace для proof-атрибутов).

Policy обязательна: «если policy не задана явно или profile-ом, compilation/evaluation завершается MISSING_POLICY» — никакого неявного варианта. V1-конвенции семантики (уточнение — normative examples WP-09):

  1. cutoff: если задан и время подачи after_time позже cutoff, старт сдвигается на следующий календарный день;
  2. start_count = next_day: отсчёт со следующего календарного дня;
  3. count > 0: день 1 = первый рабочий день >= старта, due = день N; count = 0: due = старт (без счёта);
  4. include_end = false: действие должно быть совершено до дня окончания — due сдвигается на предыдущий рабочий день;
  5. roll: применяется к итоговой дате, если она нерабочая (достижимо при count = 0 или пустом счёте); no_roll оставляет дату как есть;
  6. unit: business_day (по умолчанию) — счёт по рабочим дням; calendar_day — счёт календарными днями (ГК РК ст. 173–175: день N = старт + N-1, затем include_end и roll — здесь roll реально достижим);
  7. suspensions (D2, DECISION-0008 §3.2): окна приостановления течения срока. День внутри окна НЕ является днём течения ни в какой единице: due — N-й СЧИТАЮЩИЙСЯ день, начиная со старта, где считающийся — рабочий (business_day) либо любой (calendar_day) день вне окон. Без окон обе ветви дают ровно прежний результат, поэтому байты существующих голденов не двигаются; поля suspension* появляются в trace ТОЛЬКО при непустых окнах — по той же причине.

Приостановление применяется к СЧЁТУ, а не к границам: include_end и roll работают поверх полученной даты как раньше (окно на итоговой дате её не сдвигает — сдвигают только нерабочесть и include_end).

load_calendarfunction#

def load_calendar(snapshot_node: dict[str, Any], resource_bytes: bytes) -> Calendar

Загрузка снапшота: digest над байтами ресурса (§85; errata-редакция addendum), schema-валидация датасета и инварианты §85.1 — всё ДО первого вычисления (T039).

needs_calendarfunction#

def needs_calendar(unit: str, policy: dict[str, Any] | None) -> bool

Спрашивает ли ЭТОТ срок рабочий календарь §85.

Календарный шаг §84.2 с no_roll и include_end не обращается к календарю ни разу: месяцы и годы считаются по датам, а не по рабочим дням. Требовать при этом закреплённый снимок праздников значило бы делать норму неисполнимой из-за данных, которых она не читает, — срок полномочий «семь лет» истекает в 2033 году, и календарь на 2033-й ему не нужен. Дневные единицы календарь спрашивают ВСЕГДА: даже при no_roll is_working_day вызывается (левый операнд and в проверке ниже), и менять это errata E-0026 не вправе — она про новые единицы.

symbol_tablesfunction#

def symbol_tables(nodes: list[dict[str, Any]] | None) -> dict[str, dict]

Таблицы символов TermEnv по узлам программы — чистая функция от узлов, которую вид программы (evaluator.prepared) считает один раз: функции §46, их символы, внешние снимки и непрозрачные границы §47.2, члены перечислений §38/§57 (errata E-0067: StableId члена {namespace}#{Член} → StableId объявившего перечисления; индекс питает ветку const_ref eval_term — член есть значение-идентичность, а не мёртвая ссылка).

Documentation for Arxo. Writings — blog.arxo.io.

Anonymous visit counts on stats.arxo.io, no cookies.