1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#[derive(Debug, Eq, PartialEq)]
pub struct Date {
pub year: i32,
pub month: u32,
pub day: u32,
}
impl Date {
pub fn ymd(y: i32, m: u32, d: u32) -> Self {
Date {
year: y,
month: m,
day: d,
}
}
}
const OUT_OF_RANGE_ERR: &'static str = "Computus is only valid from 1583 to 9999";
pub fn gregorian(year: i32) -> Result<::Date, &'static str> {
if year < 1583 || year > 9999 {
return Err(::OUT_OF_RANGE_ERR);
}
let aa = year % 19;
let bb = year / 100;
let cc = year % 100;
let dd = bb / 4;
let ee = bb % 4;
let ff = (bb + 8) / 25;
let gg = (bb - ff + 1) / 3;
let hh = (19 * aa + bb - dd - gg + 15) % 30;
let ii = cc / 4;
let kk = cc % 4;
let ll = (32 + 2 * ee + 2 * ii - hh - kk) % 7;
let mm = (aa + 11 * hh + 22 * ll) / 451;
let month = (hh + ll - 7 * mm + 114) / 31;
let day = (hh + ll - 7 * mm + 114) % 31 + 1;
Ok(::Date::ymd(year, month as u32, day as u32))
}
pub fn julian(year: i32) -> Result<::Date, &'static str> {
if year < 1583 || year > 9999 {
return Err(::OUT_OF_RANGE_ERR);
}
let aa = year % 4;
let bb = year % 7;
let cc = year % 19;
let dd = (19 * cc + 15) % 30;
let ee = (2 * aa + 4 * bb - dd + 34) % 7;
let ff = dd + ee + 114;
let month = ff / 31;
let day = ff % 31 + 1;
Ok(::Date::ymd(year, month as u32, day as u32))
}
#[cfg(test)]
mod tests {
#[test]
fn gregorian_month_day() {
use super::{gregorian, Date};
assert_eq!(gregorian(1961), Ok(Date::ymd(1961, 4, 2)));
assert_eq!(gregorian(1996), Ok(Date::ymd(1996, 4, 7)));
assert_eq!(gregorian(1997), Ok(Date::ymd(1997, 3, 30)));
assert_eq!(gregorian(1998), Ok(Date::ymd(1998, 4, 12)));
assert_eq!(gregorian(2000), Ok(Date::ymd(2000, 4, 23)));
assert_eq!(gregorian(2001), Ok(Date::ymd(2001, 4, 15)));
assert_eq!(gregorian(2002), Ok(Date::ymd(2002, 3, 31)));
assert_eq!(gregorian(2003), Ok(Date::ymd(2003, 4, 20)));
assert_eq!(gregorian(2004), Ok(Date::ymd(2004, 4, 11)));
assert_eq!(gregorian(2005), Ok(Date::ymd(2005, 3, 27)));
assert_eq!(gregorian(2006), Ok(Date::ymd(2006, 4, 16)));
assert_eq!(gregorian(2007), Ok(Date::ymd(2007, 4, 8)));
assert_eq!(gregorian(2008), Ok(Date::ymd(2008, 3, 23)));
assert_eq!(gregorian(2009), Ok(Date::ymd(2009, 4, 12)));
assert_eq!(gregorian(2010), Ok(Date::ymd(2010, 4, 4)));
assert_eq!(gregorian(2011), Ok(Date::ymd(2011, 4, 24)));
assert_eq!(gregorian(2012), Ok(Date::ymd(2012, 4, 8)));
assert_eq!(gregorian(2013), Ok(Date::ymd(2013, 3, 31)));
assert_eq!(gregorian(2014), Ok(Date::ymd(2014, 4, 20)));
assert_eq!(gregorian(2015), Ok(Date::ymd(2015, 4, 5)));
assert_eq!(gregorian(2016), Ok(Date::ymd(2016, 3, 27)));
assert_eq!(gregorian(2017), Ok(Date::ymd(2017, 4, 16)));
assert_eq!(gregorian(2018), Ok(Date::ymd(2018, 4, 1)));
assert_eq!(gregorian(2019), Ok(Date::ymd(2019, 4, 21)));
assert_eq!(gregorian(2020), Ok(Date::ymd(2020, 4, 12)));
assert_eq!(gregorian(2021), Ok(Date::ymd(2021, 4, 4)));
assert_eq!(gregorian(2022), Ok(Date::ymd(2022, 4, 17)));
assert_eq!(gregorian(3035), Ok(Date::ymd(3035, 4, 19)));
assert_eq!(gregorian(4000), Ok(Date::ymd(4000, 4, 9)));
assert_eq!(gregorian(9999), Ok(Date::ymd(9999, 3, 28)));
}
#[test]
fn julian_month_day() {
use super::{julian, Date};
assert_eq!(julian(1961), Ok(Date::ymd(1961, 3, 27)));
assert_eq!(julian(1996), Ok(Date::ymd(1996, 4, 1)));
assert_eq!(julian(1997), Ok(Date::ymd(1997, 4, 14)));
assert_eq!(julian(1998), Ok(Date::ymd(1998, 4, 6)));
assert_eq!(julian(1999), Ok(Date::ymd(1999, 3, 29)));
assert_eq!(julian(2000), Ok(Date::ymd(2000, 4, 17)));
assert_eq!(julian(2001), Ok(Date::ymd(2001, 4, 2)));
assert_eq!(julian(2002), Ok(Date::ymd(2002, 4, 22)));
assert_eq!(julian(2003), Ok(Date::ymd(2003, 4, 14)));
assert_eq!(julian(2004), Ok(Date::ymd(2004, 3, 29)));
assert_eq!(julian(2005), Ok(Date::ymd(2005, 4, 18)));
assert_eq!(julian(2006), Ok(Date::ymd(2006, 4, 10)));
assert_eq!(julian(2007), Ok(Date::ymd(2007, 3, 26)));
assert_eq!(julian(2008), Ok(Date::ymd(2008, 4, 14)));
assert_eq!(julian(2009), Ok(Date::ymd(2009, 4, 6)));
assert_eq!(julian(2010), Ok(Date::ymd(2010, 3, 22)));
assert_eq!(julian(2011), Ok(Date::ymd(2011, 4, 11)));
assert_eq!(julian(2012), Ok(Date::ymd(2012, 4, 2)));
assert_eq!(julian(2013), Ok(Date::ymd(2013, 4, 22)));
assert_eq!(julian(2014), Ok(Date::ymd(2014, 4, 7)));
assert_eq!(julian(2015), Ok(Date::ymd(2015, 3, 30)));
assert_eq!(julian(2016), Ok(Date::ymd(2016, 4, 18)));
assert_eq!(julian(2017), Ok(Date::ymd(2017, 4, 3)));
assert_eq!(julian(2018), Ok(Date::ymd(2018, 3, 26)));
assert_eq!(julian(2019), Ok(Date::ymd(2019, 4, 15)));
assert_eq!(julian(2020), Ok(Date::ymd(2020, 4, 6)));
}
}