1174 lines
35 KiB
Rust
1174 lines
35 KiB
Rust
/*
|
|
Copyright 2020-2023, Savanni D'Gerinel <savanni@luminescent-dreams.com>
|
|
|
|
This file is part of the Luminescent Dreams Tools.
|
|
|
|
Luminescent Dreams Tools is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
|
|
|
Luminescent Dreams Tools is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License along with Lumeto. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
use chrono::{Datelike, NaiveDate};
|
|
use serde::{Deserialize, Serialize};
|
|
use std::convert::TryInto;
|
|
use thiserror::Error;
|
|
|
|
#[derive(Clone, Debug, Error, PartialEq)]
|
|
pub enum Error {
|
|
#[error("invalid date")]
|
|
InvalidDate,
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
|
pub enum DayOfWeek {
|
|
Sunday,
|
|
Monday,
|
|
Tuesday,
|
|
Wednesday,
|
|
Thursday,
|
|
Friday,
|
|
Saturday,
|
|
LeapDay,
|
|
YearDay,
|
|
}
|
|
|
|
impl From<DayOfWeek> for String {
|
|
fn from(day: DayOfWeek) -> Self {
|
|
match day {
|
|
DayOfWeek::Sunday => "Sunday",
|
|
DayOfWeek::Monday => "Monday",
|
|
DayOfWeek::Tuesday => "Tuesday",
|
|
DayOfWeek::Wednesday => "Wednesday",
|
|
DayOfWeek::Thursday => "Thursday",
|
|
DayOfWeek::Friday => "Friday",
|
|
DayOfWeek::Saturday => "Saturday",
|
|
DayOfWeek::LeapDay => "LeapDay",
|
|
DayOfWeek::YearDay => "YearDay",
|
|
}
|
|
.to_owned()
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
|
pub enum Month {
|
|
January,
|
|
February,
|
|
March,
|
|
April,
|
|
May,
|
|
June,
|
|
Sol,
|
|
July,
|
|
August,
|
|
September,
|
|
October,
|
|
November,
|
|
December,
|
|
}
|
|
|
|
impl From<u32> for Month {
|
|
fn from(val: u32) -> Month {
|
|
match val {
|
|
1 => Month::January,
|
|
2 => Month::February,
|
|
3 => Month::March,
|
|
4 => Month::April,
|
|
5 => Month::May,
|
|
6 => Month::June,
|
|
7 => Month::Sol,
|
|
8 => Month::July,
|
|
9 => Month::August,
|
|
10 => Month::September,
|
|
11 => Month::October,
|
|
12 => Month::November,
|
|
13 => Month::December,
|
|
_ => panic!("invalid month number"),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<u8> for Month {
|
|
fn from(val: u8) -> Month {
|
|
Month::from(val as u32)
|
|
}
|
|
}
|
|
|
|
impl From<Month> for String {
|
|
fn from(val: Month) -> String {
|
|
match val {
|
|
Month::January => "January",
|
|
Month::February => "February",
|
|
Month::March => "March",
|
|
Month::April => "April",
|
|
Month::May => "May",
|
|
Month::June => "June",
|
|
Month::Sol => "Sol",
|
|
Month::July => "July",
|
|
Month::August => "August",
|
|
Month::September => "September",
|
|
Month::October => "October",
|
|
Month::November => "November",
|
|
Month::December => "December",
|
|
}
|
|
.to_owned()
|
|
}
|
|
}
|
|
|
|
fn is_leap_year(year: i32) -> bool {
|
|
NaiveDate::from_ymd_opt(year, 12, 31).unwrap().ordinal() == 366
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
|
pub enum IFC {
|
|
LeapDay(i32),
|
|
YearDay(i32),
|
|
Day(Day),
|
|
}
|
|
|
|
impl IFC {
|
|
pub fn leap_day(year: i32) -> Result<Self, Error> {
|
|
if is_leap_year(year) {
|
|
Ok(Self::LeapDay(year))
|
|
} else {
|
|
Err(Error::InvalidDate)
|
|
}
|
|
}
|
|
|
|
pub fn year_day(year: i32) -> Self {
|
|
Self::YearDay(year)
|
|
}
|
|
|
|
pub fn ymd(year: i32, month: u8, day: u8) -> Result<Self, Error> {
|
|
if month < 1 || month > 13 {
|
|
Err(Error::InvalidDate)
|
|
} else if day < 1 || day > 28 {
|
|
Err(Error::InvalidDate)
|
|
} else {
|
|
Ok(Self::Day(Day { year, month, day }))
|
|
}
|
|
}
|
|
|
|
pub fn year(&self) -> i32 {
|
|
match *self {
|
|
IFC::LeapDay(year) => year,
|
|
IFC::YearDay(year) => year,
|
|
IFC::Day(Day { year, .. }) => year,
|
|
}
|
|
}
|
|
|
|
pub fn month(&self) -> Month {
|
|
match *self {
|
|
IFC::Day(Day { month, .. }) => Month::from(month),
|
|
IFC::LeapDay(_) => Month::June,
|
|
IFC::YearDay(_) => Month::December,
|
|
}
|
|
}
|
|
|
|
pub fn day(&self) -> u8 {
|
|
match *self {
|
|
IFC::Day(Day { day, .. }) => day,
|
|
IFC::LeapDay(_) => 29,
|
|
IFC::YearDay(_) => 29,
|
|
}
|
|
}
|
|
|
|
pub fn weekday(&self) -> DayOfWeek {
|
|
match *self {
|
|
IFC::LeapDay(_) => DayOfWeek::LeapDay,
|
|
IFC::YearDay(_) => DayOfWeek::YearDay,
|
|
IFC::Day(Day { day, .. }) => match (day - 1) % 7 {
|
|
0 => DayOfWeek::Sunday,
|
|
1 => DayOfWeek::Monday,
|
|
2 => DayOfWeek::Tuesday,
|
|
3 => DayOfWeek::Wednesday,
|
|
4 => DayOfWeek::Thursday,
|
|
5 => DayOfWeek::Friday,
|
|
6 => DayOfWeek::Saturday,
|
|
_ => panic!("impossible calculation"),
|
|
},
|
|
}
|
|
}
|
|
|
|
pub fn day_ordinal(&self) -> u32 {
|
|
self.day_ordinal0() + 1
|
|
}
|
|
|
|
pub fn day_ordinal0(&self) -> u32 {
|
|
match *self {
|
|
IFC::LeapDay(_) => 168,
|
|
IFC::YearDay(year) => {
|
|
if is_leap_year(year) {
|
|
365
|
|
} else {
|
|
364
|
|
}
|
|
}
|
|
IFC::Day(Day { year, month, day }) => {
|
|
u32::from(month - 1) * 28
|
|
+ u32::from(day - 1)
|
|
+ if is_leap_year(year) && month > 6 {
|
|
1
|
|
} else {
|
|
0
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn week_ordinal(&self) -> u32 {
|
|
self.week_ordinal0() + 1
|
|
}
|
|
|
|
pub fn week_ordinal0(&self) -> u32 {
|
|
match *self {
|
|
IFC::LeapDay(_) => 0,
|
|
IFC::YearDay(_) => 0,
|
|
IFC::Day(Day { month, day, .. }) => u32::from(month - 1) * 4 + (u32::from(day - 1) / 7),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
|
pub struct Day {
|
|
year: i32,
|
|
month: u8,
|
|
day: u8,
|
|
}
|
|
|
|
impl From<chrono::NaiveDate> for IFC {
|
|
fn from(date: chrono::NaiveDate) -> Self {
|
|
if date.month() == 12 && date.day() == 31 {
|
|
Self::YearDay(date.year())
|
|
} else if is_leap_year(date.year()) && date.month() == 6 && date.day() == 17 {
|
|
Self::LeapDay(date.year())
|
|
} else {
|
|
let mut days = date.ordinal();
|
|
if is_leap_year(date.year())
|
|
&& date > NaiveDate::from_ymd_opt(date.year(), 6, 17).unwrap()
|
|
{
|
|
days = days - 1;
|
|
}
|
|
let month: u8 = (days / 28).try_into().unwrap();
|
|
let day: u8 = (days % 28).try_into().unwrap();
|
|
Self::Day(Day {
|
|
year: date.year(),
|
|
month: month + 1,
|
|
day,
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<IFC> for chrono::NaiveDate {
|
|
fn from(ifc: IFC) -> Self {
|
|
Self::from_ymd_opt(ifc.year(), 1, 1).unwrap()
|
|
+ chrono::naive::Days::new(ifc.day_ordinal0().into())
|
|
}
|
|
}
|
|
|
|
/*
|
|
impl IFC {
|
|
pub fn year_day(year: u32) -> Self {
|
|
Self {
|
|
year,
|
|
ordinal: if is_leap_year(year) { 366 } else { 365 }
|
|
}
|
|
}
|
|
|
|
}
|
|
*/
|
|
|
|
/*
|
|
impl From<chrono::Date<chrono::Utc>> for IFC {
|
|
fn from(d: chrono::Date<chrono::Utc>) -> IFC {
|
|
IFC::from(d.naive_utc())
|
|
}
|
|
}
|
|
|
|
impl From<chrono::Date<chrono_tz::Tz>> for IFC {
|
|
fn from(d: chrono::Date<chrono_tz::Tz>) -> IFC {
|
|
IFC::from(d.naive_utc())
|
|
}
|
|
}
|
|
|
|
impl From<chrono::NaiveDate> for IFC {
|
|
fn from(d: NaiveDate) -> IFC {
|
|
//println!("d: {} [{}]", d.format("%Y-%m-%d"), d.ordinal());
|
|
IFC {
|
|
year: (d.year() + 10000) as u32,
|
|
ordinal: d.ordinal0(),
|
|
leap_year: is_leap_year(d.year()),
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
|
|
/*
|
|
impl Datelike for IFC {
|
|
fn year(&self) -> i32 {
|
|
// self.year as i32
|
|
unimplemented!()
|
|
}
|
|
fn month(&self) -> u32 {
|
|
// self.month0() + 1
|
|
unimplemented!()
|
|
}
|
|
fn month0(&self) -> u32 {
|
|
/*
|
|
if self.leap_year && self.ordinal == 365 {
|
|
12
|
|
} else if self.leap_year && self.ordinal == 168 {
|
|
5
|
|
} else {
|
|
self.ordinal / 28
|
|
}
|
|
*/
|
|
unimplemented!()
|
|
}
|
|
fn day(&self) -> u32 {
|
|
// self.day0() + 1
|
|
unimplemented!()
|
|
}
|
|
fn day0(&self) -> u32 {
|
|
/*
|
|
if self.leap_year {
|
|
if self.ordinal == 365 {
|
|
28
|
|
} else if self.ordinal == 168 {
|
|
28
|
|
} else if self.ordinal > 168 {
|
|
(self.ordinal - 1).rem_euclid(28) as u32
|
|
} else {
|
|
self.ordinal.rem_euclid(28) as u32
|
|
}
|
|
} else {
|
|
if self.ordinal == 364 {
|
|
28
|
|
} else {
|
|
self.ordinal.rem_euclid(28) as u32
|
|
}
|
|
}
|
|
*/
|
|
unimplemented!()
|
|
}
|
|
fn ordinal(&self) -> u32 {
|
|
// self.ordinal + 1
|
|
unimplemented!()
|
|
}
|
|
fn ordinal0(&self) -> u32 {
|
|
// self.ordinal
|
|
unimplemented!()
|
|
}
|
|
fn weekday(&self) -> chrono::Weekday {
|
|
if self.day0() == 28 {
|
|
chrono::Weekday::Sat
|
|
} else {
|
|
match self.day0().rem_euclid(7) {
|
|
0 => chrono::Weekday::Sun,
|
|
1 => chrono::Weekday::Mon,
|
|
2 => chrono::Weekday::Tue,
|
|
3 => chrono::Weekday::Wed,
|
|
4 => chrono::Weekday::Thu,
|
|
5 => chrono::Weekday::Fri,
|
|
6 => chrono::Weekday::Sat,
|
|
_ => panic!("rem_euclid should not return anything outside the 0..6 range"),
|
|
}
|
|
}
|
|
}
|
|
fn iso_week(&self) -> chrono::IsoWeek {
|
|
panic!("iso_week is not implemented because chrono does not expose any constructors for IsoWeek!");
|
|
}
|
|
fn with_year(&self, year: i32) -> Option<IFC> {
|
|
/*
|
|
Some(IFC {
|
|
year: (year as u32) + 10000,
|
|
ordinal: self.ordinal,
|
|
leap_year: is_leap_year(year),
|
|
})
|
|
*/
|
|
unimplemented!()
|
|
}
|
|
fn with_month(&self, month: u32) -> Option<IFC> {
|
|
// Some(IFC::ymd(self.year, month as u8, self.day() as u8))
|
|
unimplemented!()
|
|
}
|
|
fn with_month0(&self, month: u32) -> Option<IFC> {
|
|
// Some(IFC::ymd(self.year, month as u8 + 1, self.day() as u8))
|
|
unimplemented!()
|
|
}
|
|
fn with_day(&self, day: u32) -> Option<IFC> {
|
|
// Some(IFC::ymd(self.year, self.month() as u8, day as u8))
|
|
unimplemented!()
|
|
}
|
|
fn with_day0(&self, day: u32) -> Option<IFC> {
|
|
// Some(IFC::ymd(self.year, self.month() as u8, day as u8 + 1))
|
|
unimplemented!()
|
|
}
|
|
fn with_ordinal(&self, ordinal: u32) -> Option<IFC> {
|
|
/*
|
|
Some(IFC {
|
|
year: self.year,
|
|
ordinal,
|
|
leap_year: self.leap_year,
|
|
})
|
|
*/
|
|
unimplemented!()
|
|
}
|
|
fn with_ordinal0(&self, ordinal: u32) -> Option<IFC> {
|
|
/*
|
|
Some(IFC {
|
|
year: self.year,
|
|
ordinal: ordinal + 1,
|
|
leap_year: self.leap_year,
|
|
})
|
|
*/
|
|
unimplemented!()
|
|
}
|
|
}
|
|
*/
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
use chrono::NaiveDate;
|
|
|
|
#[test]
|
|
fn creates_a_day() {
|
|
assert_eq!(IFC::leap_day(12020), Ok(IFC::LeapDay(12020)));
|
|
assert_eq!(IFC::year_day(12020), IFC::YearDay(12020));
|
|
assert_eq!(
|
|
IFC::ymd(12022, 13, 28),
|
|
Ok(IFC::Day(Day {
|
|
year: 12022,
|
|
month: 13,
|
|
day: 28
|
|
}))
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn rejects_invalid_dates() {
|
|
assert_eq!(IFC::leap_day(12022), Err(Error::InvalidDate));
|
|
assert_eq!(IFC::ymd(12022, 13, 0), Err(Error::InvalidDate));
|
|
assert_eq!(IFC::ymd(12022, 14, 1), Err(Error::InvalidDate));
|
|
}
|
|
|
|
#[test]
|
|
fn it_expresses_day_of_week() {
|
|
assert_eq!(IFC::leap_day(12020).unwrap().weekday(), DayOfWeek::LeapDay);
|
|
assert_eq!(IFC::year_day(12022).weekday(), DayOfWeek::YearDay);
|
|
assert_eq!(IFC::ymd(12022, 1, 1).unwrap().weekday(), DayOfWeek::Sunday);
|
|
assert_eq!(IFC::ymd(12022, 1, 2).unwrap().weekday(), DayOfWeek::Monday);
|
|
assert_eq!(IFC::ymd(12022, 1, 3).unwrap().weekday(), DayOfWeek::Tuesday);
|
|
assert_eq!(
|
|
IFC::ymd(12022, 1, 4).unwrap().weekday(),
|
|
DayOfWeek::Wednesday
|
|
);
|
|
assert_eq!(
|
|
IFC::ymd(12022, 1, 5).unwrap().weekday(),
|
|
DayOfWeek::Thursday
|
|
);
|
|
assert_eq!(IFC::ymd(12022, 1, 6).unwrap().weekday(), DayOfWeek::Friday);
|
|
assert_eq!(
|
|
IFC::ymd(12022, 1, 7).unwrap().weekday(),
|
|
DayOfWeek::Saturday
|
|
);
|
|
assert_eq!(IFC::ymd(12022, 1, 8).unwrap().weekday(), DayOfWeek::Sunday);
|
|
}
|
|
|
|
#[test]
|
|
fn it_expresses_month() {
|
|
assert_eq!(IFC::ymd(12022, 1, 4).unwrap().month(), Month::January);
|
|
assert_eq!(IFC::ymd(12022, 12, 1).unwrap().month(), Month::November);
|
|
assert_eq!(IFC::leap_day(12020).unwrap().month(), Month::June);
|
|
assert_eq!(IFC::year_day(12020).month(), Month::December);
|
|
}
|
|
|
|
#[test]
|
|
fn it_reports_ordinal_days() {
|
|
assert_eq!(IFC::ymd(12022, 1, 1).unwrap().day_ordinal(), 1);
|
|
assert_eq!(IFC::ymd(12022, 1, 1).unwrap().day_ordinal0(), 0);
|
|
|
|
assert_eq!(IFC::ymd(12022, 1, 28).unwrap().day_ordinal(), 28);
|
|
assert_eq!(IFC::ymd(12022, 1, 28).unwrap().day_ordinal0(), 27);
|
|
|
|
assert_eq!(IFC::ymd(12022, 2, 1).unwrap().day_ordinal(), 29);
|
|
assert_eq!(IFC::ymd(12022, 2, 1).unwrap().day_ordinal0(), 28);
|
|
|
|
assert_eq!(IFC::ymd(12022, 3, 1).unwrap().day_ordinal(), 57);
|
|
assert_eq!(IFC::ymd(12022, 3, 1).unwrap().day_ordinal0(), 56);
|
|
|
|
assert_eq!(IFC::ymd(12022, 4, 1).unwrap().day_ordinal(), 85);
|
|
assert_eq!(IFC::ymd(12022, 4, 1).unwrap().day_ordinal0(), 84);
|
|
|
|
assert_eq!(IFC::ymd(12022, 5, 1).unwrap().day_ordinal(), 113);
|
|
assert_eq!(IFC::ymd(12022, 5, 1).unwrap().day_ordinal0(), 112);
|
|
|
|
assert_eq!(IFC::ymd(12022, 6, 1).unwrap().day_ordinal(), 141);
|
|
assert_eq!(IFC::ymd(12022, 6, 1).unwrap().day_ordinal0(), 140);
|
|
|
|
assert_eq!(IFC::ymd(12022, 7, 1).unwrap().day_ordinal(), 169);
|
|
assert_eq!(IFC::ymd(12022, 7, 1).unwrap().day_ordinal0(), 168);
|
|
|
|
assert_eq!(IFC::ymd(12022, 8, 1).unwrap().day_ordinal(), 197);
|
|
assert_eq!(IFC::ymd(12022, 8, 1).unwrap().day_ordinal0(), 196);
|
|
|
|
assert_eq!(IFC::ymd(12022, 9, 1).unwrap().day_ordinal(), 225);
|
|
assert_eq!(IFC::ymd(12022, 9, 1).unwrap().day_ordinal0(), 224);
|
|
|
|
assert_eq!(IFC::ymd(12022, 10, 1).unwrap().day_ordinal(), 253);
|
|
assert_eq!(IFC::ymd(12022, 10, 1).unwrap().day_ordinal0(), 252);
|
|
|
|
assert_eq!(IFC::ymd(12022, 11, 1).unwrap().day_ordinal(), 281);
|
|
assert_eq!(IFC::ymd(12022, 11, 1).unwrap().day_ordinal0(), 280);
|
|
|
|
assert_eq!(IFC::ymd(12022, 12, 1).unwrap().day_ordinal(), 309);
|
|
assert_eq!(IFC::ymd(12022, 12, 1).unwrap().day_ordinal0(), 308);
|
|
|
|
assert_eq!(IFC::ymd(12022, 13, 1).unwrap().day_ordinal(), 337);
|
|
assert_eq!(IFC::ymd(12022, 13, 1).unwrap().day_ordinal0(), 336);
|
|
|
|
assert_eq!(IFC::ymd(12022, 13, 28).unwrap().day_ordinal(), 364);
|
|
assert_eq!(IFC::ymd(12022, 13, 28).unwrap().day_ordinal0(), 363);
|
|
|
|
assert_eq!(IFC::year_day(12022).day_ordinal(), 365);
|
|
}
|
|
|
|
#[test]
|
|
fn it_reports_ordinal_days_on_leap_year() {
|
|
assert_eq!(IFC::ymd(12020, 1, 1).unwrap().day_ordinal(), 1);
|
|
assert_eq!(IFC::ymd(12020, 1, 1).unwrap().day_ordinal0(), 0);
|
|
|
|
assert_eq!(IFC::ymd(12020, 1, 28).unwrap().day_ordinal(), 28);
|
|
assert_eq!(IFC::ymd(12020, 1, 28).unwrap().day_ordinal0(), 27);
|
|
|
|
assert_eq!(IFC::ymd(12020, 2, 1).unwrap().day_ordinal(), 29);
|
|
assert_eq!(IFC::ymd(12020, 2, 1).unwrap().day_ordinal0(), 28);
|
|
|
|
assert_eq!(IFC::ymd(12020, 3, 1).unwrap().day_ordinal(), 57);
|
|
assert_eq!(IFC::ymd(12020, 3, 1).unwrap().day_ordinal0(), 56);
|
|
|
|
assert_eq!(IFC::ymd(12020, 4, 1).unwrap().day_ordinal(), 85);
|
|
assert_eq!(IFC::ymd(12020, 4, 1).unwrap().day_ordinal0(), 84);
|
|
|
|
assert_eq!(IFC::ymd(12020, 5, 1).unwrap().day_ordinal(), 113);
|
|
assert_eq!(IFC::ymd(12020, 5, 1).unwrap().day_ordinal0(), 112);
|
|
|
|
assert_eq!(IFC::ymd(12020, 6, 1).unwrap().day_ordinal(), 141);
|
|
assert_eq!(IFC::ymd(12020, 6, 1).unwrap().day_ordinal0(), 140);
|
|
|
|
assert_eq!(IFC::leap_day(12020).unwrap().day_ordinal(), 169);
|
|
assert_eq!(IFC::leap_day(12020).unwrap().day_ordinal0(), 168);
|
|
|
|
assert_eq!(IFC::ymd(12020, 7, 1).unwrap().day_ordinal(), 170);
|
|
assert_eq!(IFC::ymd(12020, 7, 1).unwrap().day_ordinal0(), 169);
|
|
|
|
assert_eq!(IFC::ymd(12020, 8, 1).unwrap().day_ordinal(), 198);
|
|
assert_eq!(IFC::ymd(12020, 8, 1).unwrap().day_ordinal0(), 197);
|
|
|
|
assert_eq!(IFC::ymd(12020, 9, 1).unwrap().day_ordinal(), 226);
|
|
assert_eq!(IFC::ymd(12020, 9, 1).unwrap().day_ordinal0(), 225);
|
|
|
|
assert_eq!(IFC::ymd(12020, 10, 1).unwrap().day_ordinal(), 254);
|
|
assert_eq!(IFC::ymd(12020, 10, 1).unwrap().day_ordinal0(), 253);
|
|
|
|
assert_eq!(IFC::ymd(12020, 11, 1).unwrap().day_ordinal(), 282);
|
|
assert_eq!(IFC::ymd(12020, 11, 1).unwrap().day_ordinal0(), 281);
|
|
|
|
assert_eq!(IFC::ymd(12020, 12, 1).unwrap().day_ordinal(), 310);
|
|
assert_eq!(IFC::ymd(12020, 12, 1).unwrap().day_ordinal0(), 309);
|
|
|
|
assert_eq!(IFC::ymd(12020, 13, 1).unwrap().day_ordinal(), 338);
|
|
assert_eq!(IFC::ymd(12020, 13, 1).unwrap().day_ordinal0(), 337);
|
|
|
|
assert_eq!(IFC::ymd(12020, 13, 28).unwrap().day_ordinal(), 365);
|
|
assert_eq!(IFC::ymd(12020, 13, 28).unwrap().day_ordinal0(), 364);
|
|
|
|
assert_eq!(IFC::year_day(12020).day_ordinal(), 366);
|
|
}
|
|
|
|
#[test]
|
|
fn it_reports_ordinal_weeks() {
|
|
assert_eq!(IFC::ymd(12022, 1, 1).unwrap().week_ordinal(), 1);
|
|
assert_eq!(IFC::ymd(12022, 1, 1).unwrap().week_ordinal0(), 0);
|
|
assert_eq!(IFC::ymd(12022, 1, 4).unwrap().week_ordinal(), 1);
|
|
assert_eq!(IFC::ymd(12022, 1, 4).unwrap().week_ordinal0(), 0);
|
|
assert_eq!(IFC::ymd(12022, 1, 7).unwrap().week_ordinal(), 1);
|
|
assert_eq!(IFC::ymd(12022, 1, 7).unwrap().week_ordinal0(), 0);
|
|
assert_eq!(IFC::ymd(12022, 1, 8).unwrap().week_ordinal(), 2);
|
|
assert_eq!(IFC::ymd(12022, 1, 8).unwrap().week_ordinal0(), 1);
|
|
assert_eq!(IFC::ymd(12022, 2, 1).unwrap().week_ordinal(), 5);
|
|
assert_eq!(IFC::ymd(12022, 2, 1).unwrap().week_ordinal0(), 4);
|
|
assert_eq!(IFC::ymd(12022, 13, 28).unwrap().week_ordinal(), 52);
|
|
assert_eq!(IFC::ymd(12022, 13, 28).unwrap().week_ordinal0(), 51);
|
|
}
|
|
|
|
#[test]
|
|
fn it_converts_from_gregorian() {
|
|
assert_eq!(
|
|
IFC::from(NaiveDate::from_ymd_opt(12022, 1, 1).unwrap()),
|
|
IFC::ymd(12022, 1, 1).unwrap()
|
|
);
|
|
assert_eq!(
|
|
IFC::from(NaiveDate::from_ymd_opt(12022, 1, 29).unwrap()),
|
|
IFC::ymd(12022, 2, 1).unwrap()
|
|
);
|
|
assert_eq!(
|
|
IFC::from(NaiveDate::from_ymd_opt(12022, 2, 26).unwrap()),
|
|
IFC::ymd(12022, 3, 1).unwrap()
|
|
);
|
|
assert_eq!(
|
|
IFC::from(NaiveDate::from_ymd_opt(12022, 3, 26).unwrap()),
|
|
IFC::ymd(12022, 4, 1).unwrap()
|
|
);
|
|
assert_eq!(
|
|
IFC::from(NaiveDate::from_ymd_opt(12022, 4, 23).unwrap()),
|
|
IFC::ymd(12022, 5, 1).unwrap()
|
|
);
|
|
assert_eq!(
|
|
IFC::from(NaiveDate::from_ymd_opt(12022, 5, 21).unwrap()),
|
|
IFC::ymd(12022, 6, 1).unwrap()
|
|
);
|
|
assert_eq!(
|
|
IFC::from(NaiveDate::from_ymd_opt(12022, 6, 18).unwrap()),
|
|
IFC::ymd(12022, 7, 1).unwrap()
|
|
);
|
|
assert_eq!(
|
|
IFC::from(NaiveDate::from_ymd_opt(12022, 7, 16).unwrap()),
|
|
IFC::ymd(12022, 8, 1).unwrap()
|
|
);
|
|
assert_eq!(
|
|
IFC::from(NaiveDate::from_ymd_opt(12022, 8, 13).unwrap()),
|
|
IFC::ymd(12022, 9, 1).unwrap()
|
|
);
|
|
assert_eq!(
|
|
IFC::from(NaiveDate::from_ymd_opt(12022, 9, 10).unwrap()),
|
|
IFC::ymd(12022, 10, 1).unwrap()
|
|
);
|
|
assert_eq!(
|
|
IFC::from(NaiveDate::from_ymd_opt(12022, 10, 8).unwrap()),
|
|
IFC::ymd(12022, 11, 1).unwrap()
|
|
);
|
|
assert_eq!(
|
|
IFC::from(NaiveDate::from_ymd_opt(12022, 11, 5).unwrap()),
|
|
IFC::ymd(12022, 12, 1).unwrap()
|
|
);
|
|
assert_eq!(
|
|
IFC::from(NaiveDate::from_ymd_opt(12022, 12, 3).unwrap()),
|
|
IFC::ymd(12022, 13, 1).unwrap()
|
|
);
|
|
assert_eq!(
|
|
IFC::from(NaiveDate::from_ymd_opt(12022, 12, 31).unwrap()),
|
|
IFC::YearDay(12022)
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn it_converts_from_gregorian_on_leap_year() {
|
|
assert_eq!(
|
|
IFC::from(NaiveDate::from_ymd_opt(12020, 1, 1).unwrap()),
|
|
IFC::ymd(12020, 1, 1).unwrap()
|
|
);
|
|
assert_eq!(
|
|
IFC::from(NaiveDate::from_ymd_opt(12020, 1, 29).unwrap()),
|
|
IFC::ymd(12020, 2, 1).unwrap()
|
|
);
|
|
assert_eq!(
|
|
IFC::from(NaiveDate::from_ymd_opt(12020, 2, 26).unwrap()),
|
|
IFC::ymd(12020, 3, 1).unwrap()
|
|
);
|
|
assert_eq!(
|
|
IFC::from(NaiveDate::from_ymd_opt(12020, 2, 28).unwrap()),
|
|
IFC::ymd(12020, 3, 3).unwrap()
|
|
);
|
|
assert_eq!(
|
|
IFC::from(NaiveDate::from_ymd_opt(12020, 2, 29).unwrap()),
|
|
IFC::ymd(12020, 3, 4).unwrap()
|
|
);
|
|
assert_eq!(
|
|
IFC::from(NaiveDate::from_ymd_opt(12020, 3, 1).unwrap()),
|
|
IFC::ymd(12020, 3, 5).unwrap()
|
|
);
|
|
assert_eq!(
|
|
IFC::from(NaiveDate::from_ymd_opt(12020, 3, 25).unwrap()),
|
|
IFC::ymd(12020, 4, 1).unwrap()
|
|
);
|
|
assert_eq!(
|
|
IFC::from(NaiveDate::from_ymd_opt(12020, 4, 22).unwrap()),
|
|
IFC::ymd(12020, 5, 1).unwrap()
|
|
);
|
|
assert_eq!(
|
|
IFC::from(NaiveDate::from_ymd_opt(12020, 5, 20).unwrap()),
|
|
IFC::ymd(12020, 6, 1).unwrap()
|
|
);
|
|
assert_eq!(
|
|
IFC::from(NaiveDate::from_ymd_opt(12020, 6, 17).unwrap()),
|
|
IFC::LeapDay(12020)
|
|
);
|
|
assert_eq!(
|
|
IFC::from(NaiveDate::from_ymd_opt(12020, 6, 18).unwrap()),
|
|
IFC::ymd(12020, 7, 1).unwrap()
|
|
);
|
|
assert_eq!(
|
|
IFC::from(NaiveDate::from_ymd_opt(12020, 7, 16).unwrap()),
|
|
IFC::ymd(12020, 8, 1).unwrap()
|
|
);
|
|
assert_eq!(
|
|
IFC::from(NaiveDate::from_ymd_opt(12020, 8, 13).unwrap()),
|
|
IFC::ymd(12020, 9, 1).unwrap()
|
|
);
|
|
assert_eq!(
|
|
IFC::from(NaiveDate::from_ymd_opt(12020, 9, 10).unwrap()),
|
|
IFC::ymd(12020, 10, 1).unwrap()
|
|
);
|
|
assert_eq!(
|
|
IFC::from(NaiveDate::from_ymd_opt(12020, 10, 8).unwrap()),
|
|
IFC::ymd(12020, 11, 1).unwrap()
|
|
);
|
|
assert_eq!(
|
|
IFC::from(NaiveDate::from_ymd_opt(12020, 11, 5).unwrap()),
|
|
IFC::ymd(12020, 12, 1).unwrap()
|
|
);
|
|
assert_eq!(
|
|
IFC::from(NaiveDate::from_ymd_opt(12020, 12, 3).unwrap()),
|
|
IFC::ymd(12020, 13, 1).unwrap()
|
|
);
|
|
assert_eq!(
|
|
IFC::from(NaiveDate::from_ymd_opt(12020, 12, 31).unwrap()),
|
|
IFC::YearDay(12020)
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn it_converts_to_gregorian() {
|
|
assert_eq!(
|
|
NaiveDate::from(IFC::ymd(12020, 1, 1).unwrap()),
|
|
NaiveDate::from_ymd_opt(12020, 1, 1).unwrap()
|
|
);
|
|
|
|
assert_eq!(
|
|
NaiveDate::from(IFC::leap_day(12020).unwrap()),
|
|
NaiveDate::from_ymd_opt(12020, 6, 17).unwrap()
|
|
);
|
|
|
|
assert_eq!(
|
|
NaiveDate::from(IFC::ymd(12020, 3, 4).unwrap()),
|
|
NaiveDate::from_ymd_opt(12020, 2, 29).unwrap()
|
|
);
|
|
|
|
assert_eq!(
|
|
NaiveDate::from(IFC::year_day(12020)),
|
|
NaiveDate::from_ymd_opt(12020, 12, 31).unwrap()
|
|
);
|
|
}
|
|
|
|
/*
|
|
#[test]
|
|
fn check_start_of_month() {
|
|
assert_eq!(
|
|
IFC::ymd(12019, 1, 1),
|
|
IFC {
|
|
year: 12019,
|
|
ordinal: 0,
|
|
leap_year: false
|
|
}
|
|
);
|
|
assert_eq!(
|
|
IFC::ymd(12019, 2, 1),
|
|
IFC {
|
|
year: 12019,
|
|
ordinal: 28,
|
|
leap_year: false
|
|
}
|
|
);
|
|
assert_eq!(
|
|
IFC::ymd(12019, 3, 1),
|
|
IFC {
|
|
year: 12019,
|
|
ordinal: 56,
|
|
leap_year: false
|
|
}
|
|
);
|
|
assert_eq!(
|
|
IFC::ymd(12019, 4, 1),
|
|
IFC {
|
|
year: 12019,
|
|
ordinal: 84,
|
|
leap_year: false
|
|
}
|
|
);
|
|
assert_eq!(
|
|
IFC::ymd(12019, 5, 1),
|
|
IFC {
|
|
year: 12019,
|
|
ordinal: 112,
|
|
leap_year: false
|
|
}
|
|
);
|
|
assert_eq!(
|
|
IFC::ymd(12019, 6, 1),
|
|
IFC {
|
|
year: 12019,
|
|
ordinal: 140,
|
|
leap_year: false
|
|
}
|
|
);
|
|
assert_eq!(
|
|
IFC::ymd(12019, 7, 1),
|
|
IFC {
|
|
year: 12019,
|
|
ordinal: 168,
|
|
leap_year: false
|
|
}
|
|
);
|
|
assert_eq!(
|
|
IFC::ymd(12019, 8, 1),
|
|
IFC {
|
|
year: 12019,
|
|
ordinal: 196,
|
|
leap_year: false
|
|
}
|
|
);
|
|
assert_eq!(
|
|
IFC::ymd(12019, 9, 1),
|
|
IFC {
|
|
year: 12019,
|
|
ordinal: 224,
|
|
leap_year: false
|
|
}
|
|
);
|
|
assert_eq!(
|
|
IFC::ymd(12019, 10, 1),
|
|
IFC {
|
|
year: 12019,
|
|
ordinal: 252,
|
|
leap_year: false
|
|
}
|
|
);
|
|
assert_eq!(
|
|
IFC::ymd(12019, 11, 1),
|
|
IFC {
|
|
year: 12019,
|
|
ordinal: 280,
|
|
leap_year: false
|
|
}
|
|
);
|
|
assert_eq!(
|
|
IFC::ymd(12019, 12, 1),
|
|
IFC {
|
|
year: 12019,
|
|
ordinal: 308,
|
|
leap_year: false
|
|
}
|
|
);
|
|
assert_eq!(
|
|
IFC::ymd(12019, 13, 1),
|
|
IFC {
|
|
year: 12019,
|
|
ordinal: 336,
|
|
leap_year: false
|
|
}
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn report_leap_day() {}
|
|
|
|
#[test]
|
|
fn check_start_of_month_leap_year() {
|
|
assert_eq!(
|
|
IFC::ymd(12020, 1, 1),
|
|
IFC {
|
|
year: 12020,
|
|
ordinal: 0,
|
|
leap_year: true
|
|
}
|
|
);
|
|
assert_eq!(
|
|
IFC::ymd(12020, 2, 1),
|
|
IFC {
|
|
year: 12020,
|
|
ordinal: 28,
|
|
leap_year: true
|
|
}
|
|
);
|
|
assert_eq!(
|
|
IFC::ymd(12020, 3, 1),
|
|
IFC {
|
|
year: 12020,
|
|
ordinal: 56,
|
|
leap_year: true
|
|
}
|
|
);
|
|
assert_eq!(
|
|
IFC::ymd(12020, 4, 1),
|
|
IFC {
|
|
year: 12020,
|
|
ordinal: 84,
|
|
leap_year: true
|
|
}
|
|
);
|
|
assert_eq!(
|
|
IFC::ymd(12020, 5, 1),
|
|
IFC {
|
|
year: 12020,
|
|
ordinal: 112,
|
|
leap_year: true
|
|
}
|
|
);
|
|
assert_eq!(
|
|
IFC::ymd(12020, 6, 1),
|
|
IFC {
|
|
year: 12020,
|
|
ordinal: 140,
|
|
leap_year: true
|
|
}
|
|
);
|
|
assert_eq!(
|
|
IFC::ymd(12020, 6, 29),
|
|
IFC {
|
|
year: 12020,
|
|
ordinal: 168,
|
|
leap_year: true
|
|
}
|
|
);
|
|
assert_eq!(
|
|
IFC::ymd(12020, 7, 1),
|
|
IFC {
|
|
year: 12020,
|
|
ordinal: 169,
|
|
leap_year: true
|
|
}
|
|
);
|
|
assert_eq!(
|
|
IFC::ymd(12020, 8, 1),
|
|
IFC {
|
|
year: 12020,
|
|
ordinal: 197,
|
|
leap_year: true
|
|
}
|
|
);
|
|
assert_eq!(
|
|
IFC::ymd(12020, 9, 1),
|
|
IFC {
|
|
year: 12020,
|
|
ordinal: 225,
|
|
leap_year: true
|
|
}
|
|
);
|
|
assert_eq!(
|
|
IFC::ymd(12020, 10, 1),
|
|
IFC {
|
|
year: 12020,
|
|
ordinal: 253,
|
|
leap_year: true
|
|
}
|
|
);
|
|
assert_eq!(
|
|
IFC::ymd(12020, 11, 1),
|
|
IFC {
|
|
year: 12020,
|
|
ordinal: 281,
|
|
leap_year: true
|
|
}
|
|
);
|
|
assert_eq!(
|
|
IFC::ymd(12020, 12, 1),
|
|
IFC {
|
|
year: 12020,
|
|
ordinal: 309,
|
|
leap_year: true
|
|
}
|
|
);
|
|
assert_eq!(
|
|
IFC::ymd(12020, 13, 1),
|
|
IFC {
|
|
year: 12020,
|
|
ordinal: 337,
|
|
leap_year: true
|
|
}
|
|
);
|
|
}
|
|
#[test]
|
|
fn it_matches_january_1() {
|
|
assert_eq!(
|
|
IFC::from(NaiveDate::from_ymd(2019, 1, 1)),
|
|
IFC::ymd(12019, 1, 1)
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn it_matches_february_1() {
|
|
assert_eq!(
|
|
IFC::from(NaiveDate::from_ymd(2019, 1, 29)),
|
|
IFC::ymd(12019, 2, 1)
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn it_matches_sol_1() {
|
|
assert_eq!(
|
|
IFC::from(NaiveDate::from_ymd(2019, 6, 18)),
|
|
IFC::ymd(12019, 7, 1)
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn it_matches_year_day() {
|
|
assert_eq!(
|
|
IFC::from(NaiveDate::from_ymd(2019, 12, 31)),
|
|
IFC::ymd(12019, 13, 29)
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn it_matches_leap_day() {
|
|
assert_eq!(
|
|
IFC::from(NaiveDate::from_ymd(2019, 6, 18)),
|
|
IFC::ymd(12019, 7, 1),
|
|
);
|
|
assert_eq!(
|
|
IFC::from(NaiveDate::from_ymd(2020, 6, 17)),
|
|
IFC::ymd(12020, 6, 29),
|
|
);
|
|
assert_eq!(
|
|
IFC::from(NaiveDate::from_ymd(2020, 6, 18)),
|
|
IFC::ymd(12020, 7, 1),
|
|
);
|
|
assert_ne!(IFC::ymd(12020, 6, 29), IFC::ymd(12020, 7, 1));
|
|
}
|
|
|
|
#[test]
|
|
fn it_handles_gregorian_leap_day() {
|
|
assert_eq!(
|
|
IFC::from(NaiveDate::from_ymd(2019, 3, 1)),
|
|
IFC::ymd(12019, 3, 4)
|
|
);
|
|
assert_eq!(
|
|
IFC::from(NaiveDate::from_ymd(2020, 2, 29)),
|
|
IFC::ymd(12020, 3, 4)
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn it_handles_days_between_leap_days() {
|
|
assert_eq!(
|
|
IFC::from(NaiveDate::from_ymd(2020, 4, 8)),
|
|
IFC::ymd(12020, 4, 15),
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn it_handles_days_after_ifc_leap_day() {
|
|
assert_eq!(
|
|
IFC::from(NaiveDate::from_ymd(2020, 10, 8)),
|
|
IFC::ymd(12020, 11, 1),
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn it_matches_year_day_in_leap_year() {
|
|
assert_eq!(NaiveDate::from_ymd(2020, 12, 31).ordinal(), 366);
|
|
assert_eq!(
|
|
IFC::from(NaiveDate::from_ymd(2020, 12, 31)),
|
|
IFC::ymd(12020, 13, 29)
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn it_reports_correct_month() {
|
|
assert_eq!(IFC::ymd(12019, 1, 1).month(), 1);
|
|
assert_eq!(IFC::ymd(12019, 1, 1).month0(), 0);
|
|
|
|
assert_eq!(IFC::ymd(12020, 6, 28).month(), 6);
|
|
assert_eq!(IFC::ymd(12020, 6, 28).month0(), 5);
|
|
|
|
assert_eq!(IFC::ymd(12020, 7, 1).month(), 7);
|
|
assert_eq!(IFC::ymd(12020, 7, 1).month0(), 6);
|
|
|
|
assert_eq!(IFC::ymd(12019, 13, 1).month(), 13);
|
|
assert_eq!(IFC::ymd(12019, 13, 1).month0(), 12);
|
|
}
|
|
|
|
#[test]
|
|
fn it_reports_correct_day() {
|
|
assert_eq!(IFC::ymd(12019, 1, 1).day(), 1);
|
|
assert_eq!(IFC::ymd(12019, 1, 1).day0(), 0);
|
|
|
|
assert_eq!(IFC::ymd(12020, 3, 1).day(), 1);
|
|
assert_eq!(IFC::ymd(12020, 3, 1).day0(), 0);
|
|
|
|
assert_eq!(IFC::ymd(12020, 6, 28).day(), 28);
|
|
assert_eq!(IFC::ymd(12020, 6, 28).day0(), 27);
|
|
|
|
assert_eq!(IFC::ymd(12020, 7, 1).day(), 1);
|
|
assert_eq!(IFC::ymd(12020, 7, 1).day0(), 0);
|
|
|
|
assert_eq!(IFC::ymd(12019, 13, 1).day(), 1);
|
|
assert_eq!(IFC::ymd(12019, 13, 1).day0(), 0);
|
|
|
|
assert_eq!(IFC::ymd(12019, 13, 29).day(), 29);
|
|
assert_eq!(IFC::ymd(12019, 13, 29).day0(), 28);
|
|
}
|
|
|
|
#[test]
|
|
fn it_reports_correct_month_in_leap_year() {
|
|
assert_eq!(IFC::ymd(12020, 1, 1).month(), 1);
|
|
assert_eq!(IFC::ymd(12020, 1, 1).month0(), 0);
|
|
|
|
assert_eq!(IFC::ymd(12020, 3, 1).month(), 3);
|
|
assert_eq!(IFC::ymd(12020, 3, 1).month0(), 2);
|
|
|
|
assert_eq!(IFC::ymd(12020, 6, 29).month(), 6);
|
|
assert_eq!(IFC::ymd(12020, 6, 29).month0(), 5);
|
|
|
|
assert_eq!(IFC::ymd(12020, 7, 1).month(), 7);
|
|
assert_eq!(IFC::ymd(12020, 7, 1).month0(), 6);
|
|
}
|
|
|
|
#[test]
|
|
fn it_reports_correct_day_in_leap_year() {
|
|
assert_eq!(IFC::ymd(12019, 1, 1).day(), 1);
|
|
assert_eq!(IFC::ymd(12019, 1, 1).day0(), 0);
|
|
|
|
assert_eq!(IFC::ymd(12020, 6, 28).day(), 28);
|
|
assert_eq!(IFC::ymd(12020, 6, 28).day0(), 27);
|
|
|
|
assert_eq!(IFC::ymd(12020, 6, 29).day(), 29);
|
|
assert_eq!(IFC::ymd(12020, 6, 29).day0(), 28);
|
|
|
|
assert_eq!(IFC::ymd(12020, 7, 1).day(), 1);
|
|
assert_eq!(IFC::ymd(12020, 7, 1).day0(), 0);
|
|
|
|
assert_eq!(IFC::ymd(12019, 13, 1).day(), 1);
|
|
assert_eq!(IFC::ymd(12019, 13, 1).day0(), 0);
|
|
|
|
assert_eq!(IFC::ymd(12019, 13, 29).day(), 29);
|
|
assert_eq!(IFC::ymd(12019, 13, 29).day0(), 28);
|
|
}
|
|
*/
|
|
|
|
/*
|
|
#[test]
|
|
fn it_reports_correct_day_of_week() {
|
|
assert_eq!(IFC::ymd(12019, 1, 1).weekday(), DayOfWeek::Sunday);
|
|
assert_eq!(IFC::ymd(12019, 6, 1).weekday(), DayOfWeek::Sunday);
|
|
assert_eq!(IFC::ymd(12019, 6, 28).weekday(), DayOfWeek::Saturday);
|
|
assert_eq!(IFC::ymd(12019, 7, 1).weekday(), DayOfWeek::Sunday);
|
|
assert_eq!(IFC::ymd(12019, 13, 28).weekday(), DayOfWeek::Saturday);
|
|
assert_eq!(IFC::ymd(12019, 13, 29).weekday(), DayOfWeek::Saturday);
|
|
|
|
assert_eq!(IFC::ymd(12020, 6, 28).weekday(), DayOfWeek::Saturday);
|
|
assert_eq!(IFC::ymd(12020, 6, 29).weekday(), DayOfWeek::Saturday);
|
|
assert_eq!(IFC::ymd(12020, 7, 1).weekday(), DayOfWeek::Sunday);
|
|
assert_eq!(IFC::ymd(12020, 13, 28).weekday(), DayOfWeek::Saturday);
|
|
assert_eq!(IFC::ymd(12020, 13, 29).weekday(), DayOfWeek::Saturday);
|
|
|
|
assert_eq!(IFC::ymd(12022, 13, 31)
|
|
}
|
|
*/
|
|
}
|