We are tracking down a bug in our application that seemingly is related to moment.js formatting.
Here's the problematic call (reproduced in Chrome, FF, and Edge, for reference):
moment('2016-03-13T23:59:59.999-06:00').format('YYYY-MM-DD')
What we expect:
2016-03-13
What we get:
2016-03-14
This seemingly has something to do with daylight savings time as this is the only date (so far) that we've been able to reproduce this incorrect behavior on and DST flipped on that day.
If we switch the UTC offset to -05:00
then it works properly.
Here's a simple JSBIN to demonstrate
What's going on here? How can we address this?
Moment will convert a date with an offset to the local time zone of the computer that you are on, if you use the default moment constructor function.
For this reason, your code is working as expected. The date is taken from -6 and converted to your local offset.
If you want to use the date in the timezone offset specified, use moment.parseZone:
moment.parseZone('2016-03-13T23:59:59.999-06:00').format()
"2016-03-13T23:59:59-06:00"
If you want to ignore the timezone offset, and work in local time, specify a format that does not include the offset. By doing this, you cause the offset to be ignored.
moment('2016-03-13T23:59:59.999-06:00', 'YYYY-MM-DDTHH:mm:ss.SSS').format()
"2016-03-13T23:59:59-05:00"
Note that I am in UTC-5 and the offset is displayed as -5 because I ignored the offset in the date.
The parsing guide may be of some help:
http://momentjs.com/guides/#/parsing/
In the momentjs documentation regarding parsing with time zones, they show that in order to take into account the specified time zone in the input string you should be using moment.parseZone()
.
console.log(moment.parseZone('2016-03-13T23:59:59.999-06:00').format('YYYY-MM-DD'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.12.0/moment.min.js"></script>
The above output "2016-03-13" on the console for me.
You are specifying a time zone on encoding (-6) yet are relying on the client time zone for formatting. The difference is the culprit.
Basically there's nothing wrong with the moment's format function.
console.log(moment.utc('2016-03-13T23:59:59.999-06:00').toString());
console.log(moment('2016-03-13T23:59:59.999-06:00').toString());
If you try to execute both of the above lines, you'll see that moment.utc()
basically takes off the offset and converts it to the UTC time note the time, not just the date and moment()
translates -06:00 offset to your local timezone and if you have smaller offset, you basically get the wrong date, because of the time.
Hope I helped.