Skip to content

Commit a9d7d03

Browse files
authored
fix: sub-second precisions need to be rounded at the seconds field to avoid adding floats (iamkun#2377)
1 parent 5f3f878 commit a9d7d03

File tree

2 files changed

+11
-1
lines changed

2 files changed

+11
-1
lines changed

src/plugin/duration/index.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,8 @@ class Duration {
139139

140140
let seconds = this.$d.seconds || 0
141141
if (this.$d.milliseconds) {
142-
seconds += Math.round(this.$d.milliseconds) / 1000
142+
seconds += this.$d.milliseconds / 1000
143+
seconds = Math.round(seconds * 1000) / 1000
143144
}
144145

145146
const S = getNumberUnitFormat(seconds, 'S')

test/plugin/duration.test.js

+9
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,15 @@ describe('Creating', () => {
7777
expect(dayjs.duration(1000.5).toISOString()).toBe('PT1.001S')
7878
expect(dayjs.duration(-1000.5).toISOString()).toBe('-PT1S')
7979
})
80+
it('should handle floating point rounding errors', () => {
81+
// An example of this is when adding 2 to 0.812 seconds, which is how
82+
// the seconds component is calculated in .toISOString().
83+
// > 2 + 0.812
84+
// 2.8120000000000003
85+
expect(dayjs.duration(-2812).toISOString()).toBe('-PT2.812S') // was -PT2.8120000000000003S
86+
expect(dayjs.duration(3121632.27382247).toISOString()).toBe('PT52M1.632S') // was PT52M1.6320000000000001S
87+
expect(dayjs.duration(7647826.525774224).toISOString()).toBe('PT2H7M27.827S') // was PT2H7M27.826999999999998S
88+
})
8089
})
8190

8291
describe('Parse ISO string', () => {

0 commit comments

Comments
 (0)