Skip to content

Commit e3e0924

Browse files
authoredApr 11, 2024··
Add Duration.divide (#2494)
1 parent 232c353 commit e3e0924

File tree

4 files changed

+127
-0
lines changed

4 files changed

+127
-0
lines changed
 

‎.changeset/yellow-shirts-destroy.md

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
---
2+
"effect": patch
3+
---
4+
5+
Add `Duration.divide` and `Duration.unsafeDivide`.
6+
7+
```ts
8+
import { Duration, Option } from "effect"
9+
import assert from "assert"
10+
11+
assert.deepStrictEqual(Duration.divide("10 seconds", 2), Option.some(Duration.decode("5 seconds")))
12+
assert.deepStrictEqual(Duration.divide("10 seconds", 0), Option.none())
13+
assert.deepStrictEqual(Duration.divide("1 nano", 1.5), Option.none())
14+
15+
assert.deepStrictEqual(Duration.unsafeDivide("10 seconds", 2), Duration.decode("5 seconds"))
16+
assert.deepStrictEqual(Duration.unsafeDivide("10 seconds", 0), Duration.infinity)
17+
assert.throws(() => Duration.unsafeDivide("1 nano", 1.5))
18+
```

‎packages/effect/dtslint/Duration.ts

+14
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,20 @@ Duration.max("1 minutes", "2 millis")
110110
// $ExpectType Duration
111111
Duration.clamp("1 millis", { minimum: "2 millis", maximum: "3 millis" })
112112

113+
// -------------------------------------------------------------------------------------
114+
// divide
115+
// -------------------------------------------------------------------------------------
116+
117+
// $ExpectType Option<Duration>
118+
Duration.divide("1 seconds", 2)
119+
120+
// -------------------------------------------------------------------------------------
121+
// unsafeDivide
122+
// -------------------------------------------------------------------------------------
123+
124+
// $ExpectType Duration
125+
Duration.unsafeDivide("1 seconds", 2)
126+
113127
// -------------------------------------------------------------------------------------
114128
// times
115129
// -------------------------------------------------------------------------------------

‎packages/effect/src/Duration.ts

+53
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,59 @@ export const clamp: {
515515
})
516516
)
517517

518+
/**
519+
* @since 2.4.19
520+
* @category math
521+
*/
522+
export const divide: {
523+
(by: number): (self: DurationInput) => Option.Option<Duration>
524+
(self: DurationInput, by: number): Option.Option<Duration>
525+
} = dual(
526+
2,
527+
(self: DurationInput, by: number): Option.Option<Duration> =>
528+
match(self, {
529+
onMillis: (millis) => {
530+
if (by === 0 || isNaN(by) || !Number.isFinite(by)) {
531+
return Option.none()
532+
}
533+
return Option.some(make(millis / by))
534+
},
535+
onNanos: (nanos) => {
536+
if (isNaN(by) || by <= 0 || !Number.isFinite(by)) {
537+
return Option.none()
538+
}
539+
try {
540+
return Option.some(make(nanos / BigInt(by)))
541+
} catch (e) {
542+
return Option.none()
543+
}
544+
}
545+
})
546+
)
547+
548+
/**
549+
* @since 2.4.19
550+
* @category math
551+
*/
552+
export const unsafeDivide: {
553+
(by: number): (self: DurationInput) => Duration
554+
(self: DurationInput, by: number): Duration
555+
} = dual(
556+
2,
557+
(self: DurationInput, by: number): Duration =>
558+
match(self, {
559+
onMillis: (millis) => make(millis / by),
560+
onNanos: (nanos) => {
561+
if (isNaN(by) || by < 0 || Object.is(by, -0)) {
562+
return zero
563+
} else if (Object.is(by, 0) || !Number.isFinite(by)) {
564+
return infinity
565+
}
566+
return make(nanos / BigInt(by))
567+
}
568+
})
569+
)
570+
518571
/**
519572
* @since 2.0.0
520573
* @category math

‎packages/effect/test/Duration.test.ts

+42
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,48 @@ describe("Duration", () => {
162162
}))
163163
})
164164

165+
it("divide", () => {
166+
expect(Duration.divide(Duration.minutes(1), 2)).toEqual(Option.some(Duration.seconds(30)))
167+
expect(Duration.divide(Duration.seconds(1), 3)).toEqual(Option.some(Duration.nanos(333333333n)))
168+
expect(Duration.divide(Duration.nanos(2n), 2)).toEqual(Option.some(Duration.nanos(1n)))
169+
expect(Duration.divide(Duration.nanos(1n), 3)).toEqual(Option.some(Duration.zero))
170+
expect(Duration.divide(Duration.infinity, 2)).toEqual(Option.some(Duration.infinity))
171+
expect(Duration.divide(Duration.zero, 2)).toEqual(Option.some(Duration.zero))
172+
expect(Duration.divide(Duration.minutes(1), 0)).toEqual(Option.none())
173+
expect(Duration.divide(Duration.minutes(1), -0)).toEqual(Option.none())
174+
expect(Duration.divide(Duration.nanos(1n), 0)).toEqual(Option.none())
175+
expect(Duration.divide(Duration.nanos(1n), -0)).toEqual(Option.none())
176+
expect(Duration.divide(Duration.minutes(1), 0.5)).toEqual(Option.some(Duration.minutes(2)))
177+
expect(Duration.divide(Duration.minutes(1), 1.5)).toEqual(Option.some(Duration.seconds(40)))
178+
expect(Duration.divide(Duration.minutes(1), NaN)).toEqual(Option.none())
179+
expect(Duration.divide(Duration.nanos(1n), 0.5)).toEqual(Option.none())
180+
expect(Duration.divide(Duration.nanos(1n), 1.5)).toEqual(Option.none())
181+
expect(Duration.divide(Duration.nanos(1n), NaN)).toEqual(Option.none())
182+
183+
expect(Duration.divide("1 minute", 2)).toEqual(Option.some(Duration.seconds(30)))
184+
})
185+
186+
it("unsafeDivide", () => {
187+
expect(Duration.unsafeDivide(Duration.minutes(1), 2)).toEqual(Duration.seconds(30))
188+
expect(Duration.unsafeDivide(Duration.seconds(1), 3)).toEqual(Duration.nanos(333333333n))
189+
expect(Duration.unsafeDivide(Duration.nanos(2n), 2)).toEqual(Duration.nanos(1n))
190+
expect(Duration.unsafeDivide(Duration.nanos(1n), 3)).toEqual(Duration.zero)
191+
expect(Duration.unsafeDivide(Duration.infinity, 2)).toEqual(Duration.infinity)
192+
expect(Duration.unsafeDivide(Duration.zero, 2)).toEqual(Duration.zero)
193+
expect(Duration.unsafeDivide(Duration.minutes(1), 0)).toEqual(Duration.infinity)
194+
expect(Duration.unsafeDivide(Duration.minutes(1), -0)).toEqual(Duration.zero)
195+
expect(Duration.unsafeDivide(Duration.nanos(1n), 0)).toEqual(Duration.infinity)
196+
expect(Duration.unsafeDivide(Duration.nanos(1n), -0)).toEqual(Duration.zero)
197+
expect(Duration.unsafeDivide(Duration.minutes(1), 0.5)).toEqual(Duration.minutes(2))
198+
expect(Duration.unsafeDivide(Duration.minutes(1), 1.5)).toEqual(Duration.seconds(40))
199+
expect(Duration.unsafeDivide(Duration.minutes(1), NaN)).toEqual(Duration.zero)
200+
expect(() => Duration.unsafeDivide(Duration.nanos(1n), 0.5)).toThrow()
201+
expect(() => Duration.unsafeDivide(Duration.nanos(1n), 1.5)).toThrow()
202+
expect(Duration.unsafeDivide(Duration.nanos(1n), NaN)).toEqual(Duration.zero)
203+
204+
expect(Duration.unsafeDivide("1 minute", 2)).toEqual(Duration.seconds(30))
205+
})
206+
165207
it("times", () => {
166208
expect(Duration.times(Duration.seconds(1), 60)).toEqual(Duration.minutes(1))
167209
expect(Duration.times(Duration.nanos(2n), 10)).toEqual(Duration.nanos(20n))

0 commit comments

Comments
 (0)
Please sign in to comment.