(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?
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?
Most helpful comment
Maggie,
for me I really need those extra digits. Zeros are not good enough.
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.
moment.js library at this point - it would no longer be a wrapper for a
Javascript Date object.
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.
Regards,
Ben Hathaway
Software Developer
DATUM - Geotechnical and Structural Monitoring