Javascript date calculation returns incorrect values

boloneysandwich

I have a javascript date calculator that sometimes works and sometimes does not. I have read through How do I get the number of days between two dates in JavaScript? but I am not sure where to implement any of the suggestions as it seems to me the dates on this post are predetermined inside the code instead of through the inputs.

For example, if you input the date of October 1, 2019, you will get the results of:

45 days: Thursday, November 14, 2019

180 days: Sunday, March 29, 2020

But, if you input the date of December 1, 2019, you will get the results of:

45 days: Wednesday, January 15, 2020

180 days: Friday, May 29, 2020

This can not be correct because there are 31 days in December. 31 + 15 = 46? Some sort of miscalculation happens in most months.

(function ($) {
    var weekdays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
    var months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];

    var afterTime = function (time, days) {
        time = time + (24 * 60 * 60 * 1000) * days;
        return time;
    };

    var getDate = function () {
        var yy = $('input#year').val();
        var mm = $('select#month').val();
        var dd = $('input#day').val();
        var wd;

        if (yy.trim().length === 0 || mm.trim().length === 0 || dd.trim().length === 0) {
            return;
        }

        var startDate = new Date(yy, mm, dd);
        var resultDate;

        resultDate = new Date();
        resultDate.setTime(afterTime(startDate.getTime(), 45));
        yy = resultDate.getFullYear();
        mm = resultDate.getMonth();
        dd = resultDate.getDate();
        wd = resultDate.getDay();
        $('#dateAfter45').html('<span>Your 45 Days from now ends on:</span> ' + weekdays[wd] + ', ' + months[mm] + ' ' + dd + ', ' + yy);

        resultDate = new Date();
        resultDate.setTime(afterTime(startDate.getTime(), 180));
        yy = resultDate.getFullYear();
        mm = resultDate.getMonth();
        dd = resultDate.getDate();
        wd = resultDate.getDay();
        $('#dateAfter180').html('<span>Your 180 Days from now ends on:</span> ' + weekdays[wd] + ', ' + months[mm] + ' ' + dd + ', ' + yy);
    };

    $(document).ready(function () {
        $('input#year').change(function () {
            getDate();
        });
        $('input#day').change(function () {
            getDate();
        });
        $('select#month').change(function () {
            getDate();
        });
    });

})(jQuery);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="dateselector">
            <div class="start-date">
                <form class="form">
                    <div class="form-row align-items-center">
                        <div class="col-auto">
                            <!--label for="month">Month</label-->
                            <select name="month" id="month" class="form-control">
                                <option value="" disabled selected>- Select a Month -</option>
                                <option value="0">January</option>
                                <option value="1">February</option>
                                <option value="2">March</option>
                                <option value="3">April</option>
                                <option value="4">May</option>
                                <option value="5">June</option>
                                <option value="6">July</option>
                                <option value="7">August</option>
                                <option value="8">September</option>
                                <option value="9">October</option>
                                <option value="10">November</option>
                                <option value="11">December</option>
                            </select>
                        </div>
                        <div class="col-auto">
                            <!--label for="day">Day</label-->
                            <input type="text" name="day" id="day" class="form-control" placeholder="Day" maxlength="2">
                        </div>
                        <div class="col-auto">
                            <!--label for="day">Year</label-->
                            <input type="text" name="year" id="year" class="form-control" placeholder="Year" maxlength="4">
                        </div>
                        <div class="col-auto">
                            <!--label for="day">Year</label-->
                            <span class="butn hvr-sweep-to-top">Calculate</span>
                        </div>
                    </div>
                </form>
            </div>
            <div class="result-date">
                <h4 id="dateAfter45"></h4>
                <h4 id="dateAfter180"></h4>
            </div>
        </div>

Barmar

45 is 31 + 14. 31 days after December 1 is January 1, 14 days after January 1 is January 15.

The result is correct. Date arithmetic that crosses month boundaries is off by 1 because there's no day 0 in months.

The reason you're getting November 14 in the first case is because daylight savings time changes sometime in October. Your afterTime() function treats all days as 24 hours long, but when DST ends we add an extra hour to that day. So you're going from Oct 1 00:00:00 to Nov 14 23:00:00 instead of Nov 15 00:00:00.

Use the built-in date arithmetic in the Date class, it automatically adjusts for this.

resultDate.setTime(afterTime(startDate.getTime(), 45));

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related