2011-06-15 8 views
14

Estoy tratando de crear un script simple que me brinde la próxima fecha de reciclaje basada en un programa bisemanal que comienza el miércoles 6 de julio de 2011. Así que he creado esta sencilla función ... .Simple javascript date math ... not really

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

y puede llamar así ...

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

hasta ahora tan bueno ... pero cuando me proyecto "hoy" a 10/27/2011, consigo Martes 11/8/2011 como la próxima fecha en lugar de miércoles 09/11/2011 ... De hecho, todos los días a partir de ahora hasta el 26/10/2011 proyecta la recogida correcta ... y cada fecha desde el 10/27/2011 hasta el 2/28/2012 proyecta el martes y no el miércoles. Y luego, cada fecha a partir del 2/29/2012 (año bisiesto) hasta el 10/24/2012 (hmmm octubre otra vez) proyecta el miércoles correctamente. ¿Qué me estoy perdiendo? Cualquier ayuda sería muy apreciada ..

V

+1

¿No debería ceil be floor? Porque es el uso 2011-06-06 1: 00u totalDays será 1, y la próxima recolección será en 13 no 14 días, por lo que un martes. – Gerben

+0

Parece extraño. Estoy obteniendo la fecha correcta con 'one_day = 1000 * 60 * 60 * 24; hoy = nueva Fecha (2011,8,27); nextDate = getNextDate (new Date (2011,6,6)); ', y nextDate is' Wed Sep 28 2011 00:00:00 GMT + ', que es correcto ¿no? Probado en FF4. – Raze

+0

startDate siempre es nuevo Date (2011,06,06) - por lo que no debería moverse – user799301

Respuesta

34

La forma más sencilla de hacer esto es actualizar el objeto Date usando setDate. Como los comentarios de esta respuesta indican que esto no es oficialmente parte de la especificación, pero es compatible con todos los principales navegadores.

Usted debe NUNCA actualización de un objeto Date diferente a la que lo hizo el original getDate de llamadas.

aplicación de la muestra:

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

Si usted está tratando de incrementar una fecha, por favor utilice esta función. Aceptará valores positivos y negativos. También garantiza que los objetos de fecha utilizados no se cambien. Esto debería evitar cualquier error que pueda ocurrir si no espera que la actualización cambie el valor del objeto.


uso incorrecto:

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

Esto actualizará el valor "fecha" para startDate con 14 días basados ​​en el valor de a. Como el valor de a no es el mismo que el startDate previamente definido, es posible obtener un valor incorrecto.

+1

No es fácil encontrar documentación que garantice que esto trabajar en el caso general (agregando un número arbitrario de días). – nobar

+7

Este es un proceso de pensamiento muy peligroso. Imagine 'startDate' es el 1 ° del mes y hoy es el 31 °. Quieres una fecha de 7 días desde la fecha de inicio. a.setDate (startDate.getDate() - 7) sería suficiente, ¿verdad? No tan rapido. 'a' ahora es 7 días antes del comienzo del * mes * actual, no 7 días antes de 'fecha de inicio'. Teniendo en cuenta dónde esta página aparece en los resultados de Google, esto es absolutamente importante de entender. Estoy corrigiendo un problema así en este momento y sospecho fuertemente que nuestro contratista encontró esta página y siguió esa lógica exacta. – 10gistic

+0

Hmm, nunca quise que esto se use de la manera que usted describió. Solo para __updating__ un valor de fecha. Cambiaré mi respuesta para reflejar el problema. – Exelian

2

Nota: tuve un problema similar; Quería crear una matriz de fechas semanalmente, es decir, fecha de inicio 10/23/2011 y continuar durante 12 semanas. Mi código era más o menos la siguiente:

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

Debido a que no especificó el tiempo y vivo en los EE.UU., mi tiempo predeterminado era la medianoche, por lo que cuando crucé la frontera horario de verano, que se trasladó a la el día anterior. Yuck. Lo resolví estableciendo mi hora del día al mediodía antes de hacer el cálculo de mi semana.

4

Ampliando la respuesta de Exellian, si se desea calcular cualquier período en el futuro (en mi caso, para la próxima fecha de pago), se puede hacer un bucle simple:

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

Esto no golpeará problemas extraños, suponiendo que los servicios de fecha base funcionan como se esperaba. Debo admitir que no lo probé durante muchos años en el futuro ...