deep_time/t_span/
constructors.rs1use crate::{
2 ATTOS_PER_FS, ATTOS_PER_MS, ATTOS_PER_NS, ATTOS_PER_PS, ATTOS_PER_SEC, ATTOS_PER_SEC_I128,
3 ATTOS_PER_SECF, ATTOS_PER_US, Dt, Real, SEC_PER_DAYI64, SEC_PER_WEEK, Scale, TSpan, floor_f,
4};
5
6impl TSpan {
7 pub const ZERO: Self = Self { sec: 0, attos: 0 };
9
10 pub const MAX: Self = Self {
12 sec: i64::MAX,
13 attos: ATTOS_PER_SEC - 1,
14 };
15
16 pub const MIN: Self = Self {
18 sec: i64::MIN,
19 attos: 0,
20 };
21
22 pub const SEC_19: Self = Self::from_sec(19);
23 pub const SEC_33: Self = Self::from_sec(33);
24 pub const SEC_37: Self = Self::from_sec(37);
25 pub const ONE_DAY: Self = Self::from_days(1);
26
27 pub const fn from_attos(mut attos: i128) -> Self {
29 if attos > (i64::MAX as i128) * ATTOS_PER_SEC_I128 {
30 return Self::MAX;
31 }
32 if attos < (i64::MIN as i128) * ATTOS_PER_SEC_I128 {
33 return Self::MIN;
34 }
35
36 if attos >= 0 {
37 let sec = (attos / ATTOS_PER_SEC_I128) as i64;
38 let attos = (attos % ATTOS_PER_SEC_I128) as u64;
39 Self { sec, attos }
40 } else {
41 attos = -attos;
42 let sec_pos = (attos / ATTOS_PER_SEC_I128) as i64;
43 let rem = (attos % ATTOS_PER_SEC_I128) as u64;
44 if rem == 0 {
45 Self {
46 sec: -sec_pos,
47 attos: 0,
48 }
49 } else {
50 Self {
51 sec: -sec_pos - 1,
52 attos: ATTOS_PER_SEC - rem,
53 }
54 }
55 }
56 }
57
58 #[inline]
62 pub const fn new(sec: i64, attos: u64) -> Self {
63 let mut dt = Self { sec, attos };
64 dt.carry_over();
65 dt
66 }
67
68 #[inline]
70 pub const fn from_sec(s: i64) -> Self {
71 Self::new(s, 0)
72 }
73
74 #[inline]
76 pub const fn from_ms(ms: i128) -> Self {
77 Self::from_attos(ms.saturating_mul(ATTOS_PER_MS as i128))
78 }
79
80 #[inline]
82 pub const fn from_us(us: i128) -> Self {
83 Self::from_attos(us.saturating_mul(ATTOS_PER_US as i128))
84 }
85
86 #[inline]
88 pub const fn from_ns(ns: i128) -> Self {
89 Self::from_attos(ns.saturating_mul(ATTOS_PER_NS as i128))
90 }
91
92 #[inline]
94 pub const fn from_ps(ps: i128) -> Self {
95 Self::from_attos(ps.saturating_mul(ATTOS_PER_PS as i128))
96 }
97
98 #[inline]
100 pub const fn from_fs(fs: i128) -> Self {
101 Self::from_attos(fs.saturating_mul(ATTOS_PER_FS as i128))
102 }
103
104 #[inline]
106 pub const fn from_min(m: i64) -> Self {
107 Self::from_sec(m * 60)
108 }
109
110 #[inline]
112 pub const fn from_hr(h: i64) -> Self {
113 Self::from_sec(h * 3600)
114 }
115
116 #[inline]
117 pub const fn from_days(d: i64) -> TSpan {
118 Self::from_sec(d.saturating_mul(SEC_PER_DAYI64))
119 }
120
121 #[inline]
122 pub const fn wk(wk: i64) -> TSpan {
123 TSpan::from_sec(wk.saturating_mul(SEC_PER_WEEK))
124 }
125
126 #[inline]
127 pub const fn yr(yr: i64) -> TSpan {
128 TSpan::from_sec(yr.saturating_mul(31_557_600))
129 }
130
131 #[inline]
133 pub const fn ago(self, scale: Scale) -> Dt {
134 Dt::from(0, 0, scale).sub(self)
135 }
136
137 #[inline]
139 pub const fn from_now(self, scale: Scale) -> Dt {
140 Dt::from(0, 0, scale).add(self)
141 }
142
143 #[inline]
146 pub const fn from_hms(hr: i64, min: i64, sec: i64, ms: i64, us: i64, ns: i64) -> Self {
147 let total_secs = hr * 3600i64 + min * 60i64 + sec;
148
149 let sub_ns = ms * 1_000_000i64 + us * 1_000i64 + ns;
150
151 if sub_ns == 0 {
152 return Self::new(total_secs, 0);
153 }
154
155 let abs_ns = sub_ns.unsigned_abs();
156 let extra_secs = (abs_ns / 1_000_000_000u64) as i64;
157 let rem_ns = abs_ns % 1_000_000_000u64;
158 let frac = rem_ns * ATTOS_PER_NS;
159
160 let (final_secs, final_frac) = if sub_ns >= 0 {
161 (total_secs + extra_secs, frac)
162 } else if frac == 0 {
163 (total_secs - extra_secs, 0)
164 } else {
165 (total_secs - extra_secs - 1, ATTOS_PER_SEC - frac)
166 };
167
168 Self::new(final_secs, final_frac)
169 }
170
171 #[inline]
173 pub const fn neg(self) -> Self {
174 if self.attos == 0 {
175 Self {
176 sec: -self.sec,
177 attos: 0,
178 }
179 } else {
180 Self {
181 sec: -self.sec - 1,
182 attos: ATTOS_PER_SEC - self.attos,
183 }
184 }
185 }
186
187 pub const fn from_sec_f(sec_f: Real) -> Self {
189 if sec_f.is_nan() {
190 return Self::ZERO;
191 }
192 if sec_f.is_infinite() {
193 return if sec_f.is_sign_positive() {
194 Self::MAX
195 } else {
196 Self::MIN
197 };
198 }
199
200 let floor_val = floor_f(sec_f);
201 let frac = sec_f - floor_val;
202 let attos_frac = (frac * ATTOS_PER_SECF) as i128;
203
204 let total = (floor_val as i128) * ATTOS_PER_SEC_I128 + attos_frac;
205 Self::from_attos(total)
206 }
207}