2011-06-15 1 views
14

Próbuję stworzyć prosty skrypt, który da mi kolejną datę recyklingu opartą na dwutygodniowym harmonogramie, który rozpocznie się 6 marca 2011 r. Stworzyłem tę prostą funkcję .. .Proste daty matematyczne javascript ... nie tak naprawdę

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); 
    } 

i można go nazwać jak ...

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

tej pory tak dobrze ... ale kiedy projekt "Today" do 10/27/2011, mam wtorek 11/8/2011 jako następna data zamiast ze środy 11/9/2011 ... W rzeczywistości każdego dnia do dnia 26 listopada 2011 r. Projektuje prawidłowy odbiór ... i każdą datę od 27.02.2011 do 2/28/2012 projekty wtorek, a nie środę. A następnie każda data od 2/29/2012 (rok przestępny) do 10/24/2012 (hmmm październik ponownie) prawidłowo wyświetla środę. czego mi brakuje? Każda pomoc będzie mile widziana ..

V

+1

Czy sufit nie powinien być podłogą? Ponieważ używasz 2011-06-06 1: 00u totalDays będzie 1, a następny odbiór będzie w 13 nie 14 dni, więc wtorek. – Gerben

+0

Wygląda dziwnie. Dostaję poprawną datę z 'one_day = 1000 * 60 * 60 * 24; dzisiaj = nowa data (2011,8,27); nextDate = getNextDate (nowa data (2011,6,6)); ', a nextDate to" śro 28 września 2011 00:00:00 GMT + ", co jest poprawne, prawda? Testowane na FF4. – Raze

+0

StartDate jest zawsze nowy Data (2011,06,06) - więc nie powinien się ruszać – user799301

Odpowiedz

34

Najłatwiej zrobić to zmiana obiektu Date użyciu setDate. Ponieważ komentarze do tej odpowiedzi wskazują, że nie jest to oficjalna część specyfikacji, jest ona obsługiwana we wszystkich głównych przeglądarkach.

Powinieneś NIGDY zaktualizować inny obiekt Date niż ten, z którym wykonano oryginalne połączenie getDate.

Przykładowa realizacja:

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

Jeśli starasz się zwiększyć datę, należy skorzystać z tej funkcji. Przyjmie zarówno wartości dodatnie, jak i ujemne. Gwarantuje również, że użyte obiekty daty nie zostaną zmienione. Powinno to zapobiec błędom, które mogą wystąpić, jeśli nie oczekujesz, że aktualizacja zmieni wartość obiektu.


Niewłaściwe użytkowanie:

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

To będzie zaktualizować wartość "Data" dla startDate z 14 dni na podstawie wartości a. Ponieważ wartość a nie jest taka sama jak poprzednio zdefiniowana startDate, możliwe jest uzyskanie niewłaściwej wartości.

+1

Nie jest łatwo znaleźć dokumentację, która gwarantuje, że to będzie pracować w ogólnym przypadku (dodając dowolną liczbę dni). – nobar

+7

To jest bardzo niebezpieczny proces myślowy. Wyobraź sobie, że "startDate" jest pierwszego dnia miesiąca, a dzisiaj jest 31-szy. Chcesz randkę 7 dni od startdate. a.setDate (startDate.getDate() - 7) byłoby wystarczające, prawda? Nie tak szybko. "a" ma teraz 7 dni przed początkiem * bieżącego * miesiąca, a nie 7 dni przed "startDate". Biorąc pod uwagę, gdzie strona pojawia się w wynikach Google, jest to absolutnie ważne, aby zrozumieć. W tej chwili poprawiam taki problem i mocno podejrzewam, że nasz kontrahent znalazł tę stronę i podążał tą dokładną logiką. – 10gistic

+0

Hmm, nigdy nie zamierzałem używać tego w sposób, który opisałeś. Tylko dla __updating__ wartość daty. Zmienię moją odpowiedź, aby odzwierciedlić problem. – Exelian

2

Uwaga: Miałem podobny problem; Chciałem stworzyć zestaw dat w bazie tygodniowej, tj., Data rozpoczęcia 10/23/2011 i przejść na 12 tygodni. Mój kod był bardziej lub mniej to:

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'); 
} 

Bo nie określił czasu, a ja mieszkam w USA, mój domyślny czas było o północy, więc kiedy przekroczył granicę czasu letniego, I przeniósł się do Poprzedni dzień. Fuj. Rozwiązałem to, ustawiając godzinę w południe przed obliczeniem tygodniowym.

4

Rozwijając na odpowiedź Exellian, o ile chcesz obliczyć dowolny okres w przyszłości (w moim przypadku, na następnej wypłacie), można zrobić prostą pętlę:

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()); 

To nie trafi dziwne problemy, zakładając, że usługi daty głównej działają zgodnie z oczekiwaniami. Muszę przyznać, że nie testowałem tego przez wiele lat w przyszłości ...