user1828605
user1828605

Reputation: 1735

Why moment.js producing Invalid Date for certain dates only?

Something strange with this function that I cannot figure out what's causing is. There are number of days that users can select from the dropdown. The days are : [3, 7, 14, 21, 28, 30, 60, 90, 180, 365]

So, when user selects 3, the moment.js converts it to appropriate ISO date. However, if the user selects 7, 14, or 21, it generates "Invalid Date" but it works for everything else. What's going on?

vm.getSelectedDate = function (days) {
            console.log(days);
            if (vm.selectedReminderDay) {

                vm.selectedReminderDate = new Date(vm.today);
                console.log(vm.selectedReminderDate);

                vm.selectedReminderDate.setDate(vm.today.getDate() + days);
                console.log(vm.selectedReminderDate);

                var m = moment(vm.selectedReminderDate, "MM/DD/YYYY h:mm:ss A");
                console.log(m);
                vm.utcReminderDate = m.toISOString();
                console.log(vm.utcReminderDate);
                return "in " + vm.selectedReminderDay + " days";
            }
            else {
                return "When?"
            }
        }

Upvotes: 1

Views: 699

Answers (2)

DonSteep
DonSteep

Reputation: 1075

The suggestions for better use of momentjs are valid in other answers.

The actual reason why 7, 14 and 21 seem to be the only numbers that misbehave is the format you're attempting to use for parsing. Moment appears to turn your Date object into a string for parsing and the "MM" part for months matches the day part in the converted string. Hence any date where the day of the month isn't in the range 1-12 fails to work. If you run the same code on another day you will find other magic numbers.

I don't quite track down how MM gets matched with the date part and it might be different in your locale than mine, but I believe it's the gist of it.

Upvotes: 0

SeinopSys
SeinopSys

Reputation: 8937

Date.getDate() gets the current day of the month, which will cause unexpected beahvior when it goes out of range (typically when it goes over ~30). What you could use is Date.getTime():

vm.selectedReminderDate.setTime(vm.today.getTime() + (days*24*60*60*1000));

The multiplication is simply to convert the days into milliseconds which setTime expects.


But a better way to do this would be to manipulate the date using momentjs alone, like this:

vm.getSelectedDate = function (days) {
    if (vm.selectedReminderDay) {
        var newdate = moment(vm.today).add(days, 'days');
        vm.utcReminderDate = newdate.toISOString();
        return "in " + vm.selectedReminderDay + " days";
    }
    else return "When?";
}

Upvotes: 2

Related Questions