Skip to content

Commit

Permalink
Add Duration.divide (#2494)
Browse files Browse the repository at this point in the history
  • Loading branch information
thewilkybarkid authored Apr 11, 2024
1 parent 232c353 commit e3e0924
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 0 deletions.
18 changes: 18 additions & 0 deletions .changeset/yellow-shirts-destroy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
"effect": patch
---

Add `Duration.divide` and `Duration.unsafeDivide`.

```ts
import { Duration, Option } from "effect"
import assert from "assert"

assert.deepStrictEqual(Duration.divide("10 seconds", 2), Option.some(Duration.decode("5 seconds")))
assert.deepStrictEqual(Duration.divide("10 seconds", 0), Option.none())
assert.deepStrictEqual(Duration.divide("1 nano", 1.5), Option.none())

assert.deepStrictEqual(Duration.unsafeDivide("10 seconds", 2), Duration.decode("5 seconds"))
assert.deepStrictEqual(Duration.unsafeDivide("10 seconds", 0), Duration.infinity)
assert.throws(() => Duration.unsafeDivide("1 nano", 1.5))
```
14 changes: 14 additions & 0 deletions packages/effect/dtslint/Duration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,20 @@ Duration.max("1 minutes", "2 millis")
// $ExpectType Duration
Duration.clamp("1 millis", { minimum: "2 millis", maximum: "3 millis" })

// -------------------------------------------------------------------------------------
// divide
// -------------------------------------------------------------------------------------

// $ExpectType Option<Duration>
Duration.divide("1 seconds", 2)

// -------------------------------------------------------------------------------------
// unsafeDivide
// -------------------------------------------------------------------------------------

// $ExpectType Duration
Duration.unsafeDivide("1 seconds", 2)

// -------------------------------------------------------------------------------------
// times
// -------------------------------------------------------------------------------------
Expand Down
53 changes: 53 additions & 0 deletions packages/effect/src/Duration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,59 @@ export const clamp: {
})
)

/**
* @since 2.4.19
* @category math
*/
export const divide: {
(by: number): (self: DurationInput) => Option.Option<Duration>
(self: DurationInput, by: number): Option.Option<Duration>
} = dual(
2,
(self: DurationInput, by: number): Option.Option<Duration> =>
match(self, {
onMillis: (millis) => {
if (by === 0 || isNaN(by) || !Number.isFinite(by)) {
return Option.none()
}
return Option.some(make(millis / by))
},
onNanos: (nanos) => {
if (isNaN(by) || by <= 0 || !Number.isFinite(by)) {
return Option.none()
}
try {
return Option.some(make(nanos / BigInt(by)))
} catch (e) {
return Option.none()
}
}
})
)

/**
* @since 2.4.19
* @category math
*/
export const unsafeDivide: {
(by: number): (self: DurationInput) => Duration
(self: DurationInput, by: number): Duration
} = dual(
2,
(self: DurationInput, by: number): Duration =>
match(self, {
onMillis: (millis) => make(millis / by),
onNanos: (nanos) => {
if (isNaN(by) || by < 0 || Object.is(by, -0)) {
return zero
} else if (Object.is(by, 0) || !Number.isFinite(by)) {
return infinity
}
return make(nanos / BigInt(by))
}
})
)

/**
* @since 2.0.0
* @category math
Expand Down
42 changes: 42 additions & 0 deletions packages/effect/test/Duration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,48 @@ describe("Duration", () => {
}))
})

it("divide", () => {
expect(Duration.divide(Duration.minutes(1), 2)).toEqual(Option.some(Duration.seconds(30)))
expect(Duration.divide(Duration.seconds(1), 3)).toEqual(Option.some(Duration.nanos(333333333n)))
expect(Duration.divide(Duration.nanos(2n), 2)).toEqual(Option.some(Duration.nanos(1n)))
expect(Duration.divide(Duration.nanos(1n), 3)).toEqual(Option.some(Duration.zero))
expect(Duration.divide(Duration.infinity, 2)).toEqual(Option.some(Duration.infinity))
expect(Duration.divide(Duration.zero, 2)).toEqual(Option.some(Duration.zero))
expect(Duration.divide(Duration.minutes(1), 0)).toEqual(Option.none())
expect(Duration.divide(Duration.minutes(1), -0)).toEqual(Option.none())
expect(Duration.divide(Duration.nanos(1n), 0)).toEqual(Option.none())
expect(Duration.divide(Duration.nanos(1n), -0)).toEqual(Option.none())
expect(Duration.divide(Duration.minutes(1), 0.5)).toEqual(Option.some(Duration.minutes(2)))
expect(Duration.divide(Duration.minutes(1), 1.5)).toEqual(Option.some(Duration.seconds(40)))
expect(Duration.divide(Duration.minutes(1), NaN)).toEqual(Option.none())
expect(Duration.divide(Duration.nanos(1n), 0.5)).toEqual(Option.none())
expect(Duration.divide(Duration.nanos(1n), 1.5)).toEqual(Option.none())
expect(Duration.divide(Duration.nanos(1n), NaN)).toEqual(Option.none())

expect(Duration.divide("1 minute", 2)).toEqual(Option.some(Duration.seconds(30)))
})

it("unsafeDivide", () => {
expect(Duration.unsafeDivide(Duration.minutes(1), 2)).toEqual(Duration.seconds(30))
expect(Duration.unsafeDivide(Duration.seconds(1), 3)).toEqual(Duration.nanos(333333333n))
expect(Duration.unsafeDivide(Duration.nanos(2n), 2)).toEqual(Duration.nanos(1n))
expect(Duration.unsafeDivide(Duration.nanos(1n), 3)).toEqual(Duration.zero)
expect(Duration.unsafeDivide(Duration.infinity, 2)).toEqual(Duration.infinity)
expect(Duration.unsafeDivide(Duration.zero, 2)).toEqual(Duration.zero)
expect(Duration.unsafeDivide(Duration.minutes(1), 0)).toEqual(Duration.infinity)
expect(Duration.unsafeDivide(Duration.minutes(1), -0)).toEqual(Duration.zero)
expect(Duration.unsafeDivide(Duration.nanos(1n), 0)).toEqual(Duration.infinity)
expect(Duration.unsafeDivide(Duration.nanos(1n), -0)).toEqual(Duration.zero)
expect(Duration.unsafeDivide(Duration.minutes(1), 0.5)).toEqual(Duration.minutes(2))
expect(Duration.unsafeDivide(Duration.minutes(1), 1.5)).toEqual(Duration.seconds(40))
expect(Duration.unsafeDivide(Duration.minutes(1), NaN)).toEqual(Duration.zero)
expect(() => Duration.unsafeDivide(Duration.nanos(1n), 0.5)).toThrow()
expect(() => Duration.unsafeDivide(Duration.nanos(1n), 1.5)).toThrow()
expect(Duration.unsafeDivide(Duration.nanos(1n), NaN)).toEqual(Duration.zero)

expect(Duration.unsafeDivide("1 minute", 2)).toEqual(Duration.seconds(30))
})

it("times", () => {
expect(Duration.times(Duration.seconds(1), 60)).toEqual(Duration.minutes(1))
expect(Duration.times(Duration.nanos(2n), 10)).toEqual(Duration.nanos(20n))
Expand Down

0 comments on commit e3e0924

Please sign in to comment.