viernes, 22 de junio de 2012

Como calcular los días entre dos fechas con Javascript teniendo en cuenta años bisiestos

Hace unos días tuvimos que hacer en una aplicación una resta entre dos fechas y mostrar el número de días entre ellas en pantalla. Por lo que nos pusimos a hacerlo en JavaScript. Coger los días, los restas, te sale un tiempo en milisegundos y listo. Algo como lo que sigue:



function mostrarDias(){ var fechaInicio = document.getElementById("fechaInicio").value; var fechaFin = document.getElementById("fechaFin").value; if (fechaInicio.length != 10 || fechaFin.length != 10){ document.getElementById("diasDisfrutados").value = 0; } else{ var diaInicio=fechaInicio.substring(0,2); var mesInicio=fechaInicio.substring(3,5); var anoInicio=fechaInicio.substring(6,10); var diaFin=fechaFin.substring(0,2); var mesFin=fechaFin.substring(3,5); var anoFin=fechaFin.substring(6,10); var f1 = new Date(anoInicio,mesInicio,diaInicio); var f2 = new Date(anoFin,mesFin,diaFin); var difDias = Math.floor((f2.getTime()-f1.getTime()) / (1000 * 60 * 60 * 24))+1; document.getElementById("diasDisfrutados").firstChild.nodeValue = difDias; document.getElementById("diasDisfrutados2").value = difDias; } }

Pero esto no funciona ya que JavaScript se pasa por el forro los meses de 31 días y los años bisiestos. Así que tuve que hacer mi propio cálculo de días cuando se buscaban fechas entre distintos años o meses, teniendo también en cuenta que no se seleccione una fecha de fin menor que la fecha de inicio.

function mostrarDias(){ var fechaInicio = document.getElementById("fechaInicio").value; var fechaFin = document.getElementById("fechaFin").value; if (fechaInicio.length != 10 || fechaFin.length != 10){ document.getElementById("diasDisfrutados").value = 0; } else{ //Separamos las fechas en dias, meses y años var diaInicio=fechaInicio.substring(0,2); var mesInicio=fechaInicio.substring(3,5); var anoInicio=fechaInicio.substring(6,10); var diaFin=fechaFin.substring(0,2); var mesFin=fechaFin.substring(3,5); var anoFin=fechaFin.substring(6,10); //Los meses empiezan en 0 por lo que le restamos 1 mesFin = mesFin -1; mesInicio = mesInicio -1; //Creamos una fecha con los valores que hemos sacado var fInicio = new Date(anoInicio,mesInicio,diaInicio); var fFin = new Date(anoFin,mesFin,diaFin); diasTotal = 0; if(fFin>fInicio){ //Para sumarle 365 días tienen que haber 2 años de diferencia //Si no solamente sumo los días entre meses anoInicio++; while(anoFin>anoInicio){ alert("Entro aquí si hay dos años de diferencia"); if(esBisiesto(anoFin)) { dias_e_anio=366; } else { dias_e_anio=365; } diasTotal = diasTotal + dias_e_anio; anoFin--; } //Para sumarle los días de un mes completo, tengo que ver que haya diferencia de 2 meses mesInicio++; while(mesFin>mesInicio){ dias_e_mes = getDays(mesFin-1,anoFin); diasTotal = diasTotal + dias_e_mes; mesFin--; } //Solamente falta sumar los días mesInicio--; if(mesInicio==mesFin){ diasTotal=diaFin-diaInicio+1; } else{ //Saco los días desde el mesInicio hasta fin de mes dias_e_mes=getDays(mesInicio,anoInicio); diasTotal = diasTotal + (dias_e_mes-diaInicio) +1; //ahora saco los días desde el principio de mesFin hasta el día diasTotal = diasTotal + parseInt(diaFin); } } //Si la fechaFin es mayor else if (fechaFin<fechaInicio){ alert("La fecha de fin no puede ser mayor que la fecha de inicio"); diasTotal=0; } //Si las fechas son iguales else{ diasTotal = 1; } } } function esBisiesto(ano) { if (ano % 4 == 0) return true /* else */ return false } function getDays(month, year) { var ar = new Array(12) ar[0] = 31 // Enero if(esBisiesto) { ar[1]=29 } else { ar[1]=28 } ar[2] = 31 // Marzo ar[3] = 30 // Abril ar[4] = 31 // Mayo ar[5] = 30 // Junio ar[6] = 31 // Julio ar[7] = 31 // Agosto ar[8] = 30 // Septiembre ar[9] = 31 // Octubre ar[10] = 30 // Noviembre ar[11] = 31 // Diciembre return ar[month]; }
No es muy muy elegante pero funciona que es lo importante ;-)

7 comentarios :

  1. me temo que no funciona, no se si intensionalmente la publicaste con errores.

    ResponderEliminar
    Respuestas
    1. Qué es lo que no te funciona?? Por qué iba a publicarlo con errores??

      Eliminar
  2. probando tu codigo me percate que funciona pero unicamente toma como referencia los meses y dias, ya que si pongo 13/05/2013 a 13/05/204 el resultado es 1 dia.

    Saludos y ojala nos compartas el codigo bueno

    ResponderEliminar
  3. esta bueno el codigo, me sirve para lo que necesito gracias :)

    ResponderEliminar
  4. UNA PORQUERIA DE CODIGO. No funciona, hay errores por todos lados...

    ResponderEliminar
  5. El problema por el que no va la primera funcion creo que esta en la hora que se cambia en verano. En milisegundos son 3.600.000. Mira si puede ser eso.

    ResponderEliminar
  6. Gracias amigo a mi me sirvió lo hice unos cambios y agregados pero la logica coincide lo que quiero Saludos y sigue aportando

    ResponderEliminar