duration.bend
bend-datetime@0.4.0.0 · 322 lines · 0 definitions
1import Base
2
3type Duration.Error is Data:
4 OutOfRange{}
5
6type Duration is Data:
7 Duration{days: U32, sod: U32, nanos: U32}
8
9type Duration.Hms is Data:
10 Hms{hours: U32, minutes: U32, seconds: U32}
11
12def Duration.zero() -> Duration:
13 Duration{0, 0, 0}
14
15def Duration.fit(+days: U32, +sod: U32) -> Bool:
16 Bool.or(
17 U32.is_lt(days, 49710),
18 Bool.and(U32.is_eq(days, 49710), U32.is_le(sod, 23295))
19 )
20
21def Duration.to_secs.add(
22 +days: U32, +sod: U32, ok: Bool
23) -> Result<&2, &2, Duration.Error, U32>:
24 match ok:
25 case False{}:
26 Fail{OutOfRange{}}
27 case True{}:
28 Done{U32.add(U32.mul(days, 86400), sod)}
29
30def Duration.to_secs(d: Duration) -> Result<&2, &2, Duration.Error, U32>:
31 match d:
32 case Duration{+days, +sod, _}:
33 Duration.to_secs.add(days, sod, Duration.fit(days, sod))
34
35def Duration.from_secs(+secs: U32) -> Duration:
36 Duration{U32.div(secs, 86400), U32.mod(secs, 86400), 0}
37
38def Duration.from_days(+days: U32) -> Duration:
39 Duration{days, 0, 0}
40
41def Duration.from_hms.s2(
42 +sec: U32, +s: U32, ok: Bool
43) -> Result<&2, &2, Duration.Error, Duration>:
44 match ok:
45 case False{}:
46 Fail{OutOfRange{}}
47 case True{}:
48 Done{Duration.from_secs(U32.add(sec, s))}
49
50def Duration.from_hms.s(
51 +sec: U32, +s: U32
52) -> Result<&2, &2, Duration.Error, Duration>:
53 Duration.from_hms.s2(sec, s, U32.is_le(s, U32.sub(U32.not(0), sec)))
54
55def Duration.from_hms.hm2(
56 +hsec: U32, +msec: U32, +s: U32, ok: Bool
57) -> Result<&2, &2, Duration.Error, Duration>:
58 match ok:
59 case False{}:
60 Fail{OutOfRange{}}
61 case True{}:
62 Duration.from_hms.s(U32.add(hsec, msec), s)
63
64def Duration.from_hms.hm(
65 +hsec: U32, +mi: U32, +s: U32
66) -> Result<&2, &2, Duration.Error, Duration>:
67 +msec = U32.mul(mi, 60)
68 Duration.from_hms.hm2(
69 hsec, msec, s, U32.is_le(msec, U32.sub(U32.not(0), hsec))
70 )
71
72def Duration.from_hms.h(
73 +h: U32, +mi: U32, +s: U32, ok: Bool
74) -> Result<&2, &2, Duration.Error, Duration>:
75 match ok:
76 case False{}:
77 Fail{OutOfRange{}}
78 case True{}:
79 Duration.from_hms.hm(U32.mul(h, 3600), mi, s)
80
81def Duration.from_hms.r(
82 +h: U32, +mi: U32, +s: U32, ok: Bool
83) -> Result<&2, &2, Duration.Error, Duration>:
84 match ok:
85 case False{}:
86 Fail{OutOfRange{}}
87 case True{}:
88 Duration.from_hms.h(
89 h, mi, s, U32.is_le(h, U32.div(U32.not(0), 3600))
90 )
91
92def Duration.from_hms(
93 +h: U32, +mi: U32, +s: U32
94) -> Result<&2, &2, Duration.Error, Duration>:
95 Duration.from_hms.r(
96 h, mi, s, Bool.and(U32.is_le(mi, 59), U32.is_le(s, 59))
97 )
98
99def Duration.from_hours(+h: U32) -> Result<&2, &2, Duration.Error, Duration>:
100 Duration.from_hms(h, 0, 0)
101
102def Duration.from_mins.go(
103 +mi: U32, ok: Bool
104) -> Result<&2, &2, Duration.Error, Duration>:
105 match ok:
106 case False{}:
107 Fail{OutOfRange{}}
108 case True{}:
109 Done{Duration.from_secs(U32.mul(mi, 60))}
110
111def Duration.from_mins(+mi: U32) -> Result<&2, &2, Duration.Error, Duration>:
112 Duration.from_mins.go(mi, U32.is_le(mi, U32.div(U32.not(0), 60)))
113
114def Duration.is_eq(a: Duration, b: Duration) -> Bool:
115 match a b:
116 case Duration{+d1, +s1, +n1} Duration{+d2, +s2, +n2}:
117 Bool.and(
118 U32.is_eq(d1, d2),
119 Bool.and(U32.is_eq(s1, s2), U32.is_eq(n1, n2))
120 )
121
122def Duration.is_lt.n(+n1: U32, +n2: U32, eq_s: Bool, slt: Bool) -> Bool:
123 match eq_s:
124 case False{}:
125 slt
126 case True{}:
127 U32.is_lt(n1, n2)
128
129def Duration.is_lt.s(
130 +s1: U32, +n1: U32, +s2: U32, +n2: U32, eq_d: Bool, dlt: Bool
131) -> Bool:
132 match eq_d:
133 case False{}:
134 dlt
135 case True{}:
136 Duration.is_lt.n(n1, n2, U32.is_eq(s1, s2), U32.is_lt(s1, s2))
137
138def Duration.is_lt(a: Duration, b: Duration) -> Bool:
139 match a b:
140 case Duration{+d1, +s1, +n1} Duration{+d2, +s2, +n2}:
141 Duration.is_lt.s(
142 s1, n1, s2, n2, U32.is_eq(d1, d2), U32.is_lt(d1, d2)
143 )
144
145def Duration.is_gt(a: Duration, b: Duration) -> Bool:
146 Duration.is_lt(b, a)
147
148def Duration.is_le(a: Duration, b: Duration) -> Bool:
149 Bool.not(Duration.is_lt(b, a))
150
151def Duration.is_ge(a: Duration, b: Duration) -> Bool:
152 Bool.not(Duration.is_lt(a, b))
153
154def Duration.add.days(
155 +d1: U32, +d2: U32, +sod: U32, +nanos: U32, carry: U32, ok: Bool
156) -> Result<&2, &2, Duration.Error, Duration>:
157 match ok:
158 case False{}:
159 Fail{OutOfRange{}}
160 case True{}:
161 Done{Duration{U32.add(U32.add(d1, d2), carry), sod, nanos}}
162
163def Duration.add.sod2(
164 +d1: U32, +d2: U32, +sod: U32, +nanos: U32, ge: Bool
165) -> Result<&2, &2, Duration.Error, Duration>:
166 match ge:
167 case False{}:
168 Duration.add.days(
169 d1, d2, sod, nanos, 0, U32.is_le(d2, U32.sub(U32.not(0), d1))
170 )
171 case True{}:
172 Duration.add.days(
173 d1, d2, U32.sub(sod, 86400), nanos, 1,
174 U32.is_le(U32.add(d2, 1), U32.sub(U32.not(0), d1))
175 )
176
177def Duration.add.sod(
178 +d1: U32, +d2: U32, +s1: U32, +s2: U32, +nanos: U32, nc: U32
179) -> Result<&2, &2, Duration.Error, Duration>:
180 +sod = U32.add(U32.add(s1, s2), nc)
181 Duration.add.sod2(d1, d2, sod, nanos, U32.is_ge(sod, 86400))
182
183def Duration.add.n2(
184 +d1: U32, +d2: U32, +s1: U32, +s2: U32, +ns: U32, ge: Bool
185) -> Result<&2, &2, Duration.Error, Duration>:
186 match ge:
187 case False{}:
188 Duration.add.sod(d1, d2, s1, s2, ns, 0)
189 case True{}:
190 Duration.add.sod(d1, d2, s1, s2, U32.sub(ns, 1000000000), 1)
191
192def Duration.add.n(
193 +d1: U32, +d2: U32, +s1: U32, +s2: U32, +n1: U32, +n2: U32
194) -> Result<&2, &2, Duration.Error, Duration>:
195 +ns = U32.add(n1, n2)
196 Duration.add.n2(d1, d2, s1, s2, ns, U32.is_ge(ns, 1000000000))
197
198def Duration.add(
199 a: Duration, b: Duration
200) -> Result<&2, &2, Duration.Error, Duration>:
201 match a b:
202 case Duration{d1, s1, n1} Duration{d2, s2, n2}:
203 Duration.add.n(d1, d2, s1, s2, n1, n2)
204
205def Duration.sub.days(
206 +days: U32, +sod: U32, +nanos: U32, +b_days: U32, ok: Bool
207) -> Result<&2, &2, Duration.Error, Duration>:
208 match ok:
209 case False{}:
210 Fail{OutOfRange{}}
211 case True{}:
212 Done{Duration{U32.sub(days, b_days), sod, nanos}}
213
214def Duration.sub.s2(
215 +days: U32, +sod: U32, +nanos: U32, +b_days: U32, +b_sod: U32, borrow: Bool
216) -> Result<&2, &2, Duration.Error, Duration>:
217 match borrow:
218 case False{}:
219 Duration.sub.days(days, U32.sub(sod, b_sod), nanos, b_days, U32.is_ge(days, b_days))
220 case True{}:
221 Duration.sub.days(
222 U32.sub(days, 1), U32.sub(U32.add(sod, 86400), b_sod), nanos, b_days,
223 U32.is_ge(days, U32.add(b_days, 1))
224 )
225
226def Duration.sub.s(
227 +days: U32, +sod: U32, +nanos: U32, +b_days: U32, +b_sod: U32
228) -> Result<&2, &2, Duration.Error, Duration>:
229 Duration.sub.s2(days, sod, nanos, b_days, b_sod, U32.is_lt(sod, b_sod))
230
231def Duration.sub.n2(
232 +days: U32, +sod: U32, +n1: U32, +b_days: U32, +b_sod: U32, +b_n: U32, borrow: Bool
233) -> Result<&2, &2, Duration.Error, Duration>:
234 match borrow:
235 case False{}:
236 Duration.sub.s(days, sod, U32.sub(n1, b_n), b_days, b_sod)
237 case True{}:
238 Duration.sub.s(
239 days, sod, U32.sub(U32.add(n1, 1000000000), b_n), b_days, b_sod
240 )
241
242def Duration.sub.n0(
243 +days: U32, +n1: U32, +b_days: U32, +b_sod: U32, +b_n: U32, zdays: Bool
244) -> Result<&2, &2, Duration.Error, Duration>:
245 match zdays:
246 case True{}:
247 Fail{OutOfRange{}}
248 case False{}:
249 Duration.sub.s(
250 U32.sub(days, 1), 86399, U32.sub(U32.add(n1, 1000000000), b_n),
251 b_days, b_sod
252 )
253
254def Duration.sub.n2b(
255 +days: U32, +sod: U32, +n1: U32, +b_days: U32, +b_sod: U32, +b_n: U32, borrow: Bool, z: Bool
256) -> Result<&2, &2, Duration.Error, Duration>:
257 match borrow z:
258 case True{} True{}:
259 Duration.sub.n0(days, n1, b_days, b_sod, b_n, U32.is_eq(days, 0))
260 case True{} False{}:
261 Duration.sub.n2(days, U32.sub(sod, 1), n1, b_days, b_sod, b_n, True{})
262 case False{} True{}:
263 Duration.sub.n2(days, sod, n1, b_days, b_sod, b_n, False{})
264 case False{} False{}:
265 Duration.sub.n2(days, sod, n1, b_days, b_sod, b_n, False{})
266
267def Duration.sub.n(
268 +days: U32, +sod: U32, +n1: U32, +b_days: U32, +b_sod: U32, +b_n: U32
269) -> Result<&2, &2, Duration.Error, Duration>:
270 +borrow = U32.is_lt(n1, b_n)
271 Duration.sub.n2b(days, sod, n1, b_days, b_sod, b_n, borrow, U32.is_eq(sod, 0))
272
273def Duration.sub.go(a: Duration, b: Duration) -> Result<&2, &2, Duration.Error, Duration>:
274 match a b:
275 case Duration{d1, s1, n1} Duration{d2, s2, n2}:
276 Duration.sub.n(d1, s1, n1, d2, s2, n2)
277
278def Duration.sub.lt(
279 a: Duration, b: Duration, lt: Bool
280) -> Result<&2, &2, Duration.Error, Duration>:
281 match lt:
282 case True{}:
283 Fail{OutOfRange{}}
284 case False{}:
285 Duration.sub.go(a, b)
286
287def Duration.sub(
288 +a: Duration, +b: Duration
289) -> Result<&2, &2, Duration.Error, Duration>:
290 Duration.sub.lt(a, b, Duration.is_lt(a, b))
291
292def Duration.to_hms.ok(+days: U32, +sod: U32) -> Bool:
293 +cap = U32.div(U32.not(0), 24)
294 Bool.or(
295 U32.is_lt(days, cap),
296 Bool.and(
297 U32.is_eq(days, cap),
298 U32.is_le(U32.div(sod, 3600), U32.mod(U32.not(0), 24))
299 )
300 )
301
302def Duration.to_hms.go(
303 +days: U32, +sod: U32, ok: Bool
304) -> Result<&2, &2, Duration.Error, Duration.Hms>:
305 match ok:
306 case False{}:
307 Fail{OutOfRange{}}
308 case True{}:
309 Done{
310 Hms{
311 U32.add(U32.mul(days, 24), U32.div(sod, 3600)),
312 U32.div(U32.mod(sod, 3600), 60),
313 U32.mod(sod, 60)
314 }
315 }
316
317def Duration.to_hms(
318 d: Duration
319) -> Result<&2, &2, Duration.Error, Duration.Hms>:
320 match d:
321 case Duration{+days, +sod, _}:
322 Duration.to_hms.go(days, sod, Duration.to_hms.ok(days, sod))