Skip to content

Commit 5d8916b

Browse files
authored
Fix inconsistent typing of duration properties (#1265)
When creating a Duration the seconds and nanoseconds will be converted to Integers, no matter if provided with Integers, Numbers, or BigInts. This is awkward and requires special handling by users
1 parent 1b448f5 commit 5d8916b

File tree

6 files changed

+65
-31
lines changed

6 files changed

+65
-31
lines changed

packages/bolt-connection/test/bolt/__snapshots__/bolt-protocol-v1.test.js.snap

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,8 @@ exports[`#unit BoltProtocolV1 .packable() should pack types introduced afterward
3333
{
3434
"days": 1,
3535
"months": 1,
36-
"nanoseconds": Integer {
37-
"high": 0,
38-
"low": 1,
39-
},
40-
"seconds": Integer {
41-
"high": 0,
42-
"low": 1,
43-
},
36+
"nanoseconds": 1,
37+
"seconds": 1,
4438
}
4539
`;
4640

packages/core/src/temporal-types.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import {
2323
assertValidDate
2424
} from './internal/util'
2525
import { newError } from './error'
26-
import Integer, { int, toNumber } from './integer'
26+
import Integer, { int, toNumber, isInt } from './integer'
2727

2828
const IDENTIFIER_PROPERTY_ATTRIBUTES = {
2929
value: true,
@@ -74,11 +74,23 @@ export class Duration<T extends NumberOrInteger = Integer> {
7474
* @type {NumberOrInteger}
7575
*/
7676
this.seconds = util.normalizeSecondsForDuration(seconds, nanoseconds) as T
77+
if (typeof seconds === 'number' && isInt(this.seconds)) {
78+
this.seconds = this.seconds.toNumber() as T
79+
}
80+
if (typeof seconds === 'bigint' && isInt(this.seconds)) {
81+
this.seconds = this.seconds.toBigInt() as T
82+
}
7783
/**
7884
* The number of nanoseconds.
7985
* @type {NumberOrInteger}
8086
*/
8187
this.nanoseconds = util.normalizeNanosecondsForDuration(nanoseconds) as T
88+
if (typeof nanoseconds === 'number' && isInt(this.nanoseconds)) {
89+
this.nanoseconds = this.nanoseconds.toNumber() as T
90+
}
91+
if (typeof nanoseconds === 'bigint' && isInt(this.nanoseconds)) {
92+
this.nanoseconds = this.nanoseconds.toBigInt() as T
93+
}
8294
Object.freeze(this)
8395
}
8496

packages/core/test/__snapshots__/json.test.ts.snap

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ exports[`json .stringify should handle DateTime in list 1`] = `"[{"year":2024,"m
1212

1313
exports[`json .stringify should handle DateTime in object 1`] = `"{"key":{"year":2024,"month":6,"day":13,"hour":10,"minute":0,"second":30,"nanosecond":134,"timeZoneOffsetSeconds":-3600,"timeZoneId":"Europe/Berlin"}}"`;
1414

15-
exports[`json .stringify should handle Duration 1`] = `"{"months":10,"days":2,"seconds":{"low":35,"high":0},"nanoseconds":{"low":100,"high":0}}"`;
15+
exports[`json .stringify should handle Duration 1`] = `"{"months":10,"days":2,"seconds":35,"nanoseconds":100}"`;
1616

17-
exports[`json .stringify should handle Duration in list 1`] = `"[{"months":10,"days":2,"seconds":{"low":35,"high":0},"nanoseconds":{"low":100,"high":0}}]"`;
17+
exports[`json .stringify should handle Duration in list 1`] = `"[{"months":10,"days":2,"seconds":35,"nanoseconds":100}]"`;
1818

19-
exports[`json .stringify should handle Duration in object 1`] = `"{"key":{"months":10,"days":2,"seconds":{"low":35,"high":0},"nanoseconds":{"low":100,"high":0}}}"`;
19+
exports[`json .stringify should handle Duration in object 1`] = `"{"key":{"months":10,"days":2,"seconds":35,"nanoseconds":100}}"`;
2020

2121
exports[`json .stringify should handle Integer 1`] = `"{"low":5,"high":0}"`;
2222

packages/core/test/temporal-types.test.ts

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import { LocalDateTime, Date, DateTime, Duration, isDuration, LocalTime, isLocalTime, Time, isTime, isDate, isLocalDateTime, isDateTime } from '../src/temporal-types'
1919
import { temporalUtil } from '../src/internal'
2020
import fc from 'fast-check'
21+
import { Integer } from '../src'
2122

2223
const MIN_UTC_IN_MS = -8_640_000_000_000_000
2324
const MAX_UTC_IN_MS = 8_640_000_000_000_000
@@ -184,23 +185,38 @@ describe('DateTime', () => {
184185
})
185186
})
186187

187-
describe('isDuration', () => {
188+
describe('Duration', () => {
189+
describe('isDuration', () => {
190+
it.each([
191+
[new Duration(1, 2, 3, 4), true],
192+
[null, false],
193+
[LocalDateTime.fromStandardDate(new global.Date()), false],
194+
[{ months: 1, days: 1, seconds: 2, nanoseconds: 2 }, false]
195+
])('should be a type guard [%o]', (obj: unknown, objIsDuration: boolean) => {
196+
expect(isDuration(obj)).toEqual(objIsDuration)
197+
198+
if (isDuration(obj)) {
199+
const duration: Duration = obj
200+
expect(duration).toEqual(obj)
201+
} else {
202+
// @ts-expect-error
203+
const duration: Duration = obj
204+
expect(duration).toEqual(obj)
205+
}
206+
})
207+
})
188208
it.each([
189-
[new Duration(1, 2, 3, 4), true],
190-
[null, false],
191-
[LocalDateTime.fromStandardDate(new global.Date()), false],
192-
[{ months: 1, days: 1, seconds: 2, nanoseconds: 2 }, false]
193-
])('should be a type guard [%o]', (obj: unknown, objIsDuration: boolean) => {
194-
expect(isDuration(obj)).toEqual(objIsDuration)
195-
196-
if (isDuration(obj)) {
197-
const duration: Duration = obj
198-
expect(duration).toEqual(obj)
199-
} else {
200-
// @ts-expect-error
201-
const duration: Duration = obj
202-
expect(duration).toEqual(obj)
203-
}
209+
[1, 2, 3, 4],
210+
[BigInt(1), BigInt(2), BigInt(3), BigInt(4)],
211+
[new Integer(1), new Integer(2), new Integer(3), new Integer(4)],
212+
[new Integer(1), 2, new Integer(3), BigInt(4)],
213+
[1, 2, BigInt(3), 4]
214+
])('should handle differing types for parameters', (months, days, seconds, nanos) => {
215+
const duration = new Duration(months, days, seconds, nanos)
216+
expect(duration.months).toEqual(months)
217+
expect(duration.days).toEqual(days)
218+
expect(duration.seconds).toEqual(seconds)
219+
expect(duration.nanoseconds).toEqual(nanos)
204220
})
205221
})
206222

packages/neo4j-driver-deno/lib/core/temporal-types.ts

Lines changed: 13 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/neo4j-driver/test/examples.test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1101,8 +1101,8 @@ describe('#integration examples', () => {
11011101
expect(neo4j.isDuration(durationField)).toEqual(true)
11021102
expect(durationField.months.toInt()).toEqual(duration.months)
11031103
expect(durationField.days.toInt()).toEqual(duration.days)
1104-
expect(durationField.seconds).toEqual(duration.seconds)
1105-
expect(durationField.nanoseconds).toEqual(duration.nanoseconds)
1104+
expect(durationField.seconds.toInt()).toEqual(duration.seconds)
1105+
expect(durationField.nanoseconds.toInt()).toEqual(duration.nanoseconds)
11061106
} finally {
11071107
await session.close()
11081108
}

0 commit comments

Comments
 (0)