Skip to content

Commit

Permalink
fix handling of hrtime in Duration.decode
Browse files Browse the repository at this point in the history
  • Loading branch information
fubhy committed Jan 27, 2025
1 parent 502223a commit c70ade0
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 4 deletions.
5 changes: 5 additions & 0 deletions .changeset/good-pillows-leave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"effect": patch
---

Fixed handling of hrtime in `Duration.decode`
14 changes: 10 additions & 4 deletions packages/effect/src/Duration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ export type DurationInput =
| Duration
| number // millis
| bigint // nanos
| [seconds: number, nanos: number]
| readonly [seconds: number, nanos: number]
| `${number} ${Unit}`

const DURATION_REGEX = /^(-?\d+(?:\.\d+)?)\s+(nanos?|micros?|millis?|seconds?|minutes?|hours?|days?|weeks?)$/
Expand All @@ -98,10 +98,16 @@ export const decode = (input: DurationInput): Duration => {
return millis(input)
} else if (isBigInt(input)) {
return nanos(input)
} else if (Array.isArray(input)) {
if (input.length === 2 && isNumber(input[0]) && isNumber(input[1])) {
return nanos(BigInt(input[0]) * bigint1e9 + BigInt(input[1]))
} else if (Array.isArray(input) && input.length === 2 && input.every(isNumber)) {
if (input[0] === -Infinity || input[1] === -Infinity || Number.isNaN(input[0]) || Number.isNaN(input[1])) {
return zero
}

if (input[0] === Infinity || input[1] === Infinity) {
return infinity
}

return nanos(BigInt(Math.round(input[0]) * 1_000_000_000) + BigInt(Math.round(input[1])))
} else if (isString(input)) {
DURATION_REGEX.lastIndex = 0 // Reset the lastIndex before each use
const match = DURATION_REGEX.exec(input)
Expand Down
4 changes: 4 additions & 0 deletions packages/effect/test/Duration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ describe("Duration", () => {

expect(Duration.decode([500, 123456789])).toEqual(Duration.nanos(500123456789n))
expect(Duration.decode([-500, 123456789])).toEqual(Duration.zero)
expect(Duration.decode([Infinity, 0])).toEqual(Duration.infinity)
expect(Duration.decode([-Infinity, 0])).toEqual(Duration.zero)

expect(() => Duration.decode("1.5 secs" as any)).toThrowError(new Error("Invalid DurationInput"))
expect(() => Duration.decode(true as any)).toThrowError(new Error("Invalid DurationInput"))
Expand Down Expand Up @@ -72,6 +74,8 @@ describe("Duration", () => {

expect(Duration.decodeUnknown([500, 123456789])).toEqual(Option.some(Duration.nanos(500123456789n)))
expect(Duration.decodeUnknown([-500, 123456789])).toEqual(Option.some(Duration.zero))
expect(Duration.decodeUnknown([Infinity, 0])).toEqual(Option.some(Duration.infinity))
expect(Duration.decodeUnknown([-Infinity, 0])).toEqual(Option.some(Duration.zero))

expect(Duration.decodeUnknown("1.5 secs")).toEqual(Option.none())
expect(Duration.decodeUnknown(true)).toEqual(Option.none())
Expand Down

0 comments on commit c70ade0

Please sign in to comment.