sumar - obtener fecha y hora actual javascript
Diferencia de fecha en Javascript(ignorando la hora del día) (15)
Estoy escribiendo una aplicación de alquiler de equipos donde los clientes pagan una tarifa por el alquiler de equipos en función de la duración (en días) del alquiler. Entonces, básicamente, (tarifa diaria * cantidad de días) = carga total.
Para una respuesta instantánea en el lado del cliente, estoy tratando de usar Javascript para descubrir la diferencia en dos fechas del calendario. He buscado, pero nada de lo que he encontrado es exactamente lo que estoy buscando. La mayoría de las soluciones que he visto son de la forma:
function dateDiff1(startDate, endDate) {
return ((endDate.getTime() - startDate.getTime()) / 1000*60*60*24);
}
Mi problema es que el equipo se puede sacar y devolver en cualquier momento del día durante esas dos fechas sin cargo adicional. El código anterior está calculando el número de períodos de 24 horas entre las dos fechas, cuando estoy realmente interesado en el número de días calendario.
Por ejemplo, si alguien revisó el equipo a las 6 a. M. El 6 de julio y lo devolvió a las 10 p. M. El 7 de julio, el código anterior calculó que había pasado más de un período de 24 horas y devolvería 2. El resultado deseado es 1, ya que una fecha del calendario ha transcurrido (es decir, del 6 al 7).
La solución más cercana que he encontrado es esta función:
function dateDiff2(startDate, endDate) {
return endDate.getDate() - startDate.getDate();
}
que hace exactamente lo que quiero, siempre y cuando las dos fechas estén dentro del mismo mes. Sin embargo, dado que getDate () solo devuelve el día del mes (es decir, 1-31), no funciona cuando las fechas abarcan varios meses (por ejemplo, el 31 de julio al 1 de agosto es de 1 día, pero el anterior calcule de 1 a 31, o -29).
En el backend, en PHP, estoy usando gregoriantojd (), que parece funcionar bien (mira esta publicación para ver un ejemplo). Simplemente no puedo encontrar una solución equivalente en Javascript.
¿Alguien tiene alguna idea?
¡Hay un error en las soluciones dadas!
Esto se aplica a las diferencias de fecha en las que no se tiene en cuenta el tiempo Y desea un resultado entero, es decir, un número entero de días.
En muchos de los ejemplos anteriores, vemos en Math.floor otras instancias que he visto en Math.ceil en otros lugares también. Estos se realizan para redondear el resultado a un número entero de días. El problema es que el horario de verano dará un resultado incorrecto en el otoño con Math.ceil: el resultado será un día demasiado grande o en la primavera si usa Math.floor se perderá un día demasiado. Solo usa Math.round porque 1 hora de cualquier manera no va a sesgar el resultado.
function dateDiff(dateEarlier, dateLater) {
var one_day=1000*60*60*24
return ( Math.round((dateLater.getTime()-dateEarlier.getTime())/one_day) );
}
+ arriba del ejemplo anterior que usa los constructores UTC. Sin hacer eso, serás abatido por Horario de verano / Horario de verano.
Si tomas las diferencias en algunos de ellos, podría terminar una hora corta al cruzar la línea DST para tu zona horaria en una dirección (Spring-forward, es decir, en Feb preguntando por abril, por ejemplo). Cuando piso N + 23/24, terminará con N.
La otra dirección (en octubre para diciembre) debería estar bien, terminarás una hora más adelante de lo que el piso () se ocupará correctamente.
Acabo de tener este problema y lo resolví después de encontrar esta pregunta, así que volví a publicar esto. Esto obtendrá el total de días independientemente del tiempo. Y DST no lo estropea:
date1 = Date.UTC(date1.getFullYear(), date1.getMonth(), date1.getDate());
date2 = Date.UTC(date2.getFullYear(), date2.getMonth(), date2.getDate());
var ms = Math.abs(date1-date2);
return Math.floor(ms/1000/60/60/24); //floor should be unnecessary, but just in case
El truco está en convertir a una fecha UTC que ni siquiera conoce los tiempos de las fechas originales.
Como el día juliano es efectivamente el número de días (y en algunos casos también la fracción de días) desde una fecha determinada, es prácticamente el mismo que el de UNIX, que se presenta de forma diferente. Puede obtener la cantidad de días enteros desde 1970 de la siguiente manera:
Date.prototype.getWholeDays = function () {
return Math.floor(new Date() / 1000*60*60*24);
};
function dateDiff(startDate, endDate) {
return endDate.getWholeDays() - startDate.getWholeDays();
}
Lo que haría es establecer los tiempos de las dos fechas al mismo tiempo. Por ejemplo, configure la hora de endDate a las 12:00 a.m. y comience la hora de la tarde a las 12:00 a.m. también. Entonces haz la diferencia entre ellos.
En una nota lateral, dado que yo también estoy en la industria de software de equipos de alquiler, parece que está perdiendo ingresos por alquileres al no contar las horas. Según su ejemplo, si alguien recogió el equipo el 6 de julio a las 6 a.m. y lo devolvió el 7 de julio a las 10 p.m. Tenían dos días completos para usar el equipo y posiblemente también incurran en una carga excesiva del medidor ...
Necesita date.js, http://code.google.com/p/datejs/
function CalculateDuration (startDate, endDate) {
var sdt = Date.parse(startDate);
var edt = Date.parse(endDate);
var sdtYear = sdt.getYear();
var edtYear = edt.getYear();
var sdtMonth = sdt.getMonth();
var edtMonth = edt.getMonth();
var sdtDay = sdt.getDate();
var edtDay = edt.getDate();
var StartDateMonthDays = Date.getDaysInMonth(sdtYear, sdtMonth);
var EndDateMonthDays = Date.getDaysInMonth(edtYear, edtMonth);
if (edtMonth < sdtMonth) { //Means the ending month is earlier, which invalidates the operation
alert("Ending month cannot be earlier than the starting month")
}
//Months are equal, if month is the next month of the start date month,
//the operation fails, thus we need to calculate month difference first
else if (edtMonth > sdtMonth) {
//Need to count how many days are left to finish the month
var daysToMonthFinish = StartDateMonthDays - sdtDay;
var calculatedDuration = daysToMonthFinish + edtDay;
$("#hdn_duration").val(calculatedDuration);
}
//If months are the same, it is safe to just calculate the end day minus the start day
else {
var calcDuration = edtDay - sdtDay;
$("#hdn_duration").val(calcDuration);
}
Para obtener los días completos el intervalo de fecha sobre el horario de verano cambia el piso (días) debe ser reemplazado por ronda. De lo contrario, es una función muy útil.
Puede ajustar la fecha de inicio a la medianoche del mismo día y luego calcular el número de períodos de 24 horas entre las fechas. Luego, tomaría el techo o el piso de ese número dependiendo de si desea contar cualquier parte de un día como un día completo o no.
function dateDiff(startDate, endDate) {
// set startDate to the beginning of the day
startDate = new Date(
startDate.getFullYear(),
startDate.getMonth(),
startDate.getDate());
return Math.floor((endDate - startDate) / 1000*60*60*24);
}
Sé que esta es una solución parcial, pero es posible que pueda obtener los días entre las fechas (siempre que las fechas no tengan tiempo establecido). Entonces puedes trabajar desde allí.
Estoy basando esta solución en el problema que presentó ((tarifa diaria * número de días) = cargo total); no es la pregunta de diferencia de fecha real. Esto debería ayudarte.
var Main = function() {
var startDate = new Date(''08/20/2014'');
var endDate = new Date(''08/22/2014'');
var totalCharge = monthlyFee * daysBetween(startDate, endDate);
}
var daysBetween = function(startDate, endDate) {
return Math.round(Math.abs((startDate.getTime() - endDate.getTime())/(24*60*60*1000)));
};
Si quieres días enteros para el ejemplo de alquiler de tu cámara de estudiante ...
function daysBetween(first, second) {
// Copy date parts of the timestamps, discarding the time parts.
var one = new Date(first.getFullYear(), first.getMonth(), first.getDate());
var two = new Date(second.getFullYear(), second.getMonth(), second.getDate());
// Do the math.
var millisecondsPerDay = 1000 * 60 * 60 * 24;
var millisBetween = two.getTime() - one.getTime();
var days = millisBetween / millisecondsPerDay;
// Round down.
return Math.floor(days);
}
Si solo quiere la diferencia en días, asegúrese de usar UTC (GMT) o la resta no producirá un número entero de días en segundos si el horario de verano comienza o termina durante el intervalo.
Solía verificar el resultado de la función de fechado que usa .getTime () con Excel para el siglo XVIII. El resultado es correcto. Tengo otro método para calcular diferentes días:
function DaysOfYear(nYear) {
if ((nYear % 4) == 0) {
return 366;
}
else {
return 365;
}
}
function DiffDays(fDate, tDate) {
var fYear = fDate.getFullYear();
var tYear = tDate.getFullYear();
var fMonth = fDate.getMonth();
var tMonth = tDate.getMonth();
var fDay = fDate.getDate();
var tDay = tDate.getDate();
var nDays = 0;
if (tYear > fYear) { // different year
// remain days of from year
nDays = DaysOfYear(fYear) - YTD_Days(fDate);
// days of between fYear to tYear
for (y = (fYear + 1); y < tYear; y++) {
nDays = nDays + DaysOfYear(y);
}
// days from the beginning of tYear
nDays = nDays + YTD_Days(tDate);
}
else { // in the same year
nDays = YTD_Days(tDate) - YTD_Days(fDate);
};
return nDays;
}
function YTD_Days(dDate) {
var y = dDate.getFullYear();
var m = dDate.getMonth();
var nDays = 0
for (i = 0; i < m; i++) {
switch (i) {
case 0: // January
nDays = nDays + 31;
break;
case 1: // February
if ((y % 4) == 0) {
nDays = nDays + 29;
}
else {
nDays = nDays + 28;
};
break;
case 2: // March
nDays = nDays + 31;
break;
case 3: // April
nDays = nDays + 30;
break;
case 4: // May
nDays = nDays + 31;
break;
case 5: // June
nDays = nDays + 30;
break;
case 6: // July
nDays = nDays + 31;
break;
case 7: // August
nDays = nDays + 31;
break;
case 8: // September
nDays = nDays + 30;
break;
case 9: // October
nDays = nDays + 31;
break;
case 10: // November
nDays = nDays + 30;
break;
case 11: // December
nDays = nDays + 31;
break;
}
}
nDays = nDays + dDate.getDate();
return nDays;
}
Solo por curiosidad:
Si puede afirmar que el resultado SIEMPRE será <31 días, la siguiente también es una solución:
var deltaDays = new Date(endDate - startDate).getDate()-1
¿Por qué?
Bien descomponiendo la línea anterior:
var msecs = endDate - startDate; // difference in milliseconds
var dt = new Date(msecs); // will give us a date object pointing to a time
// somewhere in Jan 1970 (given the precondition above)
var days = dt.getDate(); // Take the day part of it
var deltaDays = days - 1; // since the numbering starts from 1, we have to
// substract 1 (Ex. if the diff in msecs is 0. The
// Date will point to 1st of Jan 1970)
Pero obviamente NO debes usarlo si tus resultados pueden ser> 31.
También sugiero echar un vistazo a la increíble biblioteca de moment.js . Tiene una función de diff
versátil, que puede usar para resolver el ejemplo anterior de la siguiente manera:
function is_same_date(startDate, endDate) {
var startMoment = moment(startDate).clone().startOf(''day''),
endMoment = moment(endDate).clone().startOf(''day'');
return startMoment.diff(endMoment, ''days'') == 0;
}
Aquí hay algunos ejemplos que usan la diferencia de moment.js
:
> d1 = new Date(2012,04,04,0,0)
Fri May 04 2012 00:00:00 GMT-0400 (EDT)
> d2 = new Date(2012,04,03,23,0)
Thu May 03 2012 23:00:00 GMT-0400 (EDT)
> d3 = new Date(2012,04,05,23,0)
Sat May 05 2012 23:00:00 GMT-0400 (EDT)
> moment(d2).diff(d1, ''days'')
0
> moment(d1).diff(d2, ''days'')
0
> moment(d1).diff(d3, ''days'') // uh oh. this is why we use `startOf`
-2
> moment(d2).diff(d3, ''days'')
-2
> moment(d3).startOf(''day'') // this modified d3, sets the time to 00:00:00.0000
> d3
Sat May 05 2012 00:00:00 GMT-0400 (EDT)
Si las zonas horarias son una preocupación, también puede usar moment.utc()
para convertir a una zona horaria normalizada.
use el método setHours (), asumiendo que el número de días nunca puede ser cero :)
function dateDiff1(startDate, endDate) {
endDate.setHours(0);
startDate.setHours(0);
//assuming days cannt be 0.
var x = ((endDate.getTime() - startDate.getTime()) / 1000*60*60*24);
if (x <1 && x>=0) {
return 1;
}
return x;
}