regit-daycount 1.0.0

Day-count fractions and business-day calendars in pure Rust — Act/360, Act/365F, ActAct ISDA, ActAct ICMA, 30/360, 30E/360, Bus/252; TARGET2, US, UK, JP, CH, HK, SG holiday calendars; all date-roll conventions. Zero dependencies, no_std, no alloc.
Documentation
regit-daycount-1.0.0 has been yanked.

regit-daycount

Day-count fractions and business-day calendars. Zero-dependency, pure Rust, no_std.

License Rust no_std

What it does

regit-daycount computes the year fraction between two dates under every common day-count fraction (Act/360, Act/365F, ActAct ISDA, ActAct ICMA, 30/360 BondBasis, 30E/360, 30E/360 ISDA, Act/365L, NL/365, Bus/252, 1/1), adjusts a date for a non-business day under every common date-roll convention (Unadjusted, Following, ModifiedFollowing, Preceding, ModifiedPreceding, Nearest, EndOfMonth), and classifies dates against the major holiday calendars (TARGET2, United States, United Kingdom, Japan, Switzerland, Hong Kong, Singapore, plus composite and joint-business combinations).

Date primitives — a Gregorian Date { year, month, day }, the leap-year and days-in-month rules, the day-of-week computation, fixed and Easter-based holiday algorithms — are own-rolled, zero-dependency, Copy.

Every algorithm is traced to a citable standard in SPEC.md. An auditor, a structurer, or a new engineer can open any source file and check it against ISDA 2006 §4.16, ICMA Rule 251, the ISO 8601 weekday rule, or the published calendar of the exchange or central bank in question.

Why this crate exists

A coupon is paid on a date. An accrued-interest amount is settled to a date. A swap leg is discounted from a date. Every one of those operations is parameterised by two conventions — which day-count fraction, which holiday calendar — and a wrong choice, or a correct choice computed wrongly, silently produces a wrong cashflow.

The algorithms are deceptively easy to get subtly wrong. Act/Act ISDA straddling a year-end splits the interval at midnight on 1 January and uses two different denominators on the two sides. 30E/360 ISDA treats the last day of February specially — but only when it is not the maturity date. ModifiedFollowing falls back to Preceding when the Following adjustment would cross a month boundary. TARGET2 is open on every weekday except 1 January, Good Friday, Easter Monday, 1 May, 25 December, and 26 December — and Easter is a function of the year. A library that gets any of these wrong reports a wrong number that downstream systems will trust.

regit-daycount implements each convention from its governing standard, verifies it against worked examples for real instruments, and ships the verification alongside the code. It is no_std and allocation-free, so the same audited logic runs in a backend service, a WASM bundle, or on an embedded device with no change.

This sits within Regit OS: regit-daycount is the time-and-calendar layer — the component that decides what fraction of a year a given date interval represents, and whether a given date is one on which a market is open.

Quick start

[dependencies]
regit-daycount = "0.1"
use regit_daycount::{Calendar, Date, DayCount, Roll, calendar, day_count};

// Year fraction under Act/360 for a 90-day interval.
let start = Date::ymd(2026, 1, 1).unwrap();
let end   = Date::ymd(2026, 4, 1).unwrap();
let yf    = day_count::fraction(start, end, DayCount::Act360);
assert!((yf - 90.0 / 360.0).abs() < 1e-12);

// Roll a date forward to the next TARGET2 business day.
let saturday = Date::ymd(2026, 5, 2).unwrap();
let monday   = calendar::adjust(saturday, Roll::Following, Calendar::Target2);
assert_eq!(monday, Date::ymd(2026, 5, 4).unwrap());

// Is 2026-12-25 a TARGET2 holiday?
assert!(calendar::is_holiday(Date::ymd(2026, 12, 25).unwrap(), Calendar::Target2));

See examples/quickstart.rs for a complete tour covering every day-count fraction, every date-roll convention, and every calendar.

Day-count fractions covered

Fraction Standard Module
Act/360 ISDA 2006 §4.16(e) day_count::act_360
Act/365F (Fixed) ISDA 2006 §4.16(d) day_count::act_365f
ActAct ISDA ISDA 2006 §4.16(b) day_count::act_act_isda
ActAct ICMA ICMA Rule 251 day_count::act_act_icma
30/360 BondBasis ISDA 2006 §4.16(f) day_count::thirty_360_bond_basis
30E/360 ISDA 2006 §4.16(g) day_count::thirty_e_360
30E/360 ISDA ISDA 2006 §4.16(h) day_count::thirty_e_360_isda
Act/365L ICMA / sterling money-market day_count::act_365l
NL/365 (No-Leap) conventional day_count::nl_365
Bus/252 Brazilian convention day_count::bus_252
1/1 OIS shortcut day_count::one_one

Date-roll conventions

  • Unadjusted — return the date as given, even if it falls on a weekend or holiday.
  • Following — roll forward to the next business day.
  • ModifiedFollowing — Following, unless that would cross a month boundary, in which case roll back to the previous business day.
  • Preceding — roll back to the previous business day.
  • ModifiedPreceding — Preceding, unless that would cross a month boundary, in which case roll forward to the next business day.
  • Nearest — the nearest business day (Saturday rolls to Friday, Sunday rolls to Monday, ties broken forward).
  • EndOfMonth — anchor every rolled date to the last business day of the month when the input is the last business day of its month.

Holiday calendars

Calendar Source Module
TARGET2 ECB-defined fixed rule calendar::target2
Luxembourg Loi du 21 juillet 1928 (+ Loi du 28 février 2019) calendar::luxembourg
United States NYSE / Federal Reserve calendar::united_states
United Kingdom Bank of England calendar::united_kingdom
Japan Japan Exchange Group calendar::japan
Switzerland SIX Swiss Exchange calendar::switzerland
Hong Kong HKEX calendar::hong_kong
Singapore SGX calendar::singapore
Composite union of holidays calendar::composite
JointBusiness intersection of business days calendar::composite

TARGET2 and Luxembourg are fixed-rule generators (every date derived from the year alone — Easter via the Computus, plus a small set of fixed civil dates); every other calendar ships a dated 2020–2040 snapshot of the exchange's or central bank's published holiday list cross-verified row-by-row against the primary published source. Snapshot dates and the gazetted-vs-derived horizon for each calendar are recorded per file and in SPEC.md. Outside the snapshot window, is_holiday returns false rather than panicking.

Architecture

src/
  lib.rs                # Module declarations + re-exports
  errors.rs             # Typed errors — ValidationError
  date.rs               # Gregorian Date primitive; leap years, weekday, arithmetic
  roll.rs               # Date-roll conventions — Unadjusted, Following, ...

  day_count/
    mod.rs              # DayCount enum + dispatcher
    act_360.rs          # Act/360
    act_365f.rs         # Act/365F
    act_act_isda.rs     # ActAct ISDA — straddle-aware
    act_act_icma.rs     # ActAct ICMA — reference-period aware
    thirty_360_bond_basis.rs
    thirty_e_360.rs
    thirty_e_360_isda.rs
    act_365l.rs
    nl_365.rs
    bus_252.rs
    one_one.rs

  calendar/
    mod.rs              # Calendar enum + dispatcher (is_holiday,
                        # is_business_day, adjust, next_business_day,
                        # previous_business_day, add_business_days,
                        # business_days_between, bus_252_for_calendar)
    target2.rs          # ECB fixed rule (Easter-derived)
    luxembourg.rs       # Loi du 21 juillet 1928 fixed rule
    united_states.rs    # NYSE / Federal Reserve table
    united_kingdom.rs   # Bank of England table
    japan.rs            # JPX table
    switzerland.rs      # SIX table
    hong_kong.rs        # HKEX table
    singapore.rs        # SGX table
    composite.rs        # Composite / JointBusiness combinators

One file, one convention. Every type is Copy, allocation-free, and validated on construction.

Testing

cargo test                      # unit + integration + doc-tests
cargo run --example quickstart  # end-to-end tour
cargo bench                     # criterion benchmarks

Tests are anchored on the ISDA 2006 worked examples (the Act/Act straddle reference, the 30/360 BondBasis reference, the 30E/360 ISDA maturity-day specials), the ICMA Rule 251 examples, and the published QuantLib daycounters cross-oracle. Holiday tables are spot-checked against the official published calendars year by year.

Code quality

  • #![no_std], allocation-free — runs in services, WASM, and on embedded targets with no std
  • #![forbid(unsafe_code)] crate-wide
  • clippy::pedantic with zero warnings
  • No unwrap(), expect(), or panic!() in library code — every failure path is a typed Result
  • Every public item documented with its governing standard and a runnable example
  • Deterministic: the same input always produces the same verdict

Dependencies

Runtime: zero. Not std, not alloc, no FFI. Every day-count fraction, every date-roll convention, and every calendar lookup is hand-rolled from its governing standard. Licence and supply-chain policy is enforced via cargo-deny (deny.toml).

The default calendars feature embeds dated holiday-table snapshots as static, no_std-clean data. Disable it for a structural-only build (date primitives, day-count fractions, date-roll conventions; TARGET2 still works because it is rule-based, the other calendars become unavailable): cargo build --no-default-features.

Standards

All algorithms implemented from their governing standard — no ports from other implementations.

Standard Convention
ISDA 2006 Definitions §4.16 Act/360, Act/365F, ActAct ISDA, 30/360, 30E/360, 30E/360 ISDA
ICMA Rule 251 ActAct ICMA, Act/365L
ISO 8601 Date format, weekday rule
ECB TARGET2 closing days regulation TARGET2 calendar
Loi du 21 juillet 1928 / Loi du 28 février 2019 (Luxembourg) Luxembourg calendar
NYSE / Federal Reserve published schedule United States calendar
Bank of England bank holiday schedule United Kingdom calendar
JPX / National Holidays Act (Japan) Japan calendar
SIX Swiss Exchange published schedule Switzerland calendar
HKEX published schedule Hong Kong calendar
SGX published schedule Singapore calendar

Documentation

  • SPEC.md — every day-count fraction, date-roll convention, and calendar rule traced to its standard, with worked examples
  • CHANGELOG.md — release history
  • SECURITY.md — vulnerability disclosure policy

License

Apache License 2.0. See LICENSE and NOTICE.

Copyright 2026 Regit.io — Nicolas Koenig

Part of Regit OS — the operating system for investment products. From Luxembourg.