Struct PyCalendar
pub(crate) struct PyCalendar {
inner: Arc<dyn Calendar>,
expression: String,
}Expand description
A business-day calendar, resolved from a lookup expression.
The expression is a business-centre code ("GBLO") or a comma-separated
list joined into the union of its members’ holidays ("GBLO,EUTA").
"EVERYDAY" names the calendar on which every day is a business day and
"WEEKDAYS" the one on which only weekends are not. A value date that must
also be good on a second calendar is stated with [Calendar.settle]’s
settlement.
Calendars are immutable. No operation amends the calendar in hand: there is
no add_holiday, no remove_holiday, and nothing a caller does here changes
what any other holder resolves for a centre. The one operation that rebinds
a code is dates.ingest_calendars, which never alters a calendar anyone
holds. Two calendars claiming one centre and disagreeing about its holidays
would make two prices differ for a reason no ledger records, and that is what
the registry exists to prevent.
Construction is a different thing from amendment, and is permitted.
[Calendar.from_holidays] builds a calendar from an explicit holiday set,
and [Calendar.amended] derives one from a calendar in hand by closing and
opening dates. Both return a new value the caller passes explicitly, both
register nothing, and both leave every other holder’s resolution exactly as
it was. What keeps the guarantee is the narrower rule that a built or derived
calendar never takes a registered centre’s name: from_holidays refuses one,
and a derived calendar’s name is one the lookup does not resolve.
Fields§
§inner: Arc<dyn Calendar>§expression: StringImplementations§
§impl PyCalendar
impl PyCalendar
pub(crate) fn handle(&self) -> &Arc<dyn Calendar>
pub(crate) fn of(inner: Arc<dyn Calendar>, label: &str) -> Self
pub(crate) fn of(inner: Arc<dyn Calendar>, label: &str) -> Self
Wraps a calendar the core already resolved.
The handle is shared, not rebuilt: a caller who takes a calendar off a
template holds the same object the template’s own schedules are built
on. Its expression is its name wherever the parser resolves that
name — a centre, or a holiday join spelled A,B — so Calendar(...)
rebuilds it; label describes where it came from otherwise, for a
calendar no expression spells (a business-day join, an amended one).
§impl PyCalendar
impl PyCalendar
fn new(expression: &str) -> PyResult<Self>
fn from_holidays(
name: &str,
holidays: Vec<NaiveDate>,
weekend: Option<Vec<String>>,
) -> PyResult<Self>
fn from_holidays( name: &str, holidays: Vec<NaiveDate>, weekend: Option<Vec<String>>, ) -> PyResult<Self>
Builds a calendar from an explicit holiday set, for a market the shipped registry does not carry.
Registers nothing and mutates nothing. The result is a value the caller passes explicitly; every registry calendar resolves afterwards to exactly what it resolved to before, and no other holder can observe that this was built. That is the distinction the calendar layer actually draws: shared mutable state is refused, construction is not.
weekend names the days that are not business days, parsed by the core’s
own day-of-week vocabulary; it defaults to Saturday and Sunday.
A registered business centre’s name is refused. Two calendars claiming the same centre and disagreeing about its holidays is the failure the registry exists to prevent, and building one under a name the lookup already answers would reintroduce it.
fn amended(
&self,
closing: Option<Vec<NaiveDate>>,
opening: Option<Vec<NaiveDate>>,
) -> PyResult<Self>
fn amended( &self, closing: Option<Vec<NaiveDate>>, opening: Option<Vec<NaiveDate>>, ) -> PyResult<Self>
Derives a new calendar from this one, closing closing and opening
opening.
This is how a caller says “GBLO, plus the closure announced after the
shipped table was generated” without enumerating a century of UK bank
holidays. from_holidays takes a whole holiday set; this takes a
difference from a calendar already in hand.
The receiver is unchanged. Nothing is registered, nothing is
amended in place, and every other holder — including a later
Calendar("GBLO") — resolves exactly what it resolved before. The
result is a value you pass explicitly.
The derived calendar takes a name of its own that Calendar(...) does
not resolve, so it can never be a second calendar claiming a registered
centre.
Both sets are taken in one call. Each derivation rebuilds the calendar’s grid, so deriving three times to close three dates pays that cost three times; and taking both together makes the result independent of the order they are supplied in. A date named in both is refused.
This rebuilds the calendar — it belongs in setup, not on a pricing path.
fn __repr__(&self) -> String
fn join(
calendars: Vec<PyRef<'_, PyCalendar>>,
rule: Named<JointCalendarRule>,
) -> PyResult<Self>
fn join( calendars: Vec<PyRef<'_, PyCalendar>>, rule: Named<JointCalendarRule>, ) -> PyResult<Self>
calendars combined under rule: JoinHolidays (a holiday in any
member is a holiday — what a comma in an expression means) or
JoinBusinessDays (a business day in any member is a business day).
fn expression(&self) -> &str
fn expression(&self) -> &str
The expression this calendar was resolved from.
fn is_weekend(&self, date: NaiveDate) -> bool
fn is_weekend(&self, date: NaiveDate) -> bool
Whether date falls on the weekend of this calendar’s week.
fn is_holiday(&self, date: NaiveDate) -> bool
fn is_holiday(&self, date: NaiveDate) -> bool
Whether date is closed for a reason beyond the weekend — a listed
closure, not a Saturday.
A weekend day carrying no listed closure is not a holiday, so
is_weekend and is_holiday do not overlap and a caller can tell one
from the other. The answer does not depend on the expression the
calendar was resolved from, and it selects exactly the dates
holidays returns when weekends are excluded.
fn is_business_day(&self, date: NaiveDate) -> bool
fn is_business_day(&self, date: NaiveDate) -> bool
Whether date is a good business day.
fn adjust(
&self,
date: NaiveDate,
business_day_convention: Named<BusinessDayConvention>,
) -> NaiveDate
fn adjust( &self, date: NaiveDate, business_day_convention: Named<BusinessDayConvention>, ) -> NaiveDate
Rolls date to a business day under business_day_convention.
fn settle(
&self,
date: NaiveDate,
n: i32,
unit: &str,
settlement: Option<&PyCalendar>,
business_day_convention: Named<BusinessDayConvention>,
) -> PyResult<NaiveDate>
fn settle( &self, date: NaiveDate, n: i32, unit: &str, settlement: Option<&PyCalendar>, business_day_convention: Named<BusinessDayConvention>, ) -> PyResult<NaiveDate>
Advances date by a settlement lag of n units and settles the
result — the one primitive behind every value date: T+2 spot, a
lagged payment, an FX delivery.
unit counts business_days on this calendar or calendar_days
settled afterwards. business_day_convention rolls the result onto a
business day of this calendar, or, when settlement is given, onto a
day that is a business day of both — the way a value date is stated
over two calendars. The count itself follows this calendar alone.
fn advance(
&self,
date: NaiveDate,
tenor: CalendarTenor,
business_day_convention: Named<BusinessDayConvention>,
end_of_month: bool,
roll_convention: Option<Named<RollConvention>>,
) -> PyResult<NaiveDate>
fn advance( &self, date: NaiveDate, tenor: CalendarTenor, business_day_convention: Named<BusinessDayConvention>, end_of_month: bool, roll_convention: Option<Named<RollConvention>>, ) -> PyResult<NaiveDate>
Advances date by tenor ("3M", "-1Y", "2W", "7D"), then
adjusts the result under business_day_convention. "4B" is four good
business days — add_business_days, so nothing is left to adjust.
end_of_month is the end-of-month roll rule: when the seed is a
business month-end anchor and the tenor is in months or years, the
result lands on the business month end of the target month rather than
on the clamped day (28 Feb + 6M reaches 31 Aug, not 28 Aug).
roll_convention snaps the advanced date before it is adjusted: a day of the
month ("31"), "EOM", or one of the named conventions.
end_of_month supersedes it, as it does in a schedule.
fn end_of_month(&self, date: NaiveDate) -> NaiveDate
fn end_of_month(&self, date: NaiveDate) -> NaiveDate
The last business day of date’s month. The calendar month end is
the free function last_day_of_month, which is blind to holidays.
fn is_end_of_month(&self, date: NaiveDate) -> bool
fn is_end_of_month(&self, date: NaiveDate) -> bool
Whether date is its month’s last business day. Strict: a trailing
weekend day is not, though it does anchor the end-of-month roll.
fn is_month_end_anchor(&self, date: NaiveDate) -> bool
fn is_month_end_anchor(&self, date: NaiveDate) -> bool
Whether date anchors the end-of-month roll — on or after its month’s
last business day, so a month-end falling on a Saturday still fires.
fn next_business_day(&self, date: NaiveDate) -> PyResult<NaiveDate>
fn next_business_day(&self, date: NaiveDate) -> PyResult<NaiveDate>
The first business day on or after date.
fn previous_business_day(&self, date: NaiveDate) -> PyResult<NaiveDate>
fn previous_business_day(&self, date: NaiveDate) -> PyResult<NaiveDate>
The first business day on or before date.
fn add_business_days(&self, date: NaiveDate, n: i64) -> PyResult<NaiveDate>
fn add_business_days(&self, date: NaiveDate, n: i64) -> PyResult<NaiveDate>
Steps date by n good business days. Negative looks backward; zero
returns date unchanged even where it is itself a holiday. This is the
primitive a settlement or fixing lag is built on.
fn business_days_between(
&self,
start: NaiveDate,
end: NaiveDate,
include_first: Option<bool>,
include_last: Option<bool>,
) -> i64
fn business_days_between( &self, start: NaiveDate, end: NaiveDate, include_first: Option<bool>, include_last: Option<bool>, ) -> i64
The number of business days in the half-open interval [start, end),
zero when start is not before end: what BUS/252 divides. With
include_first or include_last stated, each endpoint’s inclusion is
as stated (the other taking its half-open default), and reversing the
dates negates the count with the flags swapped.
fn holidays(
&self,
start: NaiveDate,
end: NaiveDate,
include_weekends: bool,
) -> Vec<NaiveDate>
fn holidays( &self, start: NaiveDate, end: NaiveDate, include_weekends: bool, ) -> Vec<NaiveDate>
The non-business days in the inclusive range, ascending. Weekends are included only when asked for. Both endpoints are required: a calendar spans a century and an unbounded listing is not a useful answer.
fn business_days(&self, start: NaiveDate, end: NaiveDate) -> Vec<NaiveDate>
fn business_days(&self, start: NaiveDate, end: NaiveDate) -> Vec<NaiveDate>
The business days in the inclusive range, ascending.
Trait Implementations§
impl DerefToPyAny for PyCalendar
§impl IntoPy<Py<PyAny>> for PyCalendar
impl IntoPy<Py<PyAny>> for PyCalendar
§impl PyClass for PyCalendar
impl PyClass for PyCalendar
§impl PyClassImpl for PyCalendar
impl PyClassImpl for PyCalendar
§const IS_BASETYPE: bool = false
const IS_BASETYPE: bool = false
§const IS_SUBCLASS: bool = false
const IS_SUBCLASS: bool = false
§const IS_MAPPING: bool = false
const IS_MAPPING: bool = false
§const IS_SEQUENCE: bool = false
const IS_SEQUENCE: bool = false
§type ThreadChecker = SendablePyClass<PyCalendar>
type ThreadChecker = SendablePyClass<PyCalendar>
§type PyClassMutability = <<PyAny as PyClassBaseType>::PyClassMutability as PyClassMutability>::ImmutableChild
type PyClassMutability = <<PyAny as PyClassBaseType>::PyClassMutability as PyClassMutability>::ImmutableChild
§type BaseNativeType = PyAny
type BaseNativeType = PyAny
PyAny by default, and when you declare
#[pyclass(extends=PyDict)], it’s PyDict.fn items_iter() -> PyClassItemsIter
fn lazy_type_object() -> &'static LazyTypeObject<Self>
fn dict_offset() -> Option<isize>
fn weaklist_offset() -> Option<isize>
§impl PyClassNewTextSignature<PyCalendar> for PyClassImplCollector<PyCalendar>
impl PyClassNewTextSignature<PyCalendar> for PyClassImplCollector<PyCalendar>
fn new_text_signature(self) -> Option<&'static str>
§impl<'a, 'py> PyFunctionArgument<'a, 'py> for &'a PyCalendar
impl<'a, 'py> PyFunctionArgument<'a, 'py> for &'a PyCalendar
§impl PyMethods<PyCalendar> for PyClassImplCollector<PyCalendar>
impl PyMethods<PyCalendar> for PyClassImplCollector<PyCalendar>
fn py_methods(self) -> &'static PyClassItems
§impl PyTypeInfo for PyCalendar
impl PyTypeInfo for PyCalendar
§fn type_object_raw(py: Python<'_>) -> *mut PyTypeObject
fn type_object_raw(py: Python<'_>) -> *mut PyTypeObject
§fn type_object_bound(py: Python<'_>) -> Bound<'_, PyType>
fn type_object_bound(py: Python<'_>) -> Bound<'_, PyType>
§fn is_type_of_bound(object: &Bound<'_, PyAny>) -> bool
fn is_type_of_bound(object: &Bound<'_, PyAny>) -> bool
object is an instance of this type or a subclass of this type.§fn is_exact_type_of_bound(object: &Bound<'_, PyAny>) -> bool
fn is_exact_type_of_bound(object: &Bound<'_, PyAny>) -> bool
object is an instance of this type.