Skip to content

Commit 056a52e

Browse files
committed
feat(lox-time): add intervals
1 parent 6dd0659 commit 056a52e

File tree

3 files changed

+152
-1
lines changed

3 files changed

+152
-1
lines changed

crates/lox-orbits/src/events.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,6 @@ impl<T: TimeScale> Window<T> {
140140

141141
fn contains(&self, other: &Self) -> bool
142142
where
143-
// FIXME: Manually implement `Ord` on `Time`
144143
T: Ord,
145144
{
146145
self.start <= other.start && self.end >= other.end

crates/lox-time/src/intervals.rs

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
// SPDX-FileCopyrightText: 2025 Helge Eichhorn <[email protected]>
2+
//
3+
// SPDX-License-Identifier: MPL-2.0
4+
5+
use std::{
6+
cmp::{max, min},
7+
fmt::Display,
8+
ops::Sub,
9+
};
10+
11+
use lox_core::time::deltas::TimeDelta;
12+
13+
use crate::{
14+
Time,
15+
offsets::{DefaultOffsetProvider, TryOffset},
16+
time_scales::{Tai, TimeScale},
17+
utc::{Utc, UtcError, transformations::TryToUtc},
18+
};
19+
20+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
21+
pub struct Interval<T> {
22+
start: T,
23+
end: T,
24+
}
25+
26+
impl<T> Interval<T> {
27+
pub fn new(start: T, end: T) -> Self {
28+
Interval { start, end }
29+
}
30+
31+
pub fn start(&self) -> T
32+
where
33+
T: Copy,
34+
{
35+
self.start
36+
}
37+
38+
pub fn end(&self) -> T
39+
where
40+
T: Copy,
41+
{
42+
self.end
43+
}
44+
45+
pub fn duration(&self) -> TimeDelta
46+
where
47+
T: Sub<Output = TimeDelta> + Copy,
48+
{
49+
self.end - self.start
50+
}
51+
52+
pub fn is_empty(&self) -> bool
53+
where
54+
T: Ord,
55+
{
56+
self.start >= self.end
57+
}
58+
59+
pub fn contains_time(&self, time: T) -> bool
60+
where
61+
T: Ord,
62+
{
63+
self.start <= time && time < self.end
64+
}
65+
66+
pub fn intersect(&self, other: Self) -> Self
67+
where
68+
T: Ord + Copy,
69+
{
70+
Interval {
71+
start: max(self.start, other.start),
72+
end: min(self.end, other.end),
73+
}
74+
}
75+
76+
pub fn overlaps(&self, other: Self) -> bool
77+
where
78+
T: Ord + Copy,
79+
{
80+
!self.intersect(other).is_empty()
81+
}
82+
}
83+
84+
pub type TimeDeltaInterval = Interval<TimeDelta>;
85+
86+
impl TimeDeltaInterval {
87+
pub fn to_scale<T: TimeScale + Copy>(&self, scale: T) -> TimeInterval<T> {
88+
Interval {
89+
start: Time::from_delta(scale, self.start),
90+
end: Time::from_delta(scale, self.end),
91+
}
92+
}
93+
}
94+
95+
pub type TimeInterval<T> = Interval<Time<T>>;
96+
97+
impl<T> TimeInterval<T>
98+
where
99+
T: TryToUtc + TimeScale + Copy,
100+
DefaultOffsetProvider: TryOffset<T, Tai>,
101+
{
102+
pub fn to_utc(&self) -> Result<UtcInterval, UtcError> {
103+
Ok(Interval {
104+
start: self.start.try_to_utc()?,
105+
end: self.end.try_to_utc()?,
106+
})
107+
}
108+
}
109+
110+
pub type UtcInterval = Interval<Utc>;
111+
112+
impl UtcInterval {
113+
pub fn to_time(&self) -> TimeInterval<Tai> {
114+
Interval {
115+
start: self.start.to_time(),
116+
end: self.end.to_time(),
117+
}
118+
}
119+
}
120+
121+
impl<T> Display for Interval<T>
122+
where
123+
T: Display,
124+
{
125+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
126+
self.start.fmt(f)?;
127+
write!(f, " – ")?;
128+
self.end.fmt(f)
129+
}
130+
}
131+
132+
#[cfg(test)]
133+
mod tests {
134+
use crate::{time, time_scales::Tai};
135+
136+
use super::*;
137+
138+
#[test]
139+
fn test_time_interval() {
140+
let t0 = time!(Tai, 2025, 11, 6).unwrap();
141+
let t1 = time!(Tai, 2025, 11, 6, 1).unwrap();
142+
let i = TimeInterval::new(t0, t1);
143+
assert_eq!(i.start(), t0);
144+
assert_eq!(i.end(), t1);
145+
assert_eq!(i.duration(), TimeDelta::from_hours(1.0));
146+
assert_eq!(
147+
format!("{}", i),
148+
"2025-11-06T00:00:00.000 TAI – 2025-11-06T01:00:00.000 TAI"
149+
);
150+
}
151+
}

crates/lox-time/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232

3333
pub mod calendar_dates;
3434
pub mod deltas;
35+
pub mod intervals;
3536
pub mod julian_dates;
3637
pub mod offsets;
3738
pub mod ranges;

0 commit comments

Comments
 (0)