#![warn(missing_docs)]
#![warn(rustdoc::broken_intra_doc_links)]
pub trait DayCounter: std::fmt::Display + Default + Copy + Clone {
#[cfg(not(feature = "hifitime"))]
fn day_count_fraction(
&self,
start: &chrono::NaiveDate,
end: &chrono::NaiveDate,
) -> DayCountFraction<Self>
where
Self: Sized;
#[cfg(feature = "hifitime")]
fn day_count_fraction(
&self,
start: &hifitime::Epoch,
end: &hifitime::Epoch,
) -> DayCountFraction<Self>
where
Self: Sized;
}
pub struct DayCountFraction<D>
where
D: DayCounter,
{
fraction: f64,
_marker: std::marker::PhantomData<D>,
}
impl<D> DayCountFraction<D>
where
D: DayCounter,
{
#[must_use]
#[inline]
pub const fn new(fraction: f64) -> Self {
Self {
fraction,
_marker: std::marker::PhantomData,
}
}
#[must_use]
#[inline]
pub const fn get_fraction(&self) -> f64 {
self.fraction
}
}
impl<D> PartialEq for DayCountFraction<D>
where
D: DayCounter,
{
fn eq(&self, other: &Self) -> bool {
self.fraction == other.fraction
}
}
mod actual_360;
pub use actual_360::{Actual360, Actual360Inc};
mod actual_364;
pub use actual_364::Actual364;
mod actual_365;
pub use actual_365::{Actual365A, Actual365Fixed};
mod actual_366;
pub use actual_366::{Actual366, Actual366Inc};
mod actual_365_25;
pub use actual_365_25::{Actual36525, Actual36525Inc};
mod nl_365;
pub use nl_365::NL365;
mod one_1;
pub use one_1::OneOne;
mod thirty_360;
pub use thirty_360::{Thirty360, ThirtyE360, ThirtyE360ISDA, ThirtyEPlus360ISDA};
mod util;
pub(crate) use util::{get_last_day_of_month, is_feb29_between_exc_inc, is_last_day_of_feb};
#[cfg(test)]
mod tests {
use crate::{DayCounter, OneOne, NL365};
#[cfg(not(feature = "hifitime"))]
use chrono::NaiveDate;
#[cfg(feature = "hifitime")]
use hifitime::Epoch;
#[cfg(not(feature = "hifitime"))]
#[test]
fn comparison() {
let day1 = NaiveDate::from_ymd_opt(2024, 1, 1).unwrap();
let day2 = NaiveDate::from_ymd_opt(2024, 7, 1).unwrap();
let dc1 = NL365::default();
let dc2 = OneOne::default();
let yf1 = dc1.day_count_fraction(&day1, &day2);
let yf2 = dc2.day_count_fraction(&day1, &day2);
assert_ne!(yf1.fraction, yf2.fraction);
}
#[cfg(feature = "hifitime")]
#[test]
fn comparison() {
let day1 = Epoch::from_gregorian_utc_at_midnight(2024, 1, 1);
let day2 = Epoch::from_gregorian_utc_at_midnight(2024, 7, 1);
let dc1 = NL365;
let dc2 = OneOne;
let yf1 = dc1.day_count_fraction(&day1, &day2);
let yf2 = dc2.day_count_fraction(&day1, &day2);
assert_ne!(yf1.fraction, yf2.fraction);
}
}