iamkun / dayjs

⏰ Day.js 2kB immutable date-time library alternative to Moment.js with the same modern API
https://day.js.org
MIT License
46.89k stars 2.3k forks source link

format() broken for duration objects (undefined values, wrong format, inconsistent behaviour) #1757

Open adroste opened 2 years ago

adroste commented 2 years ago

Describe the bug Every duration instance I create whether from ISO-string or from object appears to be broken. The behaviour is also inconsistent between construction from ISO-string or object.

Case 1 (init leaves undefined values, inconsistent):

dayjs.duration({ seconds: 20 }).format('HH:mm:ss:SSS');
// received: undefined:undefined:20:undefined
// wanted: 00:00:20:000

and weirdly:

dayjs.duration('PT20S').format('HH:mm:ss:SSS');
// received: 00:00:20:undefined
// wanted: 00:00:20:000

Case 2 (milliseconds parsing from ISO string):

dayjs.duration({ hours: 1, minutes: 2, seconds: 3, milliseconds: 4 }).format('HH:mm:ss:SSS');
// received: 01:02:03:004
// wanted: 01:02:03:004

but from ISO string, parsing is completely broken:

duration = dayjs.duration('PT1H2M3.004S').format('HH:mm:ss:SSS');
// received: 01:02:3.004:undefined
// wanted: 01:02:03:004

Case 3 (overflows not calculated on creation):

dayjs.duration({ seconds: 180 }).format('mm:ss');
// received: undefined:180
// wanted: 03:00

Case 4 (overflow calculation ignores format options)

dayjs.duration({ hours: 23, minutes: 30 }).add(3, 'h').format('HH:mm');
// received: 02:30
// wanted: 26:30

Workaround

Cases 1,2,3 can be worked around by adding nothing (.add(0,'s')), like:

// for case 1
dayjs.duration({ seconds: 20 }).add(0,'s').format('HH:mm:ss:SSS');
// received: 00:00:20:000

// for case 2
dayjs.duration('PT1H2M3.004S').add(0,'s').format('HH:mm:ss:SSS');
// received: 01:02:03:004

// for case 3
dayjs.duration({ seconds: 180 }).add(0,'s').format('mm:ss');
// received: 03:00

@iamkun Feels like you forgot to call an init function inside the constructor.

Information

derouck commented 2 years ago

format seems to be broken entirely for me as well, only weird results coming out of it so far...

stuartm commented 2 years ago

I'm going to add another failure case:

SSS is supposed to give milliseconds to 3 digits according to the documentation but if a fractional value is given to duration() then SSS also gives fractions in the output.

daysjs.duration(16030.000000000002).format('HH:mm:ss.SSS');
// outputs 00:00:16.30.00000000000182
IgnisDa commented 10 months ago

Just to add a note, dayjsLib.duration({ seconds }).format(format) does not work, but dayjsLib.duration(seconds * 1000).format(format) does.