Простой javascript date math... на самом деле

Я пытаюсь создать простой script, который дает мне следующую дату утилизации, основанную на двухнедельном расписании, начиная с 6 июля 2011 года. Поэтому я создал эту простую функцию...

    function getNextDate(startDate) {
        if (today <= startDate) {
            return startDate;
        }
        // calculate the day since the start date.
        var totalDays = Math.ceil((today.getTime()-startDate.getTime())/(one_day));
        // check to see if this day falls on a recycle day 
        var bumpDays = totalDays%14;  // mod 14 -- pickup up every 14 days...
        // pickup is today
        if (bumpDays == 0) {
            return today;
        }
        // return the closest day which is in 14 days, less the # of days since the last
        // pick up..
        var ms =  today.getTime() + ((14- bumpDays) * one_day);
        return new Date(ms);
    }

и может вызвать его как...

 var today=new Date();
 var one_day=1000*60*60*24;  // one day in milliseconds
 var nextDate = getNextDate(new Date(2011,06,06));

пока так хорошо... но когда я проецирую "сегодня" на 10/27/2011, я получаю вторник 11/8/2011 в качестве следующей даты вместо среды 11/9/2011... На самом деле каждый через день до 10/26/2011 проект правильного пикапа... и каждую дату с 27.10.2011 по 28.02.2012 проекты во вторник, а не в среду. И тогда каждая дата с 29.02.2012 (високосный год) до 10/24/2012 (снова хммм октябрь) правильно прогнозирует среду. Что мне не хватает? Любая помощь будет принята с благодарностью.

В

Ответ 1

Самый простой способ сделать это - обновить объект Date, используя setDate. Поскольку комментарии к этому ответу указывают, что это официально не входит в спецификацию, но поддерживается всеми основными браузерами.

Вы должны НИКОГДА обновить другой объект Date, чем тот, на который вы выполнили первоначальный вызов getDate.

Пример реализации:

var incrementDate = function (date, amount) {
    var tmpDate = new Date(date);
    tmpDate.setDate(tmpDate.getDate() + amount)
    return tmpDate;
};

Если вы пытаетесь увеличить дату, используйте эту функцию. Он будет принимать как положительные, так и отрицательные значения. Он также гарантирует, что используемые объекты даты не будут изменены. Это должно предотвратить любую ошибку, которая может произойти, если вы не ожидаете, что обновление изменит значение объекта.


Неправильное использование:

var startDate = new Date('2013-11-01T11:00:00');
var a = new Date();
a.setDate(startDate.getDate() + 14)

Это обновит значение "date" для startDate с 14 днями в зависимости от значения a. Поскольку значение a не совпадает с ранее установленным startDate, возможно получить неправильное значение.

Ответ 2

Расширяясь по экселлианскому ответу, если вы хотите рассчитать любой период в будущем (в моем случае, для следующей даты оплаты), вы можете сделать простой цикл:

var today = new Date();
var basePayDate = new Date(2012, 9, 23, 0, 0, 0, 0);

while (basePayDate < today) {
    basePayDate.setDate(basePayDate.getDate()+14);
}

var nextPayDate = new Date(basePayDate.getTime());
basePayDate.setDate(nextPayDate.getDate()-14);

document.writeln("<p>Previous pay Date: " + basePayDate.toString());
document.writeln("<p>Current Date: " + today.toString());
document.writeln("<p>Next pay Date: " + nextPayDate.toString());

Это не приведет к возникновению нечетных проблем, если предположить, что службы базовой даты работают, как ожидалось. Должен признаться, я не проверял его на много лет в будущем...

Ответ 3

Примечание. У меня была аналогичная проблема; Я хотел создать массив дат еженедельно, т.е., Дату начала 10/23/2011 и перейти на 12 недель. Мой код был более или менее:

var myDate = new Date(Date.parse(document.eventForm.startDate.value));
var toDate = new Date(myDate);

var week = 60 * 60 * 24 * 7 * 1000;
var milliseconds = toDate.getTime();

dateArray[0] = myDate.format('m/d/Y');

for (var count = 1; count < numberOccurrences; count++) {
    milliseconds += week;
toDate.setTime(milliseconds);
    dateArray[count] = toDate.format('m/d/Y');
}

Поскольку я не указывал время, и я живу в США, мое время по умолчанию было полночь, поэтому, когда я пересек границу с летним временем, я переехал в предыдущий день. Тьфу. Я разрешил это, установив свое время дня до полудня, прежде чем я сделал расчет за неделю.