/home/a220/proj/radnelac/src/calendar/moment.rs
Line | Count | Source |
1 | | // This Source Code Form is subject to the terms of the Mozilla Public |
2 | | // License, v. 2.0. If a copy of the MPL was not distributed with this |
3 | | // file, You can obtain one at https://mozilla.org/MPL/2.0/. |
4 | | |
5 | | use crate::calendar::CommonDate; |
6 | | use crate::calendar::CommonWeekOfYear; |
7 | | use crate::calendar::GuaranteedMonth; |
8 | | use crate::calendar::HasEpagemonae; |
9 | | use crate::calendar::HasLeapYears; |
10 | | use crate::calendar::OrdinalDate; |
11 | | use crate::calendar::Perennial; |
12 | | use crate::calendar::Quarter; |
13 | | use crate::calendar::ToFromCommonDate; |
14 | | use crate::calendar::ToFromOrdinalDate; |
15 | | use crate::clock::ClockTime; |
16 | | use crate::clock::TimeOfDay; |
17 | | use crate::day_count::BoundedDayCount; |
18 | | use crate::day_count::EffectiveBound; |
19 | | use crate::day_count::Epoch; |
20 | | use crate::day_count::Fixed; |
21 | | use crate::day_count::FromFixed; |
22 | | use crate::day_count::ToFixed; |
23 | | use crate::day_cycle::Weekday; |
24 | | use crate::CalendarError; |
25 | | use num_traits::FromPrimitive; |
26 | | use num_traits::ToPrimitive; |
27 | | use std::num::NonZero; |
28 | | |
29 | | /// Represents an instant in time using calendar system T |
30 | | #[derive(Debug, PartialEq, PartialOrd, Clone, Copy)] |
31 | | pub struct CalendarMoment<T> { |
32 | | date: T, |
33 | | time: ClockTime, |
34 | | } |
35 | | |
36 | | impl<T> CalendarMoment<T> { |
37 | | /// Create a CalendarMoment with the given date and time |
38 | 43.1k | pub fn new(date: T, t: TimeOfDay) -> Self { |
39 | 43.1k | Self { |
40 | 43.1k | date: date, |
41 | 43.1k | time: t.to_clock(), |
42 | 43.1k | } |
43 | 43.1k | } |
44 | | |
45 | | /// Date of the given CalendarMoment |
46 | 768 | pub fn date(self) -> T { |
47 | 768 | self.date |
48 | 768 | } |
49 | | |
50 | | /// Time of day of the given CalendarMoment |
51 | 0 | pub fn time_of_day(self) -> ClockTime { |
52 | 0 | self.time |
53 | 0 | } |
54 | | } |
55 | | |
56 | | impl<T: FromFixed> FromFixed for CalendarMoment<T> { |
57 | 19.7k | fn from_fixed(fixed_date: Fixed) -> Self { |
58 | 19.7k | Self::new(T::from_fixed(fixed_date), TimeOfDay::from_fixed(fixed_date)) |
59 | 19.7k | } |
60 | | } |
61 | | |
62 | | impl<T: ToFixed> ToFixed for CalendarMoment<T> { |
63 | 7.32k | fn to_fixed(self) -> Fixed { |
64 | 7.32k | let fd = self.date.to_fixed(); |
65 | 7.32k | let ft = TimeOfDay::try_from_clock(self.time).expect("Guaranteed valid"); |
66 | 7.32k | Fixed::new(fd.to_day().get() + ft.get()) |
67 | 7.32k | } |
68 | | } |
69 | | |
70 | | impl<T: Epoch> Epoch for CalendarMoment<T> { |
71 | 771 | fn epoch() -> Fixed { |
72 | 771 | T::epoch() |
73 | 771 | } |
74 | | } |
75 | | |
76 | | impl<T: EffectiveBound> EffectiveBound for CalendarMoment<T> { |
77 | 17 | fn effective_min() -> Self { |
78 | 17 | Self::new(T::effective_min(), TimeOfDay::midnight()) |
79 | 17 | } |
80 | 17 | fn effective_max() -> Self { |
81 | 17 | Self::new(T::effective_max(), TimeOfDay::midnight()) |
82 | 17 | } |
83 | | } |
84 | | |
85 | | impl<T: HasLeapYears> HasLeapYears for CalendarMoment<T> { |
86 | 10.7k | fn is_leap(year: i32) -> bool { |
87 | 10.7k | T::is_leap(year) |
88 | 10.7k | } |
89 | | } |
90 | | |
91 | | impl<T, U> ToFromCommonDate<T> for CalendarMoment<U> |
92 | | where |
93 | | T: FromPrimitive, |
94 | | U: ToFromCommonDate<T> + EffectiveBound, |
95 | | { |
96 | 13.7k | fn to_common_date(self) -> CommonDate { |
97 | 13.7k | self.date.to_common_date() |
98 | 13.7k | } |
99 | | |
100 | 0 | fn from_common_date_unchecked(d: CommonDate) -> Self { |
101 | 0 | Self::new(U::from_common_date_unchecked(d), TimeOfDay::midnight()) |
102 | 0 | } |
103 | | |
104 | 256 | fn valid_ymd(d: CommonDate) -> Result<(), CalendarError> { |
105 | 256 | U::valid_ymd(d) |
106 | 256 | } |
107 | | |
108 | 1 | fn year_start_date(year: i32) -> CommonDate { |
109 | 1 | U::year_start_date(year) |
110 | 1 | } |
111 | | |
112 | 2 | fn year_end_date(year: i32) -> CommonDate { |
113 | 2 | U::year_end_date(year) |
114 | 2 | } |
115 | | |
116 | 0 | fn month_length(year: i32, month: T) -> u8 { |
117 | 0 | U::month_length(year, month) |
118 | 0 | } |
119 | | |
120 | 0 | fn in_effective_bounds(d: CommonDate) -> bool { |
121 | 0 | U::in_effective_bounds(d) |
122 | 0 | } |
123 | | |
124 | 23.6k | fn try_from_common_date(d: CommonDate) -> Result<Self, CalendarError> { |
125 | 23.6k | let d22.6k = U::try_from_common_date(d)?1.02k ; |
126 | 22.6k | Ok(Self::new(d, TimeOfDay::midnight())) |
127 | 23.6k | } |
128 | | |
129 | 256 | fn try_year_start(year: i32) -> Result<Self, CalendarError> { |
130 | 256 | let d = U::try_year_start(year)?0 ; |
131 | 256 | Ok(Self::new(d, TimeOfDay::midnight())) |
132 | 256 | } |
133 | | |
134 | 256 | fn try_year_end(year: i32) -> Result<Self, CalendarError> { |
135 | 256 | let d = U::try_year_end(year)?0 ; |
136 | 256 | Ok(Self::new(d, TimeOfDay::midnight())) |
137 | 256 | } |
138 | | |
139 | 0 | fn day(self) -> u8 { |
140 | 0 | self.date.day() |
141 | 0 | } |
142 | | |
143 | 15.2k | fn try_month(self) -> Option<T> { |
144 | 15.2k | self.date.try_month() |
145 | 15.2k | } |
146 | | |
147 | 8 | fn year(self) -> i32 { |
148 | 8 | self.date.year() |
149 | 8 | } |
150 | | } |
151 | | |
152 | | impl<T, U> GuaranteedMonth<T> for CalendarMoment<U> |
153 | | where |
154 | | T: FromPrimitive + ToPrimitive, |
155 | | U: GuaranteedMonth<T>, |
156 | | { |
157 | 0 | fn month(self) -> T { |
158 | 0 | self.date.month() |
159 | 0 | } |
160 | | |
161 | 0 | fn try_new(year: i32, month: T, day: u8) -> Result<Self, CalendarError> { |
162 | 0 | let d = U::try_new(year, month, day)?; |
163 | 0 | Ok(Self::new(d, TimeOfDay::midnight())) |
164 | 0 | } |
165 | | } |
166 | | |
167 | | impl<T, U> HasEpagemonae<T> for CalendarMoment<U> |
168 | | where |
169 | | T: FromPrimitive + ToPrimitive, |
170 | | U: HasEpagemonae<T>, |
171 | | { |
172 | 773 | fn epagomenae(self) -> Option<T> { |
173 | 773 | self.date.epagomenae() |
174 | 773 | } |
175 | | |
176 | 0 | fn epagomenae_count(p_year: i32) -> u8 { |
177 | 0 | U::epagomenae_count(p_year) |
178 | 0 | } |
179 | | } |
180 | | |
181 | | impl<S, T, U> Perennial<S, T> for CalendarMoment<U> |
182 | | where |
183 | | S: FromPrimitive + ToPrimitive, |
184 | | T: FromPrimitive + ToPrimitive, |
185 | | U: Perennial<S, T>, |
186 | | { |
187 | 768 | fn weekday(self) -> Option<T> { |
188 | 768 | self.date.weekday() |
189 | 768 | } |
190 | | |
191 | 1.28k | fn days_per_week() -> u8 { |
192 | 1.28k | U::days_per_week() |
193 | 1.28k | } |
194 | | |
195 | 1.27k | fn weeks_per_month() -> u8 { |
196 | 1.27k | U::weeks_per_month() |
197 | 1.27k | } |
198 | | |
199 | 3.84k | fn try_week_of_year(self) -> Option<u8> { |
200 | 3.84k | self.date.try_week_of_year() |
201 | 3.84k | } |
202 | | } |
203 | | |
204 | | impl<T: Quarter> Quarter for CalendarMoment<T> { |
205 | 2.56k | fn quarter(self) -> NonZero<u8> { |
206 | 2.56k | self.date.quarter() |
207 | 2.56k | } |
208 | | } |
209 | | |
210 | | impl<T, U> CommonWeekOfYear<T> for CalendarMoment<U> |
211 | | where |
212 | | T: FromPrimitive, |
213 | | U: CommonWeekOfYear<T> + ToFixed, |
214 | | { |
215 | 8.44k | fn week_of_year(self) -> u8 { |
216 | 8.44k | self.date.week_of_year() |
217 | 8.44k | } |
218 | | |
219 | 0 | fn nth_kday(self, nz: NonZero<i16>, k: Weekday) -> Fixed { |
220 | 0 | self.date.nth_kday(nz, k) |
221 | 0 | } |
222 | | } |
223 | | |
224 | | impl<T: ToFromOrdinalDate> ToFromOrdinalDate for CalendarMoment<T> { |
225 | 1.28k | fn valid_ordinal(ord: OrdinalDate) -> Result<(), CalendarError> { |
226 | 1.28k | T::valid_ordinal(ord) |
227 | 1.28k | } |
228 | | |
229 | 512 | fn ordinal_from_fixed(fixed_date: Fixed) -> OrdinalDate { |
230 | 512 | T::ordinal_from_fixed(fixed_date) |
231 | 512 | } |
232 | | |
233 | 1.79k | fn to_ordinal(self) -> OrdinalDate { |
234 | 1.79k | self.date.to_ordinal() |
235 | 1.79k | } |
236 | | |
237 | 256 | fn from_ordinal_unchecked(ord: OrdinalDate) -> Self { |
238 | 256 | Self::new(T::from_ordinal_unchecked(ord), TimeOfDay::midnight()) |
239 | 256 | } |
240 | | } |