Skip to main content

chrono_node/calculation/
years.rs

1//! upstream `calculation/years.ts`.
2
3use crate::calculation::duration::{add_duration, Duration, DurationUnit};
4use crate::core::js_date::JsDate;
5
6/// `findMostLikelyADYear(yearNumber)`: 97 -> 1997, 12 -> 2012.
7pub fn find_most_likely_ad_year(year_number: i64) -> i64 {
8    if year_number < 100 {
9        if year_number > 50 {
10            year_number + 1900
11        } else {
12            year_number + 2000
13        }
14    } else {
15        year_number
16    }
17}
18
19/// `findYearClosestToRef(refDate, day, month)`.
20pub fn find_year_closest_to_ref(ref_date: JsDate, day: i64, month: i64) -> i64 {
21    let mut date = ref_date;
22    date.set_month(month - 1);
23    date.set_date(day);
24    let next_year = add_duration(date, &mut Duration::from_pairs(&[(DurationUnit::Year, 1.0)]));
25    let last_year = add_duration(date, &mut Duration::from_pairs(&[(DurationUnit::Year, -1.0)]));
26    let distance = |d: JsDate| match (d.get_time(), ref_date.get_time()) {
27        (Some(a), Some(b)) => Some((a - b).abs()),
28        _ => None,
29    };
30    // JS `<` with NaN is false.
31    let lt = |a: Option<i64>, b: Option<i64>| matches!((a, b), (Some(a), Some(b)) if a < b);
32    if lt(distance(next_year), distance(date)) {
33        date = next_year;
34    } else if lt(distance(last_year), distance(date)) {
35        date = last_year;
36    }
37    date.get_full_year()
38}
39
40#[cfg(test)]
41mod tests {
42    use super::*;
43
44    #[test]
45    fn most_likely_year() {
46        assert_eq!(find_most_likely_ad_year(97), 1997);
47        assert_eq!(find_most_likely_ad_year(12), 2012);
48        assert_eq!(find_most_likely_ad_year(50), 2050);
49        assert_eq!(find_most_likely_ad_year(2012), 2012);
50    }
51
52    #[test]
53    fn closest_year() {
54        let r = JsDate::parse_iso("2012-12-20T00:00:00.000Z").unwrap();
55        assert_eq!(find_year_closest_to_ref(r, 2, 1), 2013);
56        let r = JsDate::parse_iso("2013-01-05T00:00:00.000Z").unwrap();
57        assert_eq!(find_year_closest_to_ref(r, 28, 12), 2012);
58        assert_eq!(find_year_closest_to_ref(r, 1, 6), 2013);
59    }
60}