Moment: Support for decimal milliseconds

Created on 22 Jun 2016  ·  3Comments  ·  Source: moment/moment

(ver 2.13.0)
The ISO standard allows for any number of decimal seconds before the 'Z' in a dateTime string. The .net platform seems to use 7 decimal places - while the moment.js library is only parsing out the first 3 decimal places.

I have monkey patched the formatter (toISOString()) to pull the full 7 digits from the creation object - but this is a terrible hack. Patching the parser would be much better - but is beyond my current understanding.

Perhaps there is another work-around?

Most helpful comment

Maggie,

Ah. I hadn't realised this was a limitation of Javascript.

I had found the option for formatting that you had mentioned - but

for me I really need those extra digits. Zeros are not good enough.

My 'monkey patch' looks at the creationData for the moment and

manually parses the milliseconds from the input string (if it is
available).

//Monkey patch the moment library to use 7 decimal places for seconds in it's standard ISO format - to match C# moment.fn._oldToISOString = moment.fn.toISOString; moment.fn.toISOString = function () { try { var originalDateSplit = moment(this).creationData().input.split("."); var milliseconds = originalDateSplit[originalDateSplit.length - 1]; if (milliseconds.indexOf(this.milliseconds()) === 0) { return moment(this).format('YYYY-MM-DD[T]HH:mm:ss.') + milliseconds + "Z"; } else { return moment(this)._oldToISOString(); } } catch (error) { return moment(this)._oldToISOString(); } }
It is not pretty - and will only work for moments that were
originally parsed out of an ISO date string. It will also be inconsistent
with the milliseconds() function. A better idea would be to intercept the
parsing process and pull any decimal seconds into a separate property on
the moment object - then we can return that as needed.

However - I do appreciate that we are moving beyond the scope of the

moment.js library at this point - it would no longer be a wrapper for a
Javascript Date object.

Perhaps we could make this limitation a little clear in the moment.js

documentation? Right now the millisecond truncation is implied from the
example code, but not explicitly described - and there is no explanation as
to why it behaves in this way.

Thank you for your help Maggie - it is much appreciated.

Regards,
Ben Hathaway
Software Developer
DATUM - Geotechnical and Structural Monitoring

All 3 comments

Because Moment.js is a wrapper for the Date object in JavaScript, we are limited to three decimal places (milliseconds). This is because that is all that the date object supports, so there is truly no way to store more. You shouldn't have to monkey patch anything to get seven decimal places to display or parse though. Just be aware that only the first three will actually be used.

moment('2016-01-01T05:21:22.1234567Z').format('YYYY-MM-DDTHH:mm:ss.SSSSSSS')
"2015-12-31T23:21:22.1230000"

Note that the output is zero filled, but there are seven digits both ways.

Maggie,

Ah. I hadn't realised this was a limitation of Javascript.

I had found the option for formatting that you had mentioned - but

for me I really need those extra digits. Zeros are not good enough.

My 'monkey patch' looks at the creationData for the moment and

manually parses the milliseconds from the input string (if it is
available).

//Monkey patch the moment library to use 7 decimal places for seconds in it's standard ISO format - to match C# moment.fn._oldToISOString = moment.fn.toISOString; moment.fn.toISOString = function () { try { var originalDateSplit = moment(this).creationData().input.split("."); var milliseconds = originalDateSplit[originalDateSplit.length - 1]; if (milliseconds.indexOf(this.milliseconds()) === 0) { return moment(this).format('YYYY-MM-DD[T]HH:mm:ss.') + milliseconds + "Z"; } else { return moment(this)._oldToISOString(); } } catch (error) { return moment(this)._oldToISOString(); } }
It is not pretty - and will only work for moments that were
originally parsed out of an ISO date string. It will also be inconsistent
with the milliseconds() function. A better idea would be to intercept the
parsing process and pull any decimal seconds into a separate property on
the moment object - then we can return that as needed.

However - I do appreciate that we are moving beyond the scope of the

moment.js library at this point - it would no longer be a wrapper for a
Javascript Date object.

Perhaps we could make this limitation a little clear in the moment.js

documentation? Right now the millisecond truncation is implied from the
example code, but not explicitly described - and there is no explanation as
to why it behaves in this way.

Thank you for your help Maggie - it is much appreciated.

Regards,
Ben Hathaway
Software Developer
DATUM - Geotechnical and Structural Monitoring

Hi @maggiepint,

I am looking for the same. After debugging through moment.js, I noticed it calls a zerofill function.

Since the resulting value is a string, I don't see why it zero fills it🤔🤔🤔
For example, I have this:

const value = 1596099230963;
const formatString = 'MM/DD/YYYY HH:mm:ss.SSSSSS';
const val = moment.utc(value).format(formatString);
console.log(val);

It prints 07/30/2020 08:53:50.963000 instead of 07/30/2020 08:53:50.963939

Further, I noticed older version of moment.js did not do this zero fill, for example ver 2.5.

I will have to write a custom formatter now to retain correct info in the date unless a change is done on moment.js. Any chance we can make this change?

Was this page helpful?
0 / 5 - 0 ratings