use std::fmt::Display;
use crate::{get_last_day_of_month, is_last_day_of_feb, DayCountFraction, DayCounter};
use chrono::{Datelike, NaiveDate};
#[derive(Debug, Copy, Clone, Default, PartialEq, Eq)]
pub struct Thirty360;
impl DayCounter for Thirty360 {
fn day_count_fraction(&self, start: &NaiveDate, end: &NaiveDate) -> DayCountFraction<Self> {
let y1 = start.year();
let m1 = start.month() as i32;
let mut d1 = start.day() as i32;
let y2 = end.year();
let m2 = end.month() as i32;
let mut d2 = end.day() as i32;
if d1 == 31 {
d1 = 30;
}
if d2 == 31 && d1 >= 30 {
d2 = 30;
}
let numerator = 360 * (y2 - y1) + 30 * (m2 - m1) + (d2 - d1);
DayCountFraction::new(f64::from(numerator) / 360.0)
}
}
impl Display for Thirty360 {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "30/360")
}
}
#[derive(Debug, Copy, Clone, Default, PartialEq, Eq)]
pub struct ThirtyE360;
impl DayCounter for ThirtyE360 {
fn day_count_fraction(&self, start: &NaiveDate, end: &NaiveDate) -> DayCountFraction<Self> {
let y1 = start.year();
let m1 = start.month() as i32;
let mut d1 = start.day() as i32;
let y2 = end.year();
let m2 = end.month() as i32;
let mut d2 = end.day() as i32;
if d1 == 31 {
d1 = 30;
}
if d2 == 31 {
d2 = 30;
}
let numerator = 360 * (y2 - y1) + 30 * (m2 - m1) + (d2 - d1);
DayCountFraction::new(f64::from(numerator) / 360.0)
}
}
impl Display for ThirtyE360 {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "30E/360")
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct ThirtyE360ISDA {
pub termination_date: NaiveDate,
}
impl ThirtyE360ISDA {
#[must_use]
pub const fn new(termination_date: NaiveDate) -> Self {
Self { termination_date }
}
}
impl DayCounter for ThirtyE360ISDA {
fn day_count_fraction(&self, start: &NaiveDate, end: &NaiveDate) -> DayCountFraction<Self> {
let y1 = start.year();
let m1 = start.month();
let mut d1 = start.day() as i32;
let y2 = end.year();
let m2 = end.month();
let mut d2 = end.day() as i32;
if get_last_day_of_month(y1, m1) == d1 {
d1 = 30;
}
if is_last_day_of_feb(*end) && (self.termination_date != *end || d2 == 31) {
d2 = 30;
}
let numerator = 360 * (y2 - y1) + 12 * ((m2 - m1) as i32) + (d2 - d1);
DayCountFraction::new(f64::from(numerator) / 360.0)
}
}
impl Display for ThirtyE360ISDA {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "30E/360 (ISDA)")
}
}
#[derive(Debug, Copy, Clone, Default, PartialEq, Eq)]
pub struct ThirtyEPlus360ISDA;
impl DayCounter for ThirtyEPlus360ISDA {
fn day_count_fraction(&self, start: &NaiveDate, end: &NaiveDate) -> DayCountFraction<Self> {
let y1 = start.year();
let m1 = start.month() as i32;
let mut d1 = start.day() as i32;
let y2 = end.year();
let mut m2 = end.month() as i32;
let mut d2 = end.day() as i32;
if d1 == 31 {
d1 = 30;
}
if d2 == 31 {
d2 = 1;
m2 += 1;
}
let numerator = 360 * (y2 - y1) + 12 * (m2 - m1) + (d2 - d1);
DayCountFraction::new(f64::from(numerator) / 360.0)
}
}
impl Display for ThirtyEPlus360ISDA {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "30E+/360 (ISDA)")
}
}