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
| Name | Description |
|---|---|
WEEKDAYS | No description. |
Classes
| Name | Description |
|---|---|
Calendar | Загруженный immutable снапшот (§85). |
CalendarError | Ошибка календарного контракта; code — из §85/§85.1. |
TermEnv | Окружение вычисления термов: всё pinned-окружение одного evaluation. |
Functions
| Name | Description |
|---|---|
compute_deadline | Deadline §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.dateoverridesattributeinstance attribute#
overrides: dict[_dt.date, bool]snapshot_idattributeinstance attribute#
snapshot_id: strstartattributeinstance attribute#
start: _dt.dateweekly_workingattributeinstance attribute#
weekly_working: dict[str, bool]CalendarErrorclass#
class CalendarError(code: str, message: str)Bases: Exception
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_versionlegal_timeproperty#
legal_time: strlegalTime контекста §5.1 — обязательная ось, не системные часы.
snapshot_idproperty#
snapshot_id: str | NoneId снапшота — для relatedNodes в issue (§85.1).
calendarmethod#
def calendar() -> Calendarcalendar_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]]enum_member_typemethod#
def enum_member_type(symbol: str) -> str | NoneStableId перечисления, объявившего член symbol, либо None (E-0067).
external_opaquemethod#
def external_opaque(symbol: str) -> dict[str, Any] | Noneexternal_snapshotmethod#
def external_snapshot(symbol: str) -> dict[str, Any] | NoneГраница §47.2 для честного adapter-required отказа без I/O.
functionmethod#
def function(symbol: str) -> dict[str, Any] | Nonefunction_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]) -> Nonereset_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):
- cutoff: если задан и время подачи after_time позже cutoff, старт сдвигается на следующий календарный день;
- start_count = next_day: отсчёт со следующего календарного дня;
- count > 0: день 1 = первый рабочий день >= старта, due = день N; count = 0: due = старт (без счёта);
- include_end = false: действие должно быть совершено до дня окончания — due сдвигается на предыдущий рабочий день;
- roll: применяется к итоговой дате, если она нерабочая (достижимо при count = 0 или пустом счёте); no_roll оставляет дату как есть;
- unit: business_day (по умолчанию) — счёт по рабочим дням; calendar_day — счёт календарными днями (ГК РК ст. 173–175: день N = старт + N-1, затем include_end и roll — здесь roll реально достижим);
- 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) -> Calendarneeds_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.