Coverage Report

Created: 2025-10-19 21:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}