• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

geo-engine / geoengine / 11911118784

19 Nov 2024 10:06AM UTC coverage: 90.448% (-0.2%) from 90.687%
11911118784

push

github

web-flow
Merge pull request #994 from geo-engine/workspace-dependencies

use workspace dependencies, update toolchain, use global lock in expression

9 of 11 new or added lines in 6 files covered. (81.82%)

369 existing lines in 74 files now uncovered.

132871 of 146904 relevant lines covered (90.45%)

54798.62 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.8
/datatypes/src/primitives/time_instance.rs
1
use super::datetime::DateTimeError;
2
use super::{DateTime, Duration};
3
use crate::primitives::error;
4
use crate::util::Result;
5
use postgres_types::{FromSql, ToSql};
6
use serde::{Deserialize, Serialize};
7
use snafu::ensure;
8
use std::ops::AddAssign;
9
use std::{
10
    convert::TryFrom,
11
    fmt::Formatter,
12
    ops::{Add, Sub},
13
    str::FromStr,
14
};
15

16
#[derive(Clone, Copy, Serialize, PartialEq, Eq, PartialOrd, Ord, Debug, FromSql, ToSql)]
6,018✔
17
#[repr(C)]
18
#[postgres(transparent)]
19
pub struct TimeInstance(i64);
20

21
impl TimeInstance {
22
    pub fn from_millis(millis: i64) -> Result<Self> {
3,549✔
23
        ensure!(
3,549✔
24
            Self::MIN.inner() <= millis && millis <= Self::MAX.inner(),
3,549✔
25
            error::InvalidTimeInstance {
1✔
26
                min: Self::MIN,
1✔
27
                max: Self::MAX,
1✔
28
                is: millis
1✔
29
            }
1✔
30
        );
31

32
        Ok(TimeInstance(millis))
3,548✔
33
    }
3,549✔
34

35
    pub const fn from_millis_unchecked(millis: i64) -> Self {
3,836✔
36
        TimeInstance(millis)
3,836✔
37
    }
3,836✔
38

39
    #[allow(clippy::missing_panics_doc)]
40
    pub fn as_datetime_string(self) -> String {
98✔
41
        let instance = self.clamp(TimeInstance::MIN, TimeInstance::MAX);
98✔
42

98✔
43
        instance
98✔
44
            .as_date_time()
98✔
45
            .expect("TimeInstance is not valid")
98✔
46
            .to_datetime_string()
98✔
47
    }
98✔
48

49
    #[allow(clippy::missing_panics_doc)]
50
    pub fn as_datetime_string_with_millis(self) -> String {
1,611✔
51
        let instance = self.clamp(TimeInstance::MIN, TimeInstance::MAX);
1,611✔
52

1,611✔
53
        instance
1,611✔
54
            .as_date_time()
1,611✔
55
            .expect("TimeInstance is not valid")
1,611✔
56
            .to_datetime_string_with_millis()
1,611✔
57
    }
1,611✔
58

59
    pub const fn inner(self) -> i64 {
103,809✔
60
        self.0
103,809✔
61
    }
103,809✔
62

63
    pub fn now() -> Self {
×
64
        Self::from(DateTime::now())
×
65
    }
×
66

67
    /// Converts a `TimeInstance` to a `DateTime`.
68
    /// If this would overflow the range of `DateTime`, the result is `None`.
69
    pub fn as_date_time(self) -> Option<DateTime> {
4,965✔
70
        DateTime::try_from(self).ok()
4,965✔
71
    }
4,965✔
72

73
    /// Returns true if this instance equals `Self::MIN`, i.e., represents the start of time.
74
    #[inline]
75
    pub fn is_min(self) -> bool {
2,580✔
76
        self == Self::MIN
2,580✔
77
    }
2,580✔
78

79
    /// Returns true if this instance equals `Self::MAX`, i.e., represents the end of time.
80
    #[inline]
81
    pub fn is_max(self) -> bool {
2,143✔
82
        self == Self::MAX
2,143✔
83
    }
2,143✔
84

85
    pub const MIN: Self = TimeInstance::from_millis_unchecked(-8_334_601_228_800_000);
86
    pub const MAX: Self = TimeInstance::from_millis_unchecked(8_210_266_876_799_999);
87

88
    pub const EPOCH_START: Self = TimeInstance::from_millis_unchecked(0);
89
}
90

91
impl std::fmt::Display for TimeInstance {
92
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
21✔
93
        let instance = self.clamp(&TimeInstance::MIN, &TimeInstance::MAX);
21✔
94
        let datetime = instance
21✔
95
            .as_date_time()
21✔
96
            .expect("time instance was clamped into valid range");
21✔
97
        write!(f, "{datetime}")
21✔
98
    }
21✔
99
}
100

101
impl TryFrom<i64> for TimeInstance {
102
    type Error = crate::error::Error;
103

104
    fn try_from(milliseconds: i64) -> Result<Self> {
3,002✔
105
        TimeInstance::from_millis(milliseconds)
3,002✔
106
    }
3,002✔
107
}
108

109
impl From<TimeInstance> for i64 {
110
    fn from(time_instance: TimeInstance) -> Self {
81,844✔
111
        time_instance.inner()
81,844✔
112
    }
81,844✔
113
}
114

115
impl Add<i64> for TimeInstance {
116
    type Output = Self;
117

118
    fn add(self, rhs: i64) -> Self::Output {
30✔
119
        if self.is_min() || self.is_max() {
30✔
120
            // begin and end of time are special values, we don't want to do arithmetics on them
121
            return self;
3✔
122
        }
27✔
123
        TimeInstance::from_millis_unchecked(self.0 + rhs)
27✔
124
    }
30✔
125
}
126

127
impl AddAssign<i64> for TimeInstance {
128
    fn add_assign(&mut self, rhs: i64) {
4✔
129
        *self = *self + rhs;
4✔
130
    }
4✔
131
}
132

133
impl Sub<i64> for TimeInstance {
134
    type Output = Self;
135

136
    fn sub(self, rhs: i64) -> Self::Output {
5✔
137
        if self.is_min() || self.is_max() {
5✔
138
            // begin and end of time are special values, we don't want to do arithmetics on them
139
            return self;
3✔
140
        }
2✔
141
        TimeInstance::from_millis_unchecked(self.0 - rhs)
2✔
142
    }
5✔
143
}
144

145
impl Add<Duration> for TimeInstance {
146
    type Output = Self;
147

148
    fn add(self, rhs: Duration) -> Self::Output {
6✔
149
        if self.is_min() || self.is_max() {
6✔
150
            // begin and end of time are special values, we don't want to do arithmetics on them
151
            return self;
×
152
        }
6✔
153
        TimeInstance::from_millis_unchecked(self.0 + rhs.num_milliseconds())
6✔
154
    }
6✔
155
}
156

157
impl Sub<Duration> for TimeInstance {
158
    type Output = Self;
159

160
    fn sub(self, rhs: Duration) -> Self::Output {
3✔
161
        if self.is_min() || self.is_max() {
3✔
162
            // begin and end of time are special values, we don't want to do arithmetics on them
163
            return self;
×
164
        }
3✔
165
        TimeInstance::from_millis_unchecked(self.0 - rhs.num_milliseconds())
3✔
166
    }
3✔
167
}
168

169
impl Sub<TimeInstance> for TimeInstance {
170
    type Output = Duration;
171

172
    fn sub(self, rhs: Self) -> Self::Output {
361✔
173
        Duration::milliseconds(self.0 - rhs.0)
361✔
174
    }
361✔
175
}
176

177
impl FromStr for TimeInstance {
178
    type Err = DateTimeError;
179

180
    fn from_str(s: &str) -> Result<Self, Self::Err> {
390✔
181
        let date_time = DateTime::from_str(s)?;
390✔
182
        Ok(date_time.into())
390✔
183
    }
390✔
184
}
185

186
impl<'de> Deserialize<'de> for TimeInstance {
187
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
108✔
188
    where
108✔
189
        D: serde::Deserializer<'de>,
108✔
190
    {
108✔
191
        struct IsoStringOrUnixTimestamp;
192

193
        impl<'de> serde::de::Visitor<'de> for IsoStringOrUnixTimestamp {
194
            type Value = TimeInstance;
195

UNCOV
196
            fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
×
197
                formatter.write_str("RFC 3339 timestamp string or Unix timestamp integer")
×
198
            }
×
199

200
            fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
18✔
201
            where
18✔
202
                E: serde::de::Error,
18✔
203
            {
18✔
204
                TimeInstance::from_str(value).map_err(E::custom)
18✔
205
            }
18✔
206

207
            fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
90✔
208
            where
90✔
209
                E: serde::de::Error,
90✔
210
            {
90✔
211
                TimeInstance::from_millis(v).map_err(E::custom)
90✔
212
            }
90✔
213

214
            fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
84✔
215
            where
84✔
216
                E: serde::de::Error,
84✔
217
            {
84✔
218
                Self::visit_i64(self, v as i64)
84✔
219
            }
84✔
220
        }
221

222
        deserializer.deserialize_any(IsoStringOrUnixTimestamp)
108✔
223
    }
108✔
224
}
225

226
#[cfg(test)]
227
mod tests {
228
    use super::*;
229

230
    #[test]
231
    fn bounds_wrt_chrono() {
1✔
232
        assert_eq!(TimeInstance::MIN, TimeInstance::from(DateTime::MIN));
1✔
233
        assert_eq!(TimeInstance::MAX, TimeInstance::from(DateTime::MAX));
1✔
234
    }
1✔
235

236
    #[test]
237
    fn time_limits() {
1✔
238
        assert_eq!(TimeInstance::MIN + 1, TimeInstance::MIN);
1✔
239
        assert_eq!(TimeInstance::MIN - 1, TimeInstance::MIN);
1✔
240
        assert_eq!(TimeInstance::MAX + 1, TimeInstance::MAX);
1✔
241
        assert_eq!(TimeInstance::MAX - 1, TimeInstance::MAX);
1✔
242
    }
1✔
243
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc