Expand description
Every Frist in German market communication, in one leaf crate.
Deadlines are the regulatory asset this platform is built around, and this
crate is the one answer to “when is this due”. It depends on nothing but
time, so every service can read it without pulling in a workflow engine —
which is what keeps the calendar, the per-Prüfidentifikator answer tables and
the alerting from each carrying a copy that disagrees with the others.
| Question | Answer |
|---|---|
| What is today’s date, in the market’s terms? | heute, berlin_date, berlin_midnight, berlin_now |
| When is the 4th Werktag after this instant? | add_werktage, deadline_at_werktage, end_of_werktag_after, next_werktag_at |
| Which window does PID 55001 carry? | antwort |
| Which messages does receiving it oblige me to send? | meldung |
| When must the CONTRL / APERAK go out? | contrl_due_at, aperak_strom_due_at, aperak_gas_folgeprozess_due_at, aperak_gas_initialprozess_due_at |
mako-engine re-exports this crate as mako_fristen, so existing
call sites are unchanged.
§Three clocks, never one number
The mistake this crate is shaped to prevent is treating any of these as the others. They differ by orders of magnitude and they fail for different reasons.
| Clock | Window | Meaning |
|---|---|---|
| CONTRL | 6 wall-clock hours; 15 min for a Strom UTILMD/ORDERS Syntaxfehlermeldung (6 h on a Saturday), 45 min for a GABi-Gas ALOCAT; deferred to the end of a Formatumstellung window (CONTRL AHB 1.0 §2.3.1, §2.4.1) | the syntax check of the Übertragungsdatei |
| APERAK | 45 min Strom weekday; Gas: next Werktag 12:00 (Folgeprozess) or 3 Werktage (Initialprozess) | the message was accepted for processing |
| Antwortfrist | per PID — 11:00 of the 1. Werktag for a GPKE Anmeldung, 4 Werktage for a Gas Anmeldung, 3/5/7/1 WT for WiM Strom | the business answer is owed |
There is no 24-hour GPKE window, under BK6-24-174 or anything else.
The technical acknowledgement is 45 minutes
(aperak_strom_due_at) and the business answer is a wall-clock instant on
the first Werktag after the Übertragungstag (mako-pruefung). A flat 24 h is
neither, and it is wrong in the direction that does not announce itself: it
reports a lapsed Frist as still running.
§Werktage
use mako_fristen::{self as fristen, HolidayCalendar};
use time::{Date, Month};
// 5 Werktage after Monday 2025-01-06:
let start = Date::from_calendar_date(2025, Month::January, 6).unwrap();
let due = fristen::add_werktage(start, 5, HolidayCalendar::BdewMaKo);
// Tue 07, Wed 08, Thu 09, Fri 10, Mon 13 → 2025-01-13
// (Saturday and Sunday are not Werktage in market communication)
assert_eq!(due, Date::from_calendar_date(2025, Month::January, 13).unwrap());§Holiday calendar: BDEW-defined, Germany-wide
HolidayCalendar::BdewMaKo is the single holiday calendar used in all
BNetzA MaKo processes. BDEW EDI@Energy specifies a conservative-inclusive
approach: every public holiday observed in any German state is treated as
a non-Werktag. This guarantees no Frist is ever shorter than the AHB
requires. Per-state calendars are not used in BDEW MaKo.
§CONTRL Übertragungsquittung
use mako_fristen::{self as fristen, ContrlAnlass};
use time::{Date, Month, OffsetDateTime, Time};
let received = OffsetDateTime::new_utc(
Date::from_calendar_date(2026, Month::September, 9).unwrap(),
Time::from_hms(9, 0, 0).unwrap(),
);
let due = fristen::contrl_due_at(received, ContrlAnlass::Regelfall);
assert_eq!(due - received, time::Duration::hours(6));Modules§
- abmeldung
- Vorlauffristen der NB-seitigen Abmeldung — how far ahead the grid operator must announce that a supplier’s assignment ends.
- antwort
- The business answer Frist per inbound Prüfidentifikator.
- meldung
- Meldepflichten — messages a Festlegung obliges a party to send, with no answer of their own.
- vorlauf
- Vorlauffristen — the windows anchored on a date the message carries.
Enums§
- Contrl
Anlass - What the CONTRL is answering — the pair that decides its window.
- Holiday
Calendar - Selects which set of public holidays to observe when counting Werktage.
Constants§
- APERAK_
GAS_ FOLGEPROZESS_ LABEL - Deadline label for Gas APERAK sending obligations on Folgeprozesse.
- APERAK_
GAS_ INITIALPROZESS_ LABEL - Deadline label for Gas APERAK sending obligations on Initialprozesse.
- APERAK_
STROM_ WEEKDAY_ MINUTES - Minutes within which a Strom APERAK must be sent on weekdays (Mon–Fri).
- APERAK_
STROM_ WINDOW_ LABEL - Deadline label for Strom APERAK 45-minute sending obligations.
- APERAK_
WINDOW_ LABEL_ PREFIX - Shared prefix of every APERAK delivery-window label.
- CONTRL_
ALOCAT_ MINUTEN - Minutes within which the CONTRL on a GABi-Gas ALOCAT must go out (CONTRL AHB 1.0 §2.3.1).
- CONTRL_
FRIST_ HOURS - The default wall-clock hours within which a CONTRL must be sent after receiving an EDIFACT interchange or APERAK.
- CONTRL_
FRIST_ LABEL - Deadline label used in the
DeadlineStorefor CONTRL delivery obligations. - CONTRL_
STROM_ SCHNELL_ MINUTEN - Minutes within which a Strom Syntaxfehlermeldung on a UTILMD or ORDERS must go out on a day other than Saturday (CONTRL AHB 1.0 §2.4.1).
- GAS_
INITIALPROZESS_ PIDS - The Gas Prüfidentifikatoren that open a business process — the Initialprozessschritte, which carry the 3-Werktage APERAK window instead of the next-Werktag-noon one.
Functions§
- add_
hours - Add
hourswall-clock hours tofrom. - add_
months - Shift a date
ncalendar months forward, clamping to the month’s last day. - add_
werktage - Add
nWerktage (working days) tofrom. - aperak_
gas_ due_ at - The Gas APERAK sending deadline for an inbound Geschäftsvorfall, chosen by its Prüfidentifikator.
- aperak_
gas_ folgeprozess_ due_ at - Compute the Gas APERAK sending deadline for Folgeprozesse.
- aperak_
gas_ initialprozess_ due_ at - Compute the Gas APERAK sending deadline for Initialprozesse.
- aperak_
hat_ anerkennungsmeldung - Whether the Sparte’s APERAK regime has a positive acknowledgement at all.
- aperak_
strom_ due_ at - Compute the Strom APERAK sending deadline after receiving a Strom UTILMD or ORDERS message.
- berlin_
at - Construct an
OffsetDateTimeatatEurope/Berlin ondate, in UTC. - berlin_
date - The Europe/Berlin calendar date of
instant. - berlin_
midnight - The instant at which the Europe/Berlin calendar day
datebegins, expressed in UTC. - berlin_
now - Now, expressed in the Europe/Berlin offset.
- contrl_
due_ at - Compute the CONTRL delivery deadline for
anlass. - deadline_
at_ werktage - Compute a deadline
werktageWerktage afterfrom, expressed as anOffsetDateTimeat 17:00 Europe/Berlin on the deadline date. - discharges_
delivery_ window - Does delivering
message_typedischarge the delivery windowlabel? - end_
of_ day_ berlin - The last moment of
datein Europe/Berlin. - end_
of_ werktag_ after - „unverzüglich, spätestens jedoch bis zum Ablauf des
werktage. Werktags nach Eingang“ — the GeLi Gas answer-Frist shape. - heute
- Today, as the German market states it — the Europe/Berlin calendar date.
- is_
werktag - Return
truewhendateis a Werktag undercal. - next_
werktag - Return the first Werktag that is on or after
from. - next_
werktag_ at - „… Uhr des 1. Werktags nach dem ÜT“ — the dominant answer-Frist shape in GPKE Teil 2.
- nth_
werktag_ at - „Unverzüglich, jedoch spätester ÜZ ist
atUhr desn. WT nach dem ÜT.“ - sub_
werktage - Subtract
nWerktage fromfrom— the mirror ofadd_werktage. - subtract_
months - Shift a date
ncalendar months back, clamping to the month’s last day. - werktage_
between - How many Werktage separate
fromandto— the inverse ofadd_werktage.