transcurrido tiempo sacar resultado restar obtener meses los horas fechas entre diferencia dias contar como años php

tiempo - obtener los meses entre dos fechas php



Encontrar el número de días entre dos fechas. (26)

¿Cómo encontrar el número de días entre dos fechas usando PHP?


Número de días entre dos fechas en PHP

function dateDiff($date1, $date2) //days find function { $diff = strtotime($date2) - strtotime($date1); return abs(round($diff / 86400)); } //start day $date1 = "11-10-2018"; // end day $date2 = "31-10-2018"; // call the days find fun store to variable $dateDiff = dateDiff($date1, $date2); echo "Difference between two dates: ". $dateDiff . " Days ";


TL; DR no usa marcas de tiempo UNIX. No use el time() . Si lo hace, prepárese si su confiabilidad de 98.0825% le falla. Use DateTime (o Carbon).

La respuesta correcta es la dada por Saksham Gupta (otras respuestas también son correctas):

$date1 = new DateTime(''2010-07-06''); $date2 = new DateTime(''2010-07-09''); $days = $date2->diff($date1)->format(''%a'');

O de manera procesal como una sola línea:

/** * Number of days between two dates. * * @param date $dt1 First date * @param date $dt2 Second date * @return int */ function daysBetween($dt1, $dt2) { return date_diff( date_create($dt2), date_create($dt1) )->format(''%a''); }

Si realmente debe usar las marcas de tiempo de UNIX, configure la zona horaria en GMT para evitar la mayoría de las dificultades que se detallan a continuación.

Respuesta larga: ¿por qué dividir por 24 * 60 * 60 (alias 86400) no es seguro?

La mayoría de las respuestas que usan las marcas de tiempo de UNIX (y 86400 para convertir eso en días) hacen dos suposiciones que, juntas, pueden llevar a escenarios con resultados incorrectos y errores sutiles que pueden ser difíciles de rastrear, y surgen incluso días, semanas o meses después un despliegue exitoso. No es que la solución no funcione, funciona. Hoy. Pero podría dejar de funcionar mañana.

El primer error no es considerar que cuando se le pregunta: "¿Cuántos días pasaron desde ayer?", Una computadora puede responder con sinceridad a cero si entre el presente y el instante indicado por "ayer" ha transcurrido menos de un día .

Generalmente, al convertir un "día" en una marca de tiempo UNIX, lo que se obtiene es la marca de tiempo para la medianoche de ese día en particular.

Así que entre las noches del 1 de octubre y el 15 de octubre, han transcurrido quince días. Pero entre las 13:00 del 1 de octubre y las 14:55 del 15 de octubre, han transcurrido quince días menos 5 minutos , y la mayoría de las soluciones que utilizan floor() o la conversión de enteros implícita informarán un día menos de lo esperado .

Entonces, "¿cuántos días atrás fue Ymd H: i: s"? dará la respuesta incorrecta .

El segundo error es igualar un día a 86400 segundos. Esto casi siempre es cierto: sucede con la frecuencia suficiente para pasar por alto los tiempos en que no lo hace. Pero la distancia en segundos entre dos noches y media consecutivas seguramente no sea 86400 al menos dos veces al año cuando el horario de verano entra en juego. La comparación de dos fechas a través de un límite DST dará la respuesta incorrecta.

Entonces, incluso si usa el "truco" de forzar todas las marcas de fecha y hora a una hora fija, digamos la medianoche (esto también lo hacen implícitamente varios idiomas y marcos cuando solo especifica día-mes-año y no también hora-minuto-segundo; lo mismo ocurre con el tipo DATE en bases de datos como MySQL), la fórmula ampliamente utilizada

(unix_timestamp(DATE2) - unix_timestamp(DATE1)) / 86400

o

floor(time() - strtotime($somedate)) / 86400

volverá, digamos, 17 cuando DATE1 y DATE2 estén en el mismo segmento DST del año; pero puede devolver 17.042, y peor aún, 16.958. El uso de floor () o cualquier truncamiento implícito a entero convertirá lo que debería haber sido un 17 en un 16. En otras circunstancias, expresiones como "$ días> 17" devolverán true para 17.042 incluso si esto indica que el día transcurrido el conteo es 18

Y las cosas se ponen aún más feas, ya que dicho código no es portátil en todas las plataformas, ya que algunos de ellos pueden aplicar segundos de salto y otros no . En las plataformas que sí lo hacen , la diferencia entre dos fechas no será 86400 sino 86401, o quizás 86399. Por lo tanto, el código que funcionó en mayo y que realmente pasó todas las pruebas se interrumpirá el próximo junio, cuando 12.99999 días se consideran 12 días en lugar de 13. Dos fechas que funcionó en 2015 no funcionará en 2017: las mismas fechas, y ninguno de los años es un año bisiesto. Pero entre 2018-03-01 y 2017-03-01, en esas plataformas a las que les importa, habrán pasado 366 días en lugar de 365, lo que hace de 2017 un año bisiesto.

Así que si realmente quieres usar las marcas de tiempo de UNIX:

  • use la función round() sabiamente, no floor() .

  • como alternativa, no calcule las diferencias entre D1-M1-YYY1 y D2-M2-YYY2. Esas fechas serán realmente consideradas como D1-M1-YYY1 00:00:00 y D2-M2-YYY2 00:00:00. Más bien, convierta entre D1-M1-YYY1 22:30:00 y D2-M2-YYY2 04:30:00. Siempre obtendrá un resto de unas veinte horas. Esto puede llegar a ser de veintiuna horas o diecinueve, y quizás dieciocho horas, cincuenta y nueve minutos treinta y seis segundos. No importa. Es un gran margen que se mantendrá allí y se mantendrá positivo en el futuro previsible. Ahora puede truncarlo con floor() en seguridad.

Sin embargo, la solución correcta , para evitar constantes mágicas, redondeo de kludges y una deuda de mantenimiento, es

  • usar una biblioteca de tiempo (Datetime, Carbon, lo que sea); no ruedes tu propio

  • escriba casos de prueba completos utilizando opciones de fecha realmente malvadas: en los límites del horario de verano, en los años bisiestos, en los segundos de los saltos, etc., así como en las fechas habituales. Idealmente (¡las llamadas a datetime son rápidas !) Generan cuatro años completos (y un día) de fechas reuniéndolas a partir de cadenas, secuencialmente, y aseguran que la diferencia entre el primer día y el día que se prueba aumenta constantemente en uno. Esto asegurará que si algo cambia en las rutinas de bajo nivel y las correcciones de los segundos de salto intenten causar estragos, al menos lo sabrá .

  • ejecuta esas pruebas regularmente junto con el resto de la suite de pruebas. Son cuestión de milisegundos y pueden ahorrarle literalmente horas de rascarse la cabeza.

Sea cual sea tu solución, ¡pruébala!

La función de función a continuación implementa una de las soluciones (como sucede, la aceptada) en un escenario del mundo real.

<?php $tz = ''Europe/Rome''; $yearFrom = 1980; $yearTo = 2020; $verbose = false; function funcdiff($date2, $date1) { $now = strtotime($date2); $your_date = strtotime($date1); $datediff = $now - $your_date; return floor($datediff / (60 * 60 * 24)); } ######################################## date_default_timezone_set($tz); $failures = 0; $tests = 0; $dom = array ( 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ); (array_sum($dom) === 365) || die("Thirty days hath November..."); $last = array(); for ($year = $yearFrom; $year < $yearTo; $year++) { $dom[2] = 28; // Apply leap year rules. if ($year % 4 === 0) { $dom[2] = 29; } if ($year % 100 === 0) { $dom[2] = 28; } if ($year % 400 === 0) { $dom[2] = 29; } for ($month = 1; $month <= 12; $month ++) { for ($day = 1; $day <= $dom[$month]; $day++) { $date = sprintf("%04d-%02d-%02d", $year, $month, $day); if (count($last) === 7) { $tests ++; $diff = funcdiff($date, $test = array_shift($last)); if ((double)$diff !== (double)7) { $failures ++; if ($verbose) { print "There seem to be {$diff} days between {$date} and {$test}/n"; } } } $last[] = $date; } } } print "This function failed {$failures} of its {$tests} tests between {$yearFrom} and {$yearTo}./n";

El resultado es,

This function failed 280 of its 14603 tests

Historia de terror: el costo de "ahorrar tiempo"

Esto sucedió hace algunos meses. Un ingenioso programador decidió guardar varios microsegundos de un cálculo que tomó aproximadamente treinta segundos como máximo, al insertar el infame "(MidnightOfDateB-MidnightOfDateA) / 86400" en varios lugares. Era una optimización tan obvia que ni siquiera lo documentó, y la optimización pasó las pruebas de integración y estuvo al acecho en el código durante varios meses, todo ello desapercibido.

Esto sucedió en un programa que calcula los salarios de varios vendedores de mayor venta, el menor de los cuales tiene una influencia mucho más espantosa que un equipo de programadores de cinco personas humilde en su conjunto. Un día, hace algunos meses, por razones poco importantes, el error se produjo, y algunos de esos muchachos sufrieron un pequeño día de comisiones pesadas. Definitivamente no estaban entretenidos.

Infinitamente peor, perdieron (ya muy poca) la fe que tenían en el programa al no estar diseñados para subrepticiarlos, y pretendieron, y obtuvieron , una revisión completa y detallada del código con casos de prueba ejecutados y comentados en términos sencillos (más un montón) de tratamiento de alfombra roja en las siguientes semanas).

Qué puedo decir: en el lado positivo, nos deshicimos de una gran cantidad de deuda técnica y pudimos reescribir y refactorizar varias piezas de un lío de espaguetis que se remonta a una infestación de COBOL en los años 90. Sin duda, el programa se ejecuta mejor ahora, y hay mucha más información de depuración para concentrarse rápidamente cuando algo parece sospechoso. Estimo que solo esto último ahorrará quizás uno o dos días-hombre por mes en el futuro previsible.

En el lado negativo, todo el escándalo le costó a la compañía cerca de € 200,000 por adelantado, además de indudablemente algo de poder de negociación (y, por lo tanto, aún más dinero).

El tipo responsable de la "optimización" había cambiado de trabajo hace un año, antes del desastre, pero aún había conversaciones para demandarlo por daños y perjuicios. Y no fue bien con los escalones superiores que fuera "la culpa del último hombre"; parecía una configuración para que resolviéramos el asunto, y al final, todavía estamos en la caseta del perro. y uno del equipo está planeando dejar de fumar.

Noventa y nueve veces de cada cien, el "truco 86400" funcionará perfectamente. (Por ejemplo, en PHP, strtotime() ignorará el horario de verano e informará que entre las dos noches del último sábado de octubre y la del lunes siguiente, han pasado exactamente 2 * 24 * 60 * 60 segundos, incluso si eso no es cierto. ... y dos errores felizmente harán una correcta).

Esto, damas y caballeros, fue un caso en el que no fue así. Al igual que con las bolsas de aire y los cinturones de seguridad, quizás nunca necesite realmente la complejidad (y la facilidad de uso) de DateTime o Carbon . Pero el día en que podrías (o el día en que tendrás que demostrar que pensaste en esto) vendrá como un ladrón en la noche. Estar preparado.


¡Esto funciona!

$start = strtotime(''2010-01-25''); $end = strtotime(''2010-02-20''); $days_between = ceil(abs($end - $start) / 86400);


A partir de la versión 5.3 de PHP, se agregaron nuevas funciones de fecha / hora para obtener la diferencia:

$datetime1 = new DateTime("2010-06-20"); $datetime2 = new DateTime("2011-06-22"); $difference = $datetime1->diff($datetime2); echo ''Difference: ''.$difference->y.'' years, '' .$difference->m.'' months, '' .$difference->d.'' days''; print_r($difference);

Resultado como abajo:

Difference: 1 years, 0 months, 2 days DateInterval Object ( [y] => 1 [m] => 0 [d] => 2 [h] => 0 [i] => 0 [s] => 0 [invert] => 0 [days] => 367 )

Espero eso ayude !


Aquí está mi versión mejorada que muestra 1 año (s) 2 mes (es) 25 día (s) si se pasa el segundo parámetro.

class App_Sandbox_String_Util { /** * Usage: App_Sandbox_String_Util::getDateDiff(); * @param int $your_date timestamp * @param bool $hr human readable. e.g. 1 year(s) 2 day(s) * @see http://.com/questions/2040560/finding-the-number-of-days-between-two-dates * @see http://qSandbox.com */ static public function getDateDiff($your_date, $hr = 0) { $now = time(); // or your date as well $datediff = $now - $your_date; $days = floor( $datediff / ( 3600 * 24 ) ); $label = ''''; if ($hr) { if ($days >= 365) { // over a year $years = floor($days / 365); $label .= $years . '' Year(s)''; $days -= 365 * $years; } if ($days) { $months = floor( $days / 30 ); $label .= '' '' . $months . '' Month(s)''; $days -= 30 * $months; } if ($days) { $label .= '' '' . $days . '' day(s)''; } } else { $label = $days; } return $label; } }


Bueno, la respuesta seleccionada no es la más correcta porque fallará fuera de UTC. Dependiendo de la zona horaria ( list ), puede haber ajustes de tiempo que creen días "sin" 24 horas, y esto hará que el cálculo (60 * 60 * 24) falle.

Aquí hay un ejemplo de ello:

date_default_timezone_set(''europe/lisbon''); $time1 = strtotime(''2016-03-27''); $time2 = strtotime(''2016-03-29''); echo floor( ($time2-$time1) /(60*60*24)); ^-- the output will be **1**

Así que la solución correcta será usar DateTime

date_default_timezone_set(''europe/lisbon''); $date1 = new DateTime("2016-03-27"); $date2 = new DateTime("2016-03-29"); echo $date2->diff($date1)->format("%a"); ^-- the output will be **2**


Convierta sus fechas a marcas de tiempo de Unix, luego reste una de la otra. Eso le dará la diferencia en segundos, que divide por 86400 (cantidad de segundos en un día) para darle una cantidad aproximada de días en ese rango.

Si sus fechas están en formato 25.1.2010 , 01/25/2010 o 2010-01-25 , puede usar la función strtotime :

$start = strtotime(''2010-01-25''); $end = strtotime(''2010-02-20''); $days_between = ceil(abs($end - $start) / 86400);

Usando ceil redondea la cantidad de días hasta el siguiente día completo. Use floor en su lugar si desea obtener la cantidad de días completos entre esas dos fechas.

Si sus fechas ya están en formato de marca de tiempo de Unix, puede omitir la conversión y simplemente hacer la parte $days_between . Para formatos de fecha más exóticos, puede que tenga que hacer un análisis personalizado para hacerlo bien.


Estilo orientado a objetos:

$datetime1 = new DateTime(''2009-10-11''); $datetime2 = new DateTime(''2009-10-13''); $interval = $datetime1->diff($datetime2); echo $interval->format(''%R%a days'');

Estilo procesal:

$datetime1 = date_create(''2009-10-11''); $datetime2 = date_create(''2009-10-13''); $interval = date_diff($datetime1, $datetime2); echo $interval->format(''%R%a days'');


Estoy usando Carbon en mis proyectos de compositor para este y otros propósitos similares.

Sería tan fácil como esto:

$dt = Carbon::parse(''2010-01-01''); echo $dt->diffInDays(Carbon::now());



Puedes encontrar fechas simplemente por

<?php $start = date_create(''1988-08-10''); $end = date_create(); // Current time and date $diff = date_diff( $start, $end ); echo ''The difference is ''; echo $diff->y . '' years, ''; echo $diff->m . '' months, ''; echo $diff->d . '' days, ''; echo $diff->h . '' hours, ''; echo $diff->i . '' minutes, ''; echo $diff->s . '' seconds''; // Output: The difference is 28 years, 5 months, 19 days, 20 hours, 34 minutes, 36 seconds echo ''The difference in days : '' . $diff->days; // Output: The difference in days : 10398


Si está utilizando PHP 5.3 > , esta es la forma más precisa de calcular la diferencia:

$earlier = new DateTime("2010-07-06"); $later = new DateTime("2010-07-09"); $diff = $later->diff($earlier)->format("%a");


Si estas usando MySql

function daysSince($date, $date2){ $q = "SELECT DATEDIFF(''$date'',''$date2'') AS days;"; $result = execQ($q); $row = mysql_fetch_array($result,MYSQL_BOTH); return ($row[0]);

}

function execQ($q){ $result = mysql_query( $q); if(!$result){echo (''Database error execQ'' . mysql_error());echo $q;} return $result;

}


Si quieres repetir todos los días entre la fecha de inicio y finalización, se me ocurrió esto:

$startdatum = $_POST[''start'']; // starting date $einddatum = $_POST[''eind'']; // end date $now = strtotime($startdatum); $your_date = strtotime($einddatum); $datediff = $your_date - $now; $number = floor($datediff/(60*60*24)); for($i=0;$i <= $number; $i++) { echo date(''d-m-Y'' ,strtotime("+".$i." day"))."<br>"; }


Si tiene los tiempos en segundos (marca de tiempo de IE unix), simplemente puede restar los tiempos y dividir por 86400 (segundos por día)


Trate de usar carbono

$d1 = /Carbon/Carbon::now()->subDays(92); $d2 = /Carbon/Carbon::now()->subDays(10); $days_btw = $d1->diffInDays($d2);

También puedes usar

/Carbon/Carbon::parse('''')

para crear un objeto de Carbon date utilizando una cadena de marca de tiempo dada.


Usé esto :)

$days = (strtotime($endDate) - strtotime($startDate)) / (60 * 60 * 24); print $days;

Ahora funciona


Utilizando esta sencilla función. Función declarar

<?php function dateDiff($firstDate,$secondDate){ $firstDate = strtotime($firstDate); $secondDate = strtotime($secondDate); $datediff = $firstDate - $secondDate; $output = round($datediff / (60 * 60 * 24)); return $output; } ?>

y llama a esta función como esta donde quieras

<?php echo dateDiff("2018-01-01","2018-12-31"); // OR $firstDate = "2018-01-01"; $secondDate = "2018-01-01"; echo dateDiff($firstDate,$secondDate); ?>


// Change this to the day in the future $day = 15; // Change this to the month in the future $month = 11; // Change this to the year in the future $year = 2012; // $days is the number of days between now and the date in the future $days = (int)((mktime (0,0,0,$month,$day,$year) - time(void))/86400); echo "There are $days days until $day/$month/$year";


$datediff = floor(strtotime($date1)/(60*60*24)) - floor(strtotime($date2)/(60*60*24));

y, si es necesario:

$datediff=abs($datediff);


$early_start_date = date2sql($_POST[''early_leave_date'']); $date = new DateTime($early_start_date); $date->modify(''+1 day''); $date_a = new DateTime($early_start_date . '' '' . $_POST[''start_hr''] . '':'' . $_POST[''start_mm'']); $date_b = new DateTime($date->format(''Y-m-d'') . '' '' . $_POST[''end_hr''] . '':'' . $_POST[''end_mm'']); $interval = date_diff($date_a, $date_b); $time = $interval->format(''%h:%i''); $parsed = date_parse($time); $seconds = $parsed[''hour''] * 3600 + $parsed[''minute''] * 60; // display_error($seconds); $second3 = $employee_information[''shift''] * 60 * 60; if ($second3 < $seconds) display_error(_(''Leave time can not be greater than shift time.Please try again........'')); set_focus(''start_hr''); set_focus(''end_hr''); return FALSE; }


$now = time(); // or your date as well $your_date = strtotime("2010-01-01"); $datediff = $now - $your_date; echo round($datediff / (60 * 60 * 24));


$start = ''2013-09-08''; $end = ''2013-09-15''; $diff = (strtotime($end)- strtotime($start))/24/3600; echo $diff;


<?php $date1=date_create("2013-03-15"); $date2=date_create("2013-12-12"); $diff=date_diff($date1,$date2); echo $diff->format("%R%a days"); ?>

Utilizó el código anterior muy simple. Gracias.


function get_daydiff($end_date,$today) { if($today=='''') { $today=date(''Y-m-d''); } $str = floor(strtotime($end_date)/(60*60*24)) - floor(strtotime($today)/(60*60*24)); return $str; } $d1 = "2018-12-31"; $d2 = "2018-06-06"; echo get_daydiff($d1, $d2);


function howManyDays($startDate,$endDate) { $date1 = strtotime($startDate." 0:00:00"); $date2 = strtotime($endDate." 23:59:59"); $res = (int)(($date2-$date1)/86400); return $res; }