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
use earth_orbit::*;
use moon_phase::*;
use sun_transit::*;
pub fn get_date(timestamp: i64, longitude: f64, use_solar_calendar: bool) -> String {
let now = timestamp;
let lon = longitude;
let mut tom = now + 86400;
let mut mid = get_midnight(now, lon);
if mid > now {
tom = now;
mid = get_midnight(now - 86400, lon);
}
let n = 2 + (now / 86400 / 365) as usize;
let k = if use_solar_calendar { 4 } else { 1 };
let mut seasonal_events = (1 * k .. n * k).map(|i| {
let new_year_timestamp = ((i / k) as f64 * 86400.0 * 365.25) as i64;
let mid_year_timestamp = new_year_timestamp - 180 * 86400;
let new_year_timestamp = get_previous_december_solstice(mid_year_timestamp);
match (i % k) + 4 - k {
0 => get_next_march_equinox(new_year_timestamp),
1 => get_next_june_solstice(new_year_timestamp),
2 => get_next_september_equinox(new_year_timestamp),
3 => get_next_december_solstice(new_year_timestamp),
_ => unreachable!()
}
});
let mut next_seasonal_event = seasonal_events.next().unwrap();
let m = n * 13;
let mut new_moons = (0..m).map(|i| {
let lunation_number = (i as f64) - 371.0;
get_new_moon(lunation_number)
});
let mut new_moon = new_moons.next().unwrap();
let mut d = 0;
let mut m = 0;
let mut y = 0;
let mut t = get_midnight(0, lon);
if t < 0 {
t += 86400;
}
while t < mid - 2000 {
d += 1;
t += 86400;
if use_solar_calendar {
if next_seasonal_event < (t + 86400) {
next_seasonal_event = seasonal_events.next().unwrap();
d = 0;
m += 1;
if m == 4 {
m = 0;
y += 1;
}
}
} else {
if new_moon < (t + 86400) {
new_moon = new_moons.next().unwrap();
d = 0;
m += 1;
if next_seasonal_event < (t + 86400) {
next_seasonal_event = seasonal_events.next().unwrap();
m = 0;
y += 1;
}
}
}
}
let e = (10000 * (now - mid)) / (get_midnight(tom, lon) - mid);
let c = e / 100;
let b = e % 100;
format!("{:02}:{:02}:{:02}:{:02}:{:02}", y, m, d, c, b)
}
pub fn get_lunisolar_date(timestamp: i64, longitude: f64) -> String {
get_date(timestamp, longitude, false)
}
pub fn get_solar_date(timestamp: i64, longitude: f64) -> String {
get_date(timestamp, longitude, true)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn get_solar_date_test() {
assert_eq!("44:02:00:15:42", get_solar_date(1403322675, -1.826189));
}
#[test]
fn get_lunisolar_date_test() {
assert_eq!("14:03:03:71:61", get_lunisolar_date(449947500, -2.7653));
}
}