/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::HasIntercalaryDays; |
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.7k | pub fn new(date: T, t: TimeOfDay) -> Self { |
39 | 43.7k | Self { |
40 | 43.7k | date: date, |
41 | 43.7k | time: t.to_clock(), |
42 | 43.7k | } |
43 | 43.7k | } |
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.30k | fn to_fixed(self) -> Fixed { |
64 | 7.30k | let fd = self.date.to_fixed(); |
65 | 7.30k | let ft = TimeOfDay::try_from_clock(self.time).expect("Guaranteed valid"); |
66 | 7.30k | Fixed::new(fd.to_day().get() + ft.get()) |
67 | 7.30k | } |
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 | 14.0k | fn to_common_date(self) -> CommonDate { |
97 | 14.0k | self.date.to_common_date() |
98 | 14.0k | } |
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 in_effective_bounds(d: CommonDate) -> bool { |
117 | 0 | U::in_effective_bounds(d) |
118 | 0 | } |
119 | | |
120 | 24.1k | fn try_from_common_date(d: CommonDate) -> Result<Self, CalendarError> { |
121 | 24.1k | let d23.1k = U::try_from_common_date(d)?1.02k ; |
122 | 23.1k | Ok(Self::new(d, TimeOfDay::midnight())) |
123 | 24.1k | } |
124 | | |
125 | 256 | fn try_year_start(year: i32) -> Result<Self, CalendarError> { |
126 | 256 | let d = U::try_year_start(year)?0 ; |
127 | 256 | Ok(Self::new(d, TimeOfDay::midnight())) |
128 | 256 | } |
129 | | |
130 | 256 | fn try_year_end(year: i32) -> Result<Self, CalendarError> { |
131 | 256 | let d = U::try_year_end(year)?0 ; |
132 | 256 | Ok(Self::new(d, TimeOfDay::midnight())) |
133 | 256 | } |
134 | | |
135 | 0 | fn day(self) -> u8 { |
136 | 0 | self.date.day() |
137 | 0 | } |
138 | | |
139 | 15.5k | fn try_month(self) -> Option<T> { |
140 | 15.5k | self.date.try_month() |
141 | 15.5k | } |
142 | | |
143 | 12 | fn year(self) -> i32 { |
144 | 12 | self.date.year() |
145 | 12 | } |
146 | | } |
147 | | |
148 | | impl<T, U> GuaranteedMonth<T> for CalendarMoment<U> |
149 | | where |
150 | | T: FromPrimitive + ToPrimitive, |
151 | | U: GuaranteedMonth<T>, |
152 | | { |
153 | 0 | fn month(self) -> T { |
154 | 0 | self.date.month() |
155 | 0 | } |
156 | | |
157 | 0 | fn try_new(year: i32, month: T, day: u8) -> Result<Self, CalendarError> { |
158 | 0 | let d = U::try_new(year, month, day)?; |
159 | 0 | Ok(Self::new(d, TimeOfDay::midnight())) |
160 | 0 | } |
161 | | } |
162 | | |
163 | | impl<T, U> HasIntercalaryDays<T> for CalendarMoment<U> |
164 | | where |
165 | | T: FromPrimitive + ToPrimitive, |
166 | | U: HasIntercalaryDays<T>, |
167 | | { |
168 | 769 | fn complementary(self) -> Option<T> { |
169 | 769 | self.date.complementary() |
170 | 769 | } |
171 | | |
172 | 0 | fn complementary_count(p_year: i32) -> u8 { |
173 | 0 | U::complementary_count(p_year) |
174 | 0 | } |
175 | | } |
176 | | |
177 | | impl<S, T, U> Perennial<S, T> for CalendarMoment<U> |
178 | | where |
179 | | S: FromPrimitive + ToPrimitive, |
180 | | T: FromPrimitive + ToPrimitive, |
181 | | U: Perennial<S, T>, |
182 | | { |
183 | 768 | fn weekday(self) -> Option<T> { |
184 | 768 | self.date.weekday() |
185 | 768 | } |
186 | | |
187 | 1.28k | fn days_per_week() -> u8 { |
188 | 1.28k | U::days_per_week() |
189 | 1.28k | } |
190 | | |
191 | 1.26k | fn weeks_per_month() -> u8 { |
192 | 1.26k | U::weeks_per_month() |
193 | 1.26k | } |
194 | | |
195 | 3.84k | fn try_week_of_year(self) -> Option<u8> { |
196 | 3.84k | self.date.try_week_of_year() |
197 | 3.84k | } |
198 | | } |
199 | | |
200 | | impl<T: Quarter> Quarter for CalendarMoment<T> { |
201 | 2.81k | fn quarter(self) -> NonZero<u8> { |
202 | 2.81k | self.date.quarter() |
203 | 2.81k | } |
204 | | } |
205 | | |
206 | | impl<T, U> CommonWeekOfYear<T> for CalendarMoment<U> |
207 | | where |
208 | | T: FromPrimitive, |
209 | | U: CommonWeekOfYear<T> + ToFixed, |
210 | | { |
211 | 8.44k | fn week_of_year(self) -> u8 { |
212 | 8.44k | self.date.week_of_year() |
213 | 8.44k | } |
214 | | |
215 | 0 | fn nth_kday(self, nz: NonZero<i16>, k: Weekday) -> Fixed { |
216 | 0 | self.date.nth_kday(nz, k) |
217 | 0 | } |
218 | | } |
219 | | |
220 | | impl<T: ToFromOrdinalDate> ToFromOrdinalDate for CalendarMoment<T> { |
221 | 1.28k | fn valid_ordinal(ord: OrdinalDate) -> Result<(), CalendarError> { |
222 | 1.28k | T::valid_ordinal(ord) |
223 | 1.28k | } |
224 | | |
225 | 512 | fn ordinal_from_fixed(fixed_date: Fixed) -> OrdinalDate { |
226 | 512 | T::ordinal_from_fixed(fixed_date) |
227 | 512 | } |
228 | | |
229 | 1.79k | fn to_ordinal(self) -> OrdinalDate { |
230 | 1.79k | self.date.to_ordinal() |
231 | 1.79k | } |
232 | | |
233 | 256 | fn from_ordinal_unchecked(ord: OrdinalDate) -> Self { |
234 | 256 | Self::new(T::from_ordinal_unchecked(ord), TimeOfDay::midnight()) |
235 | 256 | } |
236 | | } |