1import { describe, it } from "@effect/vitest"
2import {
3 assertFalse,
4 assertNone,
5 assertSome,
6 assertTrue,
7 deepStrictEqual,
8 strictEqual,
9 throws
10} from "@effect/vitest/utils"
11import { Duration, Equal, Hash, HashSet, pipe } from "effect"
12
13describe("Duration", () => {
14 it("fromInputUnsafe", () => {
15 const millis100 = Duration.millis(100)
16 assertTrue(Duration.fromInputUnsafe(millis100) === millis100)
17
18 deepStrictEqual(Duration.fromInputUnsafe(100), millis100)
19
20 deepStrictEqual(Duration.fromInputUnsafe(10n), Duration.nanos(10n))
21
22 deepStrictEqual(Duration.fromInputUnsafe("1 nano"), Duration.nanos(1n))
23 deepStrictEqual(Duration.fromInputUnsafe("10 nanos"), Duration.nanos(10n))
24 deepStrictEqual(Duration.fromInputUnsafe("1.5 nanos"), Duration.nanos(2n))
25 deepStrictEqual(Duration.fromInputUnsafe("-1.5 nanos"), Duration.nanos(-2n))
26 deepStrictEqual(Duration.fromInputUnsafe("9007199254740993.1 nanos"), Duration.nanos(9_007_199_254_740_993n))
27 deepStrictEqual(Duration.fromInputUnsafe("-9007199254740993.5 nanos"), Duration.nanos(-9_007_199_254_740_994n))
28 deepStrictEqual(Duration.fromInputUnsafe("1 micro"), Duration.micros(1n))
29 deepStrictEqual(Duration.fromInputUnsafe("10 micros"), Duration.micros(10n))
30 deepStrictEqual(Duration.fromInputUnsafe("1.5 micros"), Duration.nanos(1500n))
31 deepStrictEqual(Duration.fromInputUnsafe("-1.5 micros"), Duration.nanos(-1500n))
32 deepStrictEqual(
33 Duration.fromInputUnsafe("9007199254740993.1 micros"),
34 Duration.nanos(9_007_199_254_740_993_100n)
35 )
36 deepStrictEqual(
37 Duration.fromInputUnsafe("-9007199254740993.0005 micros"),
38 Duration.nanos(-9_007_199_254_740_993_001n)
39 )
40 deepStrictEqual(Duration.fromInputUnsafe("1 milli"), Duration.millis(1))
41 deepStrictEqual(Duration.fromInputUnsafe("10 millis"), Duration.millis(10))
42 deepStrictEqual(Duration.fromInputUnsafe("1 second"), Duration.seconds(1))
43 deepStrictEqual(Duration.fromInputUnsafe("10 seconds"), Duration.seconds(10))
44 deepStrictEqual(Duration.fromInputUnsafe("1 minute"), Duration.minutes(1))
45 deepStrictEqual(Duration.fromInputUnsafe("10 minutes"), Duration.minutes(10))
46 deepStrictEqual(Duration.fromInputUnsafe("1 hour"), Duration.hours(1))
47 deepStrictEqual(Duration.fromInputUnsafe("10 hours"), Duration.hours(10))
48 deepStrictEqual(Duration.fromInputUnsafe("1 day"), Duration.days(1))
49 deepStrictEqual(Duration.fromInputUnsafe("10 days"), Duration.days(10))
50 deepStrictEqual(Duration.fromInputUnsafe("1 week"), Duration.weeks(1))
51 deepStrictEqual(Duration.fromInputUnsafe("10 weeks"), Duration.weeks(10))
52
53 deepStrictEqual(Duration.fromInputUnsafe("1.5 seconds"), Duration.seconds(1.5))
54 deepStrictEqual(Duration.fromInputUnsafe("-1.5 seconds"), Duration.seconds(-1.5))
55 deepStrictEqual(Duration.fromInputUnsafe("Infinity"), Duration.infinity)
56 deepStrictEqual(Duration.fromInputUnsafe("-Infinity"), Duration.negativeInfinity)
57
58 deepStrictEqual(Duration.fromInputUnsafe([500, 123456789]), Duration.nanos(500123456789n))
59 deepStrictEqual(Duration.fromInputUnsafe([-500, 123456789]), Duration.nanos(-500000000000n + 123456789n))
60 deepStrictEqual(Duration.fromInputUnsafe([0, 1.5]), Duration.nanos(2n))
61 deepStrictEqual(Duration.fromInputUnsafe([0, -1.5]), Duration.nanos(-2n))
62 deepStrictEqual(Duration.fromInputUnsafe([0.0000000005, 0.5]), Duration.nanos(1n))
63 deepStrictEqual(Duration.fromInputUnsafe([Infinity, 0]), Duration.infinity)
64 deepStrictEqual(Duration.fromInputUnsafe([-Infinity, 0]), Duration.negativeInfinity)
65 deepStrictEqual(Duration.fromInputUnsafe([NaN, 0]), Duration.zero)
66 deepStrictEqual(Duration.fromInputUnsafe([0, Infinity]), Duration.infinity)
67 deepStrictEqual(Duration.fromInputUnsafe([0, -Infinity]), Duration.negativeInfinity)
68 deepStrictEqual(Duration.fromInputUnsafe([0, NaN]), Duration.zero)
69
70 // object input
71 deepStrictEqual(Duration.fromInputUnsafe({}), Duration.zero)
72 deepStrictEqual(Duration.fromInputUnsafe({ hours: 2 }), Duration.hours(2))
73 deepStrictEqual(Duration.fromInputUnsafe({ weeks: 1 }), Duration.weeks(1))
74 deepStrictEqual(Duration.fromInputUnsafe({ days: 3 }), Duration.days(3))
75 deepStrictEqual(Duration.fromInputUnsafe({ minutes: 45 }), Duration.minutes(45))
76 deepStrictEqual(Duration.fromInputUnsafe({ seconds: 30 }), Duration.seconds(30))
77 deepStrictEqual(Duration.fromInputUnsafe({ milliseconds: 500 }), Duration.millis(500))
78 deepStrictEqual(
79 Duration.fromInputUnsafe({ hours: 1, minutes: 30 }),
80 Duration.sum(Duration.hours(1), Duration.minutes(30))
81 )
82 deepStrictEqual(Duration.fromInputUnsafe({ hours: -1 }), Duration.hours(-1))
83 deepStrictEqual(
84 Duration.fromInputUnsafe({ seconds: 1, nanoseconds: 500 }),
85 Duration.nanos(1_000_000_500n)
86 )
87 deepStrictEqual(
88 Duration.fromInputUnsafe({ microseconds: 100 }),
89 Duration.micros(100n)
90 )
91 deepStrictEqual(
92 Duration.fromInputUnsafe({ microseconds: -1.5 }),
93 Duration.nanos(-1500n)
94 )
95 deepStrictEqual(
96 Duration.fromInputUnsafe({ nanoseconds: 1.5 }),
97 Duration.nanos(2n)
98 )
99 deepStrictEqual(
100 Duration.fromInputUnsafe({ nanoseconds: -1.5 }),
101 Duration.nanos(-2n)
102 )
103 deepStrictEqual(
104 Duration.fromInputUnsafe({ milliseconds: 0.0000005, nanoseconds: 0.5 }),
105 Duration.nanos(1n)
106 )
107 deepStrictEqual(
108 Duration.fromInputUnsafe({ days: 1, hours: 2, minutes: 30, seconds: 15 }),
109 Duration.sum(
110 Duration.sum(Duration.days(1), Duration.hours(2)),
111 Duration.sum(Duration.minutes(30), Duration.seconds(15))
112 )
113 )
114 })
115
116 it("fromInput", () => {
117 const millis100 = Duration.millis(100)
118 assertSome(Duration.fromInput(millis100), millis100)
119
120 assertSome(Duration.fromInput(100), millis100)
121
122 assertSome(Duration.fromInput(10n), Duration.nanos(10n))
123
124 assertSome(Duration.fromInput("1 nano"), Duration.nanos(1n))
125 assertSome(Duration.fromInput("10 nanos"), Duration.nanos(10n))
126 assertSome(Duration.fromInput("1 micro"), Duration.micros(1n))
127 assertSome(Duration.fromInput("10 micros"), Duration.micros(10n))
128 assertSome(Duration.fromInput("1 milli"), Duration.millis(1))
129 assertSome(Duration.fromInput("10 millis"), Duration.millis(10))
130 assertSome(Duration.fromInput("1 second"), Duration.seconds(1))
131 assertSome(Duration.fromInput("10 seconds"), Duration.seconds(10))
132 assertSome(Duration.fromInput("1 minute"), Duration.minutes(1))
133 assertSome(Duration.fromInput("10 minutes"), Duration.minutes(10))
134 assertSome(Duration.fromInput("1 hour"), Duration.hours(1))
135 assertSome(Duration.fromInput("10 hours"), Duration.hours(10))
136 assertSome(Duration.fromInput("1 day"), Duration.days(1))
137 assertSome(Duration.fromInput("10 days"), Duration.days(10))
138 assertSome(Duration.fromInput("1 week"), Duration.weeks(1))
139 assertSome(Duration.fromInput("10 weeks"), Duration.weeks(10))
140
141 assertSome(Duration.fromInput("1.5 seconds"), Duration.seconds(1.5))
142 assertSome(Duration.fromInput("-1.5 seconds"), Duration.seconds(-1.5))
143 assertSome(Duration.fromInput("Infinity"), Duration.infinity)
144 assertSome(Duration.fromInput("-Infinity"), Duration.negativeInfinity)
145
146 assertSome(Duration.fromInput([500, 123456789]), Duration.nanos(500123456789n))
147 assertSome(Duration.fromInput([-500, 123456789]), Duration.nanos(-500000000000n + 123456789n))
148 assertSome(Duration.fromInput([Infinity, 0]), Duration.infinity)
149 assertSome(Duration.fromInput([-Infinity, 0]), Duration.negativeInfinity)
150 assertSome(Duration.fromInput([NaN, 0]), Duration.zero)
151 assertSome(Duration.fromInput([0, Infinity]), Duration.infinity)
152 assertSome(Duration.fromInput([0, -Infinity]), Duration.negativeInfinity)
153 assertSome(Duration.fromInput([0, NaN]), Duration.zero)
154
155 assertNone(Duration.fromInput("invalid" as any))
156 })
157
158 it("Order", () => {
159 // millis
160 deepStrictEqual(Duration.Order(Duration.millis(1), Duration.millis(2)), -1)
161 deepStrictEqual(Duration.Order(Duration.millis(2), Duration.millis(1)), 1)
162 deepStrictEqual(Duration.Order(Duration.millis(2), Duration.millis(2)), 0)
163 deepStrictEqual(Duration.Order(Duration.millis(1), Duration.nanos(2_000_000n)), -1)
164
165 // nanos
166 deepStrictEqual(Duration.Order(Duration.nanos(1n), Duration.nanos(2n)), -1)
167 deepStrictEqual(Duration.Order(Duration.nanos(2n), Duration.nanos(1n)), 1)
168 deepStrictEqual(Duration.Order(Duration.nanos(2n), Duration.nanos(2n)), 0)
169 deepStrictEqual(Duration.Order(Duration.nanos(2_000_000n), Duration.millis(1)), 1)
170
171 // infinity
172 deepStrictEqual(Duration.Order(Duration.infinity, Duration.infinity), 0)
173 deepStrictEqual(Duration.Order(Duration.infinity, Duration.millis(1)), 1)
174 deepStrictEqual(Duration.Order(Duration.infinity, Duration.nanos(1n)), 1)
175 deepStrictEqual(Duration.Order(Duration.millis(1), Duration.infinity), -1)
176 deepStrictEqual(Duration.Order(Duration.nanos(1n), Duration.infinity), -1)
177 })
178
179 it("Equivalence", () => {
180 // millis
181 assertTrue(Duration.Equivalence(Duration.millis(1), Duration.millis(1)))
182 assertTrue(Duration.Equivalence(Duration.millis(1), Duration.nanos(1_000_000n)))
183 assertFalse(Duration.Equivalence(Duration.millis(1), Duration.millis(2)))
184 assertFalse(Duration.Equivalence(Duration.millis(1), Duration.millis(2)))
185
186 // nanos
187 assertTrue(Duration.Equivalence(Duration.nanos(1n), Duration.nanos(1n)))
188 assertTrue(Duration.Equivalence(Duration.nanos(1_000_000n), Duration.millis(1)))
189 assertFalse(Duration.Equivalence(Duration.nanos(1n), Duration.nanos(2n)))
190 assertFalse(Duration.Equivalence(Duration.nanos(1n), Duration.nanos(2n)))
191
192 // infinity
193 assertTrue(Duration.Equivalence(Duration.infinity, Duration.infinity))
194 assertFalse(Duration.Equivalence(Duration.infinity, Duration.millis(1)))
195 assertFalse(Duration.Equivalence(Duration.infinity, Duration.nanos(1n)))
196 assertFalse(Duration.Equivalence(Duration.millis(1), Duration.infinity))
197 assertFalse(Duration.Equivalence(Duration.nanos(1n), Duration.infinity))
198 })
199
200 it("max", () => {
201 deepStrictEqual(Duration.max(Duration.millis(1), Duration.millis(2)), Duration.millis(2))
202 deepStrictEqual(Duration.max(Duration.minutes(1), Duration.millis(2)), Duration.minutes(1))
203 })
204
205 it("min", () => {
206 deepStrictEqual(Duration.min(Duration.millis(1), Duration.millis(2)), Duration.millis(1))
207 deepStrictEqual(Duration.min(Duration.minutes(1), Duration.millis(2)), Duration.millis(2))
208 })
209
210 it("clamp", () => {
211 deepStrictEqual(
212 Duration.clamp(Duration.millis(1), {
213 minimum: Duration.millis(2),
214 maximum: Duration.millis(3)
215 }),
216 Duration.millis(2)
217 )
218 deepStrictEqual(
219 Duration.clamp(Duration.minutes(1.5), {
220 minimum: Duration.minutes(1),
221 maximum: Duration.minutes(2)
222 }),
223 Duration.minutes(1.5)
224 )
225 })
226
227 it("equals", () => {
228 assertTrue(pipe(Duration.hours(1), Duration.equals(Duration.minutes(60))))
229 })
230
231 it("Hash.symbol agrees with equals across Millis/Nanos representations", () => {
232 const millisTagged = Duration.seconds(5)
233 const nanosTagged = Duration.nanos(5_000_000_000n)
234
235 assertTrue(Duration.equals(millisTagged, nanosTagged))
236 assertTrue(Equal.equals(millisTagged, nanosTagged))
237 strictEqual(Hash.hash(millisTagged), Hash.hash(nanosTagged))
238 strictEqual(Hash.hash(Duration.millis(-5000)), Hash.hash(Duration.nanos(-5_000_000_000n)))
239 strictEqual(Hash.hash(Duration.infinity), Hash.hash(Duration.infinity))
240 assertFalse(Equal.equals(Duration.infinity, Duration.negativeInfinity))
241
242 assertTrue(HashSet.has(HashSet.make(millisTagged), nanosTagged))
243 })
244
245 it("Hash.symbol handles finite millis too large to convert to nanos", () => {
246 const duration = Duration.millis(1e303)
247
248 assertTrue(Equal.equals(duration, Duration.millis(1e303)))
249 assertTrue(HashSet.has(HashSet.make(duration), Duration.millis(1e303)))
250 })
251
252 it("between", () => {
253 assertTrue(Duration.between(Duration.hours(1), {
254 minimum: Duration.minutes(59),
255 maximum: Duration.minutes(61)
256 }))
257 assertTrue(
258 Duration.between(Duration.minutes(1), {
259 minimum: Duration.seconds(59),
260 maximum: Duration.seconds(61)
261 })
262 )
263 })
264
265 it("divide", () => {
266 // millis
267 assertSome(Duration.divide(Duration.minutes(1), 2), Duration.seconds(30))
268 assertSome(Duration.divide(Duration.seconds(1), 3), Duration.nanos(333333333n))
269 assertSome(Duration.divide(Duration.zero, 2), Duration.zero)
270 assertSome(Duration.divide(Duration.minutes(1), 0.5), Duration.minutes(2))
271 assertSome(Duration.divide(Duration.minutes(1), 1.5), Duration.seconds(40))
272
273 // nanos
274 assertSome(Duration.divide(Duration.nanos(2n), 2), Duration.nanos(1n))
275 assertSome(Duration.divide(Duration.nanos(1n), 3), Duration.zero)
276 assertNone(Duration.divide(Duration.nanos(1n), 0.5))
277 assertNone(Duration.divide(Duration.nanos(1n), 1.5))
278
279 // infinity
280 assertSome(Duration.divide(Duration.infinity, 2), Duration.infinity)
281 assertSome(Duration.divide(Duration.infinity, -2), Duration.negativeInfinity)
282 assertSome(Duration.divide(Duration.negativeInfinity, -2), Duration.infinity)
283
284 // divide by zero
285 assertNone(Duration.divide(Duration.minutes(1), 0))
286 assertNone(Duration.divide(Duration.minutes(1), -0))
287 assertNone(Duration.divide(Duration.nanos(1n), 0))
288 assertNone(Duration.divide(Duration.nanos(1n), -0))
289
290 // bad by
291 assertNone(Duration.divide(Duration.minutes(1), NaN))
292 assertNone(Duration.divide(Duration.nanos(1n), NaN))
293 assertNone(Duration.divide(Duration.infinity, NaN))
294
295 assertNone(Duration.divide(Duration.minutes(1), Infinity))
296 assertNone(Duration.divide(Duration.nanos(1n), Infinity))
297 assertNone(Duration.divide(Duration.infinity, Infinity))
298
299 assertNone(Duration.divide(Duration.minutes(1), -Infinity))
300 assertNone(Duration.divide(Duration.nanos(1n), -Infinity))
301 assertNone(Duration.divide(Duration.infinity, -Infinity))
302 })
303
304 it("divideUnsafe", () => {
305 // millis
306 deepStrictEqual(Duration.divideUnsafe(Duration.minutes(1), 2), Duration.seconds(30))
307 deepStrictEqual(Duration.divideUnsafe(Duration.seconds(1), 3), Duration.nanos(333333333n))
308 deepStrictEqual(Duration.divideUnsafe(Duration.zero, 2), Duration.zero)
309 deepStrictEqual(Duration.divideUnsafe(Duration.minutes(1), 0.5), Duration.minutes(2))
310 deepStrictEqual(Duration.divideUnsafe(Duration.minutes(1), 1.5), Duration.seconds(40))
311
312 // nanos
313 deepStrictEqual(Duration.divideUnsafe(Duration.nanos(2n), 2), Duration.nanos(1n))
314 deepStrictEqual(Duration.divideUnsafe(Duration.nanos(1n), 3), Duration.zero)
315 deepStrictEqual(Duration.divideUnsafe(Duration.nanos(1n), 0.5), Duration.zero)
316 deepStrictEqual(Duration.divideUnsafe(Duration.nanos(1n), 1.5), Duration.zero)
317
318 // infinity
319 deepStrictEqual(Duration.divideUnsafe(Duration.infinity, 2), Duration.infinity)
320
321 // divide by zero (IEEE 754 sign rules)
322 deepStrictEqual(Duration.divideUnsafe(Duration.minutes(1), 0), Duration.infinity)
323 deepStrictEqual(Duration.divideUnsafe(Duration.minutes(1), -0), Duration.negativeInfinity)
324 deepStrictEqual(Duration.divideUnsafe(Duration.nanos(1n), 0), Duration.infinity)
325 deepStrictEqual(Duration.divideUnsafe(Duration.nanos(1n), -0), Duration.negativeInfinity)
326 deepStrictEqual(Duration.divideUnsafe(Duration.nanos(-1n), 0), Duration.negativeInfinity)
327 deepStrictEqual(Duration.divideUnsafe(Duration.nanos(-1n), -0), Duration.infinity)
328 deepStrictEqual(Duration.divideUnsafe(Duration.zero, 0), Duration.zero)
329 deepStrictEqual(Duration.divideUnsafe(Duration.zero, -0), Duration.zero)
330
331 // bad by
332 deepStrictEqual(Duration.divideUnsafe(Duration.minutes(1), NaN), Duration.zero)
333 deepStrictEqual(Duration.divideUnsafe(Duration.nanos(1n), NaN), Duration.zero)
334 deepStrictEqual(Duration.divideUnsafe(Duration.infinity, NaN), Duration.zero)
335
336 deepStrictEqual(Duration.divideUnsafe(Duration.minutes(1), Infinity), Duration.zero)
337 deepStrictEqual(Duration.divideUnsafe(Duration.nanos(1n), Infinity), Duration.zero)
338 deepStrictEqual(Duration.divideUnsafe(Duration.infinity, Infinity), Duration.zero)
339
340 deepStrictEqual(Duration.divideUnsafe(Duration.minutes(1), -Infinity), Duration.zero)
341 deepStrictEqual(Duration.divideUnsafe(Duration.nanos(1n), -Infinity), Duration.zero)
342 deepStrictEqual(Duration.divideUnsafe(Duration.infinity, -Infinity), Duration.zero)
343 })
344
345 it("times", () => {
346 deepStrictEqual(Duration.times(Duration.seconds(1), 60), Duration.minutes(1))
347 deepStrictEqual(Duration.times(Duration.nanos(2n), 10), Duration.nanos(20n))
348 deepStrictEqual(Duration.times(Duration.infinity, 60), Duration.infinity)
349 })
350
351 it("sum", () => {
352 // millis
353 deepStrictEqual(Duration.sum(Duration.seconds(30), Duration.seconds(30)), Duration.minutes(1))
354
355 // nanos
356 deepStrictEqual(Duration.sum(Duration.nanos(30n), Duration.nanos(30n)), Duration.nanos(60n))
357
358 // infinity
359 deepStrictEqual(Duration.sum(Duration.infinity, Duration.seconds(30)), Duration.infinity)
360 deepStrictEqual(Duration.sum(Duration.seconds(30), Duration.infinity), Duration.infinity)
361 deepStrictEqual(Duration.sum(Duration.infinity, Duration.nanos(1n)), Duration.infinity)
362 deepStrictEqual(Duration.sum(Duration.nanos(1n), Duration.infinity), Duration.infinity)
363 deepStrictEqual(Duration.sum(Duration.infinity, Duration.infinity), Duration.infinity)
364 })
365
366 it("subtract", () => {
367 // millis
368 deepStrictEqual(Duration.subtract(Duration.seconds(30), Duration.seconds(10)), Duration.seconds(20))
369 deepStrictEqual(Duration.subtract(Duration.seconds(30), Duration.seconds(30)), Duration.zero)
370 deepStrictEqual(Duration.subtract(Duration.seconds(30), Duration.seconds(40)), Duration.seconds(-10))
371
372 // nanos
373 deepStrictEqual(Duration.subtract(Duration.nanos(30n), Duration.nanos(10n)), Duration.nanos(20n))
374 deepStrictEqual(Duration.subtract(Duration.nanos(30n), Duration.nanos(30n)), Duration.zero)
375 deepStrictEqual(Duration.subtract(Duration.nanos(30n), Duration.nanos(40n)), Duration.nanos(-10n))
376
377 // infinity
378 deepStrictEqual(Duration.subtract(Duration.infinity, Duration.seconds(30)), Duration.infinity)
379 deepStrictEqual(Duration.subtract(Duration.infinity, Duration.nanos(30n)), Duration.infinity)
380 deepStrictEqual(Duration.subtract(Duration.seconds(30), Duration.infinity), Duration.negativeInfinity)
381 deepStrictEqual(Duration.subtract(Duration.nanos(30n), Duration.infinity), Duration.negativeInfinity)
382 deepStrictEqual(Duration.subtract(Duration.infinity, Duration.infinity), Duration.zero)
383
384 // negativeInfinity
385 deepStrictEqual(Duration.subtract(Duration.infinity, Duration.negativeInfinity), Duration.infinity)
386 deepStrictEqual(Duration.subtract(Duration.negativeInfinity, Duration.infinity), Duration.negativeInfinity)
387 deepStrictEqual(Duration.subtract(Duration.negativeInfinity, Duration.negativeInfinity), Duration.zero)
388 deepStrictEqual(Duration.subtract(Duration.negativeInfinity, Duration.seconds(5)), Duration.negativeInfinity)
389 deepStrictEqual(Duration.subtract(Duration.seconds(5), Duration.negativeInfinity), Duration.infinity)
390 })
391
392 it("isGreaterThan", () => {
393 assertTrue(pipe(Duration.seconds(30), Duration.isGreaterThan(Duration.seconds(20))))
394 assertFalse(pipe(Duration.seconds(30), Duration.isGreaterThan(Duration.seconds(30))))
395 assertFalse(pipe(Duration.seconds(30), Duration.isGreaterThan(Duration.seconds(60))))
396
397 assertTrue(pipe(Duration.nanos(30n), Duration.isGreaterThan(Duration.nanos(20n))))
398 assertFalse(pipe(Duration.nanos(30n), Duration.isGreaterThan(Duration.nanos(30n))))
399 assertFalse(pipe(Duration.nanos(30n), Duration.isGreaterThan(Duration.nanos(60n))))
400
401 assertTrue(pipe(Duration.millis(1), Duration.isGreaterThan(Duration.nanos(1n))))
402
403 assertTrue(pipe(Duration.infinity, Duration.isGreaterThan(Duration.seconds(20))))
404 assertFalse(pipe(Duration.seconds(-Infinity), Duration.isGreaterThan(Duration.infinity)))
405 assertFalse(pipe(Duration.nanos(1n), Duration.isGreaterThan(Duration.infinity)))
406 })
407
408 it("isGreaterThanOrEqualTo", () => {
409 assertTrue(pipe(Duration.seconds(30), Duration.isGreaterThanOrEqualTo(Duration.seconds(20))))
410 assertTrue(pipe(Duration.seconds(30), Duration.isGreaterThanOrEqualTo(Duration.seconds(30))))
411 assertFalse(pipe(Duration.seconds(30), Duration.isGreaterThanOrEqualTo(Duration.seconds(60))))
412
413 assertTrue(pipe(Duration.nanos(30n), Duration.isGreaterThanOrEqualTo(Duration.nanos(20n))))
414 assertTrue(pipe(Duration.nanos(30n), Duration.isGreaterThanOrEqualTo(Duration.nanos(30n))))
415 assertFalse(pipe(Duration.nanos(30n), Duration.isGreaterThanOrEqualTo(Duration.nanos(60n))))
416 })
417
418 it("isLessThan", () => {
419 assertTrue(pipe(Duration.seconds(20), Duration.isLessThan(Duration.seconds(30))))
420 assertFalse(pipe(Duration.seconds(30), Duration.isLessThan(Duration.seconds(30))))
421 assertFalse(pipe(Duration.seconds(60), Duration.isLessThan(Duration.seconds(30))))
422
423 assertTrue(pipe(Duration.nanos(20n), Duration.isLessThan(Duration.nanos(30n))))
424 assertFalse(pipe(Duration.nanos(30n), Duration.isLessThan(Duration.nanos(30n))))
425 assertFalse(pipe(Duration.nanos(60n), Duration.isLessThan(Duration.nanos(30n))))
426
427 assertTrue(pipe(Duration.nanos(1n), Duration.isLessThan(Duration.millis(1))))
428 })
429
430 it("isLessThanOrEqualTo", () => {
431 assertTrue(pipe(Duration.seconds(20), Duration.isLessThanOrEqualTo(Duration.seconds(30))))
432 assertTrue(pipe(Duration.seconds(30), Duration.isLessThanOrEqualTo(Duration.seconds(30))))
433 assertFalse(pipe(Duration.seconds(60), Duration.isLessThanOrEqualTo(Duration.seconds(30))))
434
435 assertTrue(pipe(Duration.nanos(20n), Duration.isLessThanOrEqualTo(Duration.nanos(30n))))
436 assertTrue(pipe(Duration.nanos(30n), Duration.isLessThanOrEqualTo(Duration.nanos(30n))))
437 assertFalse(pipe(Duration.nanos(60n), Duration.isLessThanOrEqualTo(Duration.nanos(30n))))
438 })
439
440 it("toString()", () => {
441 strictEqual(String(Duration.infinity), `Infinity`)
442 strictEqual(String(Duration.nanos(10n)), `10 nanos`)
443 strictEqual(String(Duration.millis(2)), `2 millis`)
444 strictEqual(String(Duration.millis(2.125)), `2125000 nanos`)
445 strictEqual(String(Duration.seconds(2)), `2000 millis`)
446 strictEqual(String(Duration.seconds(2.5)), `2500 millis`)
447 })
448
449 it("format", () => {
450 strictEqual(Duration.format(Duration.infinity), `Infinity`)
451 strictEqual(Duration.format(Duration.minutes(5)), `5m`)
452 strictEqual(Duration.format(Duration.minutes(5.325)), `5m 19s 500ms`)
453 strictEqual(Duration.format(Duration.hours(3)), `3h`)
454 strictEqual(Duration.format(Duration.hours(3.11125)), `3h 6m 40s 500ms`)
455 strictEqual(Duration.format(Duration.days(2)), `2d`)
456 strictEqual(Duration.format(Duration.days(2.25)), `2d 6h`)
457 strictEqual(Duration.format(Duration.weeks(1)), `7d`)
458 strictEqual(Duration.format(Duration.zero), `0`)
459 })
460
461 it("parts", () => {
462 deepStrictEqual(Duration.parts(Duration.infinity), {
463 days: Infinity,
464 hours: Infinity,
465 minutes: Infinity,
466 seconds: Infinity,
467 millis: Infinity,
468 nanos: Infinity
469 })
470
471 deepStrictEqual(Duration.parts(Duration.minutes(5.325)), {
472 days: 0,
473 hours: 0,
474 minutes: 5,
475 seconds: 19,
476 millis: 500,
477 nanos: 0
478 })
479
480 deepStrictEqual(Duration.parts(Duration.minutes(3.11125)), {
481 days: 0,
482 hours: 0,
483 minutes: 3,
484 seconds: 6,
485 millis: 675,
486 nanos: 0
487 })
488 })
489
490 it("toJSON", () => {
491 deepStrictEqual(Duration.seconds(2).toJSON(), { _id: "Duration", _tag: "Millis", millis: 2000 })
492 deepStrictEqual(Duration.nanos(5n).toJSON(), { _id: "Duration", _tag: "Nanos", nanos: "5" })
493 deepStrictEqual(Duration.millis(1.5).toJSON(), { _id: "Duration", _tag: "Nanos", nanos: "1500000" })
494 deepStrictEqual(Duration.infinity.toJSON(), { _id: "Duration", _tag: "Infinity" })
495 })
496
497 it(`inspect`, () => {
498 if (typeof window === "undefined") {
499 // oxlint-disable-next-line @typescript-eslint/no-require-imports
500 const { inspect } = require("node:util")
501 deepStrictEqual(inspect(Duration.millis(1000)), inspect({ _id: "Duration", _tag: "Millis", millis: 1000 }))
502 }
503 })
504
505 it(".pipe()", () => {
506 deepStrictEqual(Duration.seconds(1).pipe(Duration.sum(Duration.seconds(1))), Duration.seconds(2))
507 })
508
509 it("isDuration", () => {
510 assertTrue(Duration.isDuration(Duration.millis(100)))
511 assertFalse(Duration.isDuration(null))
512 })
513
514 it("zero", () => {
515 deepStrictEqual(Duration.sum(Duration.seconds(1), Duration.zero), Duration.seconds(1))
516 })
517
518 it("weeks", () => {
519 assertTrue(Equal.equals(Duration.weeks(1), Duration.days(7)))
520 assertFalse(Equal.equals(Duration.weeks(1), Duration.days(1)))
521 })
522
523 it("toMillis", () => {
524 strictEqual(Duration.millis(1).pipe(Duration.toMillis), 1)
525 strictEqual(Duration.nanos(1n).pipe(Duration.toMillis), 0.000001)
526 strictEqual(Duration.infinity.pipe(Duration.toMillis), Infinity)
527 })
528
529 it("toSeconds", () => {
530 strictEqual(Duration.millis(1).pipe(Duration.toSeconds), 0.001)
531 strictEqual(Duration.nanos(1n).pipe(Duration.toSeconds), 1e-9)
532 strictEqual(Duration.infinity.pipe(Duration.toSeconds), Infinity)
533 })
534
535 it("toNanos", () => {
536 assertSome(Duration.nanos(1n).pipe(Duration.toNanos), 1n)
537 assertNone(Duration.infinity.pipe(Duration.toNanos))
538 assertNone(Duration.negativeInfinity.pipe(Duration.toNanos))
539 assertSome(Duration.millis(1.0005).pipe(Duration.toNanos), 1_000_500n)
540 assertSome(Duration.millis(100).pipe(Duration.toNanos), 100_000_000n)
541 })
542
543 it("toNanosUnsafe", () => {
544 strictEqual(Duration.nanos(1n).pipe(Duration.toNanosUnsafe), 1n)
545 throws(() => Duration.infinity.pipe(Duration.toNanosUnsafe))
546 strictEqual(Duration.millis(1.0005).pipe(Duration.toNanosUnsafe), 1_000_500n)
547 strictEqual(Duration.millis(0.0000015).pipe(Duration.toNanosUnsafe), 2n)
548 strictEqual(Duration.millis(-0.0000015).pipe(Duration.toNanosUnsafe), -2n)
549 strictEqual(Duration.millis(100).pipe(Duration.toNanosUnsafe), 100_000_000n)
550 })
551
552 it("toHrTime", () => {
553 deepStrictEqual(Duration.millis(1).pipe(Duration.toHrTime), [0, 1_000_000])
554 deepStrictEqual(Duration.nanos(1n).pipe(Duration.toHrTime), [0, 1])
555 deepStrictEqual(Duration.nanos(1_000_000_001n).pipe(Duration.toHrTime), [1, 1])
556 deepStrictEqual(Duration.millis(1001).pipe(Duration.toHrTime), [1, 1_000_000])
557 deepStrictEqual(Duration.infinity.pipe(Duration.toHrTime), [Infinity, 0])
558 })
559
560 it("negative values", () => {
561 // negative constructors produce negative durations
562 assertTrue(Duration.isNegative(Duration.millis(-1)))
563 assertTrue(Duration.isNegative(Duration.nanos(-1n)))
564 strictEqual(Duration.toMillis(Duration.millis(-1)), -1)
565 strictEqual(Duration.toNanosUnsafe(Duration.nanos(-1n)), -1n)
566
567 // isNegative / isPositive
568 assertTrue(Duration.isNegative(Duration.seconds(-5)))
569 assertFalse(Duration.isNegative(Duration.zero))
570 assertFalse(Duration.isNegative(Duration.seconds(5)))
571 assertFalse(Duration.isNegative(Duration.infinity))
572 assertTrue(Duration.isNegative(Duration.negativeInfinity))
573
574 assertTrue(Duration.isPositive(Duration.seconds(5)))
575 assertFalse(Duration.isPositive(Duration.zero))
576 assertFalse(Duration.isPositive(Duration.seconds(-5)))
577 assertTrue(Duration.isPositive(Duration.infinity))
578 assertFalse(Duration.isPositive(Duration.negativeInfinity))
579
580 // abs
581 deepStrictEqual(Duration.abs(Duration.seconds(-5)), Duration.seconds(5))
582 deepStrictEqual(Duration.abs(Duration.seconds(5)), Duration.seconds(5))
583 deepStrictEqual(Duration.abs(Duration.zero), Duration.zero)
584 deepStrictEqual(Duration.abs(Duration.negativeInfinity), Duration.infinity)
585 deepStrictEqual(Duration.abs(Duration.infinity), Duration.infinity)
586
587 // negate
588 deepStrictEqual(Duration.negate(Duration.seconds(5)), Duration.seconds(-5))
589 deepStrictEqual(Duration.negate(Duration.seconds(-5)), Duration.seconds(5))
590 deepStrictEqual(Duration.negate(Duration.zero), Duration.zero)
591 deepStrictEqual(Duration.negate(Duration.infinity), Duration.negativeInfinity)
592 deepStrictEqual(Duration.negate(Duration.negativeInfinity), Duration.infinity)
593
594 // negativeInfinity
595 assertFalse(Duration.isFinite(Duration.negativeInfinity))
596 assertFalse(Duration.isZero(Duration.negativeInfinity))
597 strictEqual(Duration.toMillis(Duration.negativeInfinity), -Infinity)
598 strictEqual(Duration.toSeconds(Duration.negativeInfinity), -Infinity)
599 deepStrictEqual(Duration.toHrTime(Duration.negativeInfinity), [-Infinity, 0])
600
601 // format
602 strictEqual(Duration.format(Duration.seconds(-5)), "-5s")
603 strictEqual(Duration.format(Duration.negativeInfinity), "-Infinity")
604
605 // Order with negatives
606 deepStrictEqual(Duration.Order(Duration.negativeInfinity, Duration.negativeInfinity), 0)
607 deepStrictEqual(Duration.Order(Duration.negativeInfinity, Duration.seconds(-5)), -1)
608 deepStrictEqual(Duration.Order(Duration.seconds(-5), Duration.negativeInfinity), 1)
609 deepStrictEqual(Duration.Order(Duration.negativeInfinity, Duration.infinity), -1)
610 deepStrictEqual(Duration.Order(Duration.infinity, Duration.negativeInfinity), 1)
611 deepStrictEqual(Duration.Order(Duration.seconds(-5), Duration.seconds(-3)), -1)
612 deepStrictEqual(Duration.Order(Duration.seconds(-3), Duration.seconds(-5)), 1)
613
614 // Equivalence with negatives
615 assertTrue(Duration.Equivalence(Duration.negativeInfinity, Duration.negativeInfinity))
616 assertFalse(Duration.Equivalence(Duration.negativeInfinity, Duration.infinity))
617
618 // sum with negativeInfinity
619 deepStrictEqual(Duration.sum(Duration.infinity, Duration.negativeInfinity), Duration.zero)
620 deepStrictEqual(Duration.sum(Duration.negativeInfinity, Duration.infinity), Duration.zero)
621 deepStrictEqual(Duration.sum(Duration.negativeInfinity, Duration.negativeInfinity), Duration.negativeInfinity)
622 deepStrictEqual(Duration.sum(Duration.negativeInfinity, Duration.seconds(5)), Duration.negativeInfinity)
623
624 // times with negatives
625 deepStrictEqual(Duration.times(Duration.infinity, -1), Duration.negativeInfinity)
626 deepStrictEqual(Duration.times(Duration.negativeInfinity, -1), Duration.infinity)
627 deepStrictEqual(Duration.times(Duration.infinity, 0), Duration.zero)
628 deepStrictEqual(Duration.times(Duration.seconds(5), -2), Duration.seconds(-10))
629
630 // parts with negative
631 deepStrictEqual(Duration.parts(Duration.negativeInfinity), {
632 days: -Infinity,
633 hours: -Infinity,
634 minutes: -Infinity,
635 seconds: -Infinity,
636 millis: -Infinity,
637 nanos: -Infinity
638 })
639
640 // toString with negatives
641 strictEqual(String(Duration.negativeInfinity), "-Infinity")
642 strictEqual(String(Duration.millis(-5)), "-5 millis")
643 strictEqual(String(Duration.nanos(-10n)), "-10 nanos")
644
645 // toJSON with negatives
646 deepStrictEqual(Duration.negativeInfinity.toJSON(), { _id: "Duration", _tag: "NegativeInfinity" })
647 })
648
649 it("match", () => {
650 const match = Duration.match({
651 onMillis: (millis) => `millis: ${millis}`,
652 onNanos: (nanos) => `nanos: ${nanos}`,
653 onInfinity: () => "infinity"
654 })
655 strictEqual(match(Duration.millis(100)), "millis: 100")
656 strictEqual(match(Duration.nanos(10n)), "nanos: 10")
657 strictEqual(match(Duration.infinity), "infinity")
658 })
659
660 it("isFinite", () => {
661 assertTrue(Duration.isFinite(Duration.millis(100)))
662 assertTrue(Duration.isFinite(Duration.nanos(100n)))
663 assertFalse(Duration.isFinite(Duration.infinity))
664 })
665
666 it("isZero", () => {
667 assertTrue(Duration.isZero(Duration.zero))
668 assertTrue(Duration.isZero(Duration.millis(0)))
669 assertTrue(Duration.isZero(Duration.nanos(0n)))
670 assertFalse(Duration.isZero(Duration.infinity))
671 assertFalse(Duration.isZero(Duration.millis(1)))
672 assertFalse(Duration.isZero(Duration.nanos(1n)))
673 })
674
675 it("toMinutes", () => {
676 strictEqual(Duration.millis(60000).pipe(Duration.toMinutes), 1)
677 strictEqual(Duration.nanos(60000000000n).pipe(Duration.toMinutes), 1)
678 strictEqual(Duration.infinity.pipe(Duration.toMinutes), Infinity)
679 })
680
681 it("toHours", () => {
682 strictEqual(Duration.millis(3_600_000).pipe(Duration.toHours), 1)
683 strictEqual(Duration.nanos(3_600_000_000_000n).pipe(Duration.toHours), 1)
684 strictEqual(Duration.infinity.pipe(Duration.toHours), Infinity)
685 })
686
687 it("toDays", () => {
688 strictEqual(Duration.millis(86_400_000).pipe(Duration.toDays), 1)
689 strictEqual(Duration.nanos(86_400_000_000_000n).pipe(Duration.toDays), 1)
690 strictEqual(Duration.infinity.pipe(Duration.toDays), Infinity)
691 })
692
693 it("toWeeks", () => {
694 strictEqual(Duration.millis(604_800_000).pipe(Duration.toWeeks), 1)
695 strictEqual(Duration.nanos(604_800_000_000_000n).pipe(Duration.toWeeks), 1)
696 strictEqual(Duration.infinity.pipe(Duration.toWeeks), Infinity)
697 })
698
699 it("ReducerSum", () => {
700 deepStrictEqual(Duration.ReducerSum.combine(Duration.millis(1), Duration.millis(2)), Duration.millis(3))
701 })
702
703 it("CombinerMax", () => {
704 deepStrictEqual(Duration.CombinerMax.combine(Duration.millis(1), Duration.millis(2)), Duration.millis(2))
705 })
706
707 it("CombinerMin", () => {
708 deepStrictEqual(Duration.CombinerMin.combine(Duration.millis(1), Duration.millis(2)), Duration.millis(1))
709 })
710})