Coverage Report

Created: 2025-08-13 21:02

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::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
}