1use core::{
2 fmt::{self, Debug},
3 ops::{Add, AddAssign, Sub, SubAssign},
4};
5
6use crate::{Calendar, CalendarTime, Duration, TimeResult, WrittenTime};
7
8const NANOS_IN_SECS: i128 = 1_000_000_000;
9
10#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
14pub struct Time {
15 nanos: i128,
19}
20
21impl Time {
22 pub const POSIX_EPOCH: Time = Time { nanos: 0 };
24
25 pub(crate) const fn from_tai_nanos(nanos: i128) -> Option<Time> {
26 Time::from_nanos_since_posix_epoch(nanos).checked_sub(&Duration::from_secs(10))
27 }
28
29 pub(crate) const fn as_tai_nanos(&self) -> Option<i128> {
30 self.nanos.checked_add(10 * NANOS_IN_SECS)
31 }
32
33 pub(crate) const fn from_nanos_since_posix_epoch(nanos: i128) -> Time {
34 Time { nanos }
35 }
36
37 pub fn try_now() -> crate::Result<TimeResult> {
42 crate::tz::System::now().read()
45 }
46
47 pub fn now() -> Time {
58 Self::try_now()
59 .expect("System time out of range")
60 .any_approximate()
61 }
62
63 pub fn read<Tim: CalendarTime>(t: Tim) -> crate::Result<TimeResult> {
65 t.read()
66 }
67
68 pub fn write<Cal: Calendar>(&self, cal: Cal) -> crate::Result<WrittenTime<Cal>> {
70 cal.write(self)
71 }
72
73 pub const fn checked_add(&self, rhs: &Duration) -> Option<Time> {
75 match self.nanos.checked_add(rhs.nanos()) {
77 Some(n) => Some(Time::from_nanos_since_posix_epoch(n)),
78 None => None,
79 }
80 }
81
82 pub const fn checked_sub(&self, rhs: &Duration) -> Option<Time> {
84 match self.nanos.checked_sub(rhs.nanos()) {
86 Some(n) => Some(Time::from_nanos_since_posix_epoch(n)),
87 None => None,
88 }
89 }
90
91 pub fn duration_since(&self, rhs: &Time) -> Duration {
93 self.checked_duration_since(rhs)
94 .expect("overflow computing duration since another time")
95 }
96
97 pub fn checked_duration_since(&self, rhs: &Time) -> Option<Duration> {
101 self.nanos.checked_sub(rhs.nanos).map(Duration::from_nanos)
102 }
103}
104
105impl Add<Duration> for Time {
106 type Output = Time;
107
108 fn add(self, rhs: Duration) -> Self::Output {
109 self.checked_add(&rhs)
110 .expect("overflow adding duration to a time")
111 }
112}
113
114impl AddAssign<Duration> for Time {
115 fn add_assign(&mut self, rhs: Duration) {
116 *self = *self + rhs;
117 }
118}
119
120impl Sub<Duration> for Time {
121 type Output = Time;
122
123 fn sub(self, rhs: Duration) -> Self::Output {
124 self.checked_sub(&rhs)
125 .expect("overflow subtracting duration from a time")
126 }
127}
128
129impl SubAssign<Duration> for Time {
130 fn sub_assign(&mut self, rhs: Duration) {
131 *self = *self - rhs;
132 }
133}
134
135impl Sub<Time> for Time {
136 type Output = Duration;
137
138 fn sub(self, rhs: Time) -> Self::Output {
139 self.duration_since(&rhs)
140 }
141}
142
143impl Debug for Time {
146 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
147 write!(
148 f,
149 "{}.{}",
150 self.nanos / NANOS_IN_SECS,
151 (self.nanos % NANOS_IN_SECS).abs(),
152 )
153 }
154}