meses - diff php
¿Cómo calcular la diferencia entre dos fechas usando PHP? (30)
Tengo dos fechas del formulario:
Start Date: 2007-03-24
End Date: 2009-06-26
Ahora necesito encontrar la diferencia entre estos dos en la siguiente forma:
2 years, 3 months and 2 days
¿Cómo puedo hacer esto en PHP?
Para PHP <5.3 de lo contrario, vea la respuesta de jurka a continuación
Puede usar strtotime () para convertir dos fechas a tiempo de Unix y luego calcular el número de segundos entre ellas. A partir de esto es bastante fácil calcular diferentes períodos de tiempo.
$date1 = "2007-03-24";
$date2 = "2009-06-26";
$diff = abs(strtotime($date2) - strtotime($date1));
$years = floor($diff / (365*60*60*24));
$months = floor(($diff - $years * 365*60*60*24) / (30*60*60*24));
$days = floor(($diff - $years * 365*60*60*24 - $months*30*60*60*24)/ (60*60*24));
printf("%d years, %d months, %d days/n", $years, $months, $days);
Edición: Obviamente, la forma preferida de hacer esto es como la descrita por jurka a continuación. Mi código generalmente solo se recomienda si no tienes PHP 5.3 o superior.
Varias personas en los comentarios han señalado que el código anterior es solo una aproximación. Todavía creo que para la mayoría de los propósitos está bien, ya que el uso de un rango es más para proporcionar una idea de cuánto tiempo ha pasado o queda en lugar de proporcionar precisión, si desea hacerlo, simplemente imprima la fecha.
A pesar de todo eso, he decidido abordar las quejas. Si realmente necesita un rango exacto pero no tiene acceso a PHP 5.3, use el siguiente código (también debería funcionar en PHP 4). Este es un puerto directo del código que PHP utiliza internamente para calcular los rangos, con la excepción de que no tiene en cuenta el horario de verano. Eso significa que está apagado por una hora a lo sumo, pero a excepción de eso debe ser correcto.
<?php
/**
* Calculate differences between two dates with precise semantics. Based on PHPs DateTime::diff()
* implementation by Derick Rethans. Ported to PHP by Emil H, 2011-05-02. No rights reserved.
*
* See here for original code:
* http://svn.php.net/viewvc/php/php-src/trunk/ext/date/lib/tm2unixtime.c?revision=302890&view=markup
* http://svn.php.net/viewvc/php/php-src/trunk/ext/date/lib/interval.c?revision=298973&view=markup
*/
function _date_range_limit($start, $end, $adj, $a, $b, $result)
{
if ($result[$a] < $start) {
$result[$b] -= intval(($start - $result[$a] - 1) / $adj) + 1;
$result[$a] += $adj * intval(($start - $result[$a] - 1) / $adj + 1);
}
if ($result[$a] >= $end) {
$result[$b] += intval($result[$a] / $adj);
$result[$a] -= $adj * intval($result[$a] / $adj);
}
return $result;
}
function _date_range_limit_days($base, $result)
{
$days_in_month_leap = array(31, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
$days_in_month = array(31, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
_date_range_limit(1, 13, 12, "m", "y", &$base);
$year = $base["y"];
$month = $base["m"];
if (!$result["invert"]) {
while ($result["d"] < 0) {
$month--;
if ($month < 1) {
$month += 12;
$year--;
}
$leapyear = $year % 400 == 0 || ($year % 100 != 0 && $year % 4 == 0);
$days = $leapyear ? $days_in_month_leap[$month] : $days_in_month[$month];
$result["d"] += $days;
$result["m"]--;
}
} else {
while ($result["d"] < 0) {
$leapyear = $year % 400 == 0 || ($year % 100 != 0 && $year % 4 == 0);
$days = $leapyear ? $days_in_month_leap[$month] : $days_in_month[$month];
$result["d"] += $days;
$result["m"]--;
$month++;
if ($month > 12) {
$month -= 12;
$year++;
}
}
}
return $result;
}
function _date_normalize($base, $result)
{
$result = _date_range_limit(0, 60, 60, "s", "i", $result);
$result = _date_range_limit(0, 60, 60, "i", "h", $result);
$result = _date_range_limit(0, 24, 24, "h", "d", $result);
$result = _date_range_limit(0, 12, 12, "m", "y", $result);
$result = _date_range_limit_days(&$base, &$result);
$result = _date_range_limit(0, 12, 12, "m", "y", $result);
return $result;
}
/**
* Accepts two unix timestamps.
*/
function _date_diff($one, $two)
{
$invert = false;
if ($one > $two) {
list($one, $two) = array($two, $one);
$invert = true;
}
$key = array("y", "m", "d", "h", "i", "s");
$a = array_combine($key, array_map("intval", explode(" ", date("Y m d H i s", $one))));
$b = array_combine($key, array_map("intval", explode(" ", date("Y m d H i s", $two))));
$result = array();
$result["y"] = $b["y"] - $a["y"];
$result["m"] = $b["m"] - $a["m"];
$result["d"] = $b["d"] - $a["d"];
$result["h"] = $b["h"] - $a["h"];
$result["i"] = $b["i"] - $a["i"];
$result["s"] = $b["s"] - $a["s"];
$result["invert"] = $invert ? 1 : 0;
$result["days"] = intval(abs(($one - $two)/86400));
if ($invert) {
_date_normalize(&$a, &$result);
} else {
_date_normalize(&$b, &$result);
}
return $result;
}
$date = "1986-11-10 19:37:22";
print_r(_date_diff(strtotime($date), time()));
print_r(_date_diff(time(), strtotime($date)));
Ejemplo de uso:
echo time_diff_string(''2013-05-01 00:22:35'', ''now'');
echo time_diff_string(''2013-05-01 00:22:35'', ''now'', true);
Salida:
4 months ago
4 months, 2 weeks, 3 days, 1 hour, 49 minutes, 15 seconds ago
Función:
function time_diff_string($from, $to, $full = false) {
$from = new DateTime($from);
$to = new DateTime($to);
$diff = $to->diff($from);
$diff->w = floor($diff->d / 7);
$diff->d -= $diff->w * 7;
$string = array(
''y'' => ''year'',
''m'' => ''month'',
''w'' => ''week'',
''d'' => ''day'',
''h'' => ''hour'',
''i'' => ''minute'',
''s'' => ''second'',
);
foreach ($string as $k => &$v) {
if ($diff->$k) {
$v = $diff->$k . '' '' . $v . ($diff->$k > 1 ? ''s'' : '''');
} else {
unset($string[$k]);
}
}
if (!$full) $string = array_slice($string, 0, 1);
return $string ? implode('', '', $string) . '' ago'' : ''just now'';
}
"si" la fecha se almacena en MySQL, me resulta más fácil hacer el cálculo de la diferencia en el nivel de la base de datos ... Luego, en función de los resultados de Día, Hora, Min, Sec, análisis y visualización, según corresponda ...
mysql> select firstName, convert_tz(loginDate, ''+00:00'', ''-04:00'') as loginDate, TIMESTAMPDIFF(DAY, loginDate, now()) as ''Day'', TIMESTAMPDIFF(HOUR, loginDate, now())+4 as ''Hour'', TIMESTAMPDIFF(MINUTE, loginDate, now())+(60*4) as ''Min'', TIMESTAMPDIFF(SECOND, loginDate, now())+(60*60*4) as ''Sec'' from User_ where userId != ''10158'' AND userId != ''10198'' group by emailAddress order by loginDate desc;
+-----------+---------------------+------+------+------+--------+
| firstName | loginDate | Day | Hour | Min | Sec |
+-----------+---------------------+------+------+------+--------+
| Peter | 2014-03-30 18:54:40 | 0 | 4 | 244 | 14644 |
| Keith | 2014-03-30 18:54:11 | 0 | 4 | 244 | 14673 |
| Andres | 2014-03-28 09:20:10 | 2 | 61 | 3698 | 221914 |
| Nadeem | 2014-03-26 09:33:43 | 4 | 109 | 6565 | 393901 |
+-----------+---------------------+------+------+------+--------+
4 rows in set (0.00 sec)
Echa un vistazo al siguiente enlace. Esta es la mejor respuesta que he encontrado hasta ahora .. :)
function dateDiff ($d1, $d2) {
// Return the number of days between the two dates:
return round(abs(strtotime($d1) - strtotime($d2))/86400);
} // end function dateDiff
No importa qué fecha sea anterior o posterior cuando pase los parámetros de fecha. La función utiliza el valor absoluto de PHP ABS () para devolver siempre un número positivo como el número de días entre las dos fechas.
Tenga en cuenta que el número de días entre las dos fechas NO incluye ambas fechas. Por lo tanto, si está buscando la cantidad de días representados por todas las fechas entre e incluyendo las fechas ingresadas, deberá agregar uno (1) al resultado de esta función.
Por ejemplo, la diferencia (según lo devuelto por la función anterior) entre 2013-02-09 y 2013-02-14 es 5. Pero el número de días o fechas representados por el rango de fechas 2013-02-09 - 2013-02- 14 es 6.
El mejor curso de acción es usar los objetos DateTime
(y DateInterval
) de DateInterval
. Cada fecha se encapsula en un objeto DateTime
, y luego se puede hacer una diferencia entre los dos:
$first_date = new DateTime("2012-11-30 17:03:30");
$second_date = new DateTime("2012-12-21 00:00:00");
El objeto DateTime
aceptará cualquier formato que strtotime()
. Si se necesita un formato de fecha aún más específico, DateTime::createFromFormat()
se puede usar para crear el objeto DateTime
.
Después de que ambos objetos fueron instanciados, se resta uno del otro con DateTime::diff()
.
$difference = $first_date->diff($second_date);
$difference
DateInterval
ahora contiene un objeto DateInterval
con la información de diferencia. Un var_dump()
ve así:
object(DateInterval)
public ''y'' => int 0
public ''m'' => int 0
public ''d'' => int 20
public ''h'' => int 6
public ''i'' => int 56
public ''s'' => int 30
public ''invert'' => int 0
public ''days'' => int 20
Para formatear el objeto DateInterval
, necesitaremos verificar cada valor y excluirlo si es 0:
/**
* Format an interval to show all existing components.
* If the interval doesn''t have a time component (years, months, etc)
* That component won''t be displayed.
*
* @param DateInterval $interval The interval
*
* @return string Formatted interval string.
*/
function format_interval(DateInterval $interval) {
$result = "";
if ($interval->y) { $result .= $interval->format("%y years "); }
if ($interval->m) { $result .= $interval->format("%m months "); }
if ($interval->d) { $result .= $interval->format("%d days "); }
if ($interval->h) { $result .= $interval->format("%h hours "); }
if ($interval->i) { $result .= $interval->format("%i minutes "); }
if ($interval->s) { $result .= $interval->format("%s seconds "); }
return $result;
}
Todo lo que queda ahora es llamar a nuestra función en el objeto $difference
DateInterval
:
echo format_interval($difference);
Y obtenemos el resultado correcto:
20 días 6 horas 56 minutos 30 segundos
El código completo utilizado para lograr el objetivo:
/**
* Format an interval to show all existing components.
* If the interval doesn''t have a time component (years, months, etc)
* That component won''t be displayed.
*
* @param DateInterval $interval The interval
*
* @return string Formatted interval string.
*/
function format_interval(DateInterval $interval) {
$result = "";
if ($interval->y) { $result .= $interval->format("%y years "); }
if ($interval->m) { $result .= $interval->format("%m months "); }
if ($interval->d) { $result .= $interval->format("%d days "); }
if ($interval->h) { $result .= $interval->format("%h hours "); }
if ($interval->i) { $result .= $interval->format("%i minutes "); }
if ($interval->s) { $result .= $interval->format("%s seconds "); }
return $result;
}
$first_date = new DateTime("2012-11-30 17:03:30");
$second_date = new DateTime("2012-12-21 00:00:00");
$difference = $first_date->diff($second_date);
echo format_interval($difference);
Encontré su artículo en la siguiente página, que contiene varias referencias para los cálculos de fecha y hora de PHP .
Calcule la diferencia entre dos Fechas (y hora) usando PHP. La siguiente página proporciona una gama de diferentes métodos (7 en total) para realizar cálculos de fecha / hora usando PHP, para determinar la diferencia en tiempo (horas, munites), días, meses o años entre dos fechas.
Consulte PHP Fecha Hora: 7 métodos para calcular la diferencia entre 2 fechas .
Esta es mi función. PHP requerido> = 5.3.4. Utiliza la clase DateTime. Muy rápido, rápido y puede hacer la diferencia entre dos fechas o incluso el llamado "tiempo desde".
if(function_exists(''grk_Datetime_Since'') === FALSE){
function grk_Datetime_Since($From, $To='''', $Prefix='''', $Suffix='' ago'', $Words=array()){
# Est-ce qu''on calcul jusqu''à un moment précis ? Probablement pas, on utilise maintenant
if(empty($To) === TRUE){
$To = time();
}
# On va s''assurer que $From est numérique
if(is_int($From) === FALSE){
$From = strtotime($From);
};
# On va s''assurer que $To est numérique
if(is_int($To) === FALSE){
$To = strtotime($To);
}
# On a une erreur ?
if($From === FALSE OR $From === -1 OR $To === FALSE OR $To === -1){
return FALSE;
}
# On va créer deux objets de date
$From = new DateTime(@date(''Y-m-d H:i:s'', $From), new DateTimeZone(''GMT''));
$To = new DateTime(@date(''Y-m-d H:i:s'', $To), new DateTimeZone(''GMT''));
# On va calculer la différence entre $From et $To
if(($Diff = $From->diff($To)) === FALSE){
return FALSE;
}
# On va merger le tableau des noms (par défaut, anglais)
$Words = array_merge(array(
''year'' => ''year'',
''years'' => ''years'',
''month'' => ''month'',
''months'' => ''months'',
''week'' => ''week'',
''weeks'' => ''weeks'',
''day'' => ''day'',
''days'' => ''days'',
''hour'' => ''hour'',
''hours'' => ''hours'',
''minute'' => ''minute'',
''minutes'' => ''minutes'',
''second'' => ''second'',
''seconds'' => ''seconds''
), $Words);
# On va créer la chaîne maintenant
if($Diff->y > 1){
$Text = $Diff->y.'' ''.$Words[''years''];
} elseif($Diff->y == 1){
$Text = ''1 ''.$Words[''year''];
} elseif($Diff->m > 1){
$Text = $Diff->m.'' ''.$Words[''months''];
} elseif($Diff->m == 1){
$Text = ''1 ''.$Words[''month''];
} elseif($Diff->d > 7){
$Text = ceil($Diff->d/7).'' ''.$Words[''weeks''];
} elseif($Diff->d == 7){
$Text = ''1 ''.$Words[''week''];
} elseif($Diff->d > 1){
$Text = $Diff->d.'' ''.$Words[''days''];
} elseif($Diff->d == 1){
$Text = ''1 ''.$Words[''day''];
} elseif($Diff->h > 1){
$Text = $Diff->h.'' ''.$Words[''hours''];
} elseif($Diff->h == 1){
$Text = ''1 ''.$Words[''hour''];
} elseif($Diff->i > 1){
$Text = $Diff->i.'' ''.$Words[''minutes''];
} elseif($Diff->i == 1){
$Text = ''1 ''.$Words[''minute''];
} elseif($Diff->s > 1){
$Text = $Diff->s.'' ''.$Words[''seconds''];
} else {
$Text = ''1 ''.$Words[''second''];
}
return $Prefix.$Text.$Suffix;
}
}
Esto intentará detectar si se dio una marca de tiempo o no, y también devolverá fechas / horas futuras como valores negativos:
<?php
function time_diff($start, $end = NULL, $convert_to_timestamp = FALSE) {
// If $convert_to_timestamp is not explicitly set to TRUE,
// check to see if it was accidental:
if ($convert_to_timestamp || !is_numeric($start)) {
// If $convert_to_timestamp is TRUE, convert to timestamp:
$timestamp_start = strtotime($start);
}
else {
// Otherwise, leave it as a timestamp:
$timestamp_start = $start;
}
// Same as above, but make sure $end has actually been overridden with a non-null,
// non-empty, non-numeric value:
if (!is_null($end) && (!empty($end) && !is_numeric($end))) {
$timestamp_end = strtotime($end);
}
else {
// If $end is NULL or empty and non-numeric value, assume the end time desired
// is the current time (useful for age, etc):
$timestamp_end = time();
}
// Regardless, set the start and end times to an integer:
$start_time = (int) $timestamp_start;
$end_time = (int) $timestamp_end;
// Assign these values as the params for $then and $now:
$start_time_var = ''start_time'';
$end_time_var = ''end_time'';
// Use this to determine if the output is positive (time passed) or negative (future):
$pos_neg = 1;
// If the end time is at a later time than the start time, do the opposite:
if ($end_time <= $start_time) {
$start_time_var = ''end_time'';
$end_time_var = ''start_time'';
$pos_neg = -1;
}
// Convert everything to the proper format, and do some math:
$then = new DateTime(date(''Y-m-d H:i:s'', $$start_time_var));
$now = new DateTime(date(''Y-m-d H:i:s'', $$end_time_var));
$years_then = $then->format(''Y'');
$years_now = $now->format(''Y'');
$years = $years_now - $years_then;
$months_then = $then->format(''m'');
$months_now = $now->format(''m'');
$months = $months_now - $months_then;
$days_then = $then->format(''d'');
$days_now = $now->format(''d'');
$days = $days_now - $days_then;
$hours_then = $then->format(''H'');
$hours_now = $now->format(''H'');
$hours = $hours_now - $hours_then;
$minutes_then = $then->format(''i'');
$minutes_now = $now->format(''i'');
$minutes = $minutes_now - $minutes_then;
$seconds_then = $then->format(''s'');
$seconds_now = $now->format(''s'');
$seconds = $seconds_now - $seconds_then;
if ($seconds < 0) {
$minutes -= 1;
$seconds += 60;
}
if ($minutes < 0) {
$hours -= 1;
$minutes += 60;
}
if ($hours < 0) {
$days -= 1;
$hours += 24;
}
$months_last = $months_now - 1;
if ($months_now == 1) {
$years_now -= 1;
$months_last = 12;
}
// "Thirty days hath September, April, June, and November" ;)
if ($months_last == 9 || $months_last == 4 || $months_last == 6 || $months_last == 11) {
$days_last_month = 30;
}
else if ($months_last == 2) {
// Factor in leap years:
if (($years_now % 4) == 0) {
$days_last_month = 29;
}
else {
$days_last_month = 28;
}
}
else {
$days_last_month = 31;
}
if ($days < 0) {
$months -= 1;
$days += $days_last_month;
}
if ($months < 0) {
$years -= 1;
$months += 12;
}
// Finally, multiply each value by either 1 (in which case it will stay the same),
// or by -1 (in which case it will become negative, for future dates).
// Note: 0 * 1 == 0 * -1 == 0
$out = new stdClass;
$out->years = (int) $years * $pos_neg;
$out->months = (int) $months * $pos_neg;
$out->days = (int) $days * $pos_neg;
$out->hours = (int) $hours * $pos_neg;
$out->minutes = (int) $minutes * $pos_neg;
$out->seconds = (int) $seconds * $pos_neg;
return $out;
}
Ejemplo de uso:
<?php
$birthday = ''June 2, 1971'';
$check_age_for_this_date = ''June 3, 1999 8:53pm'';
$age = time_diff($birthday, $check_age_for_this_date)->years;
print $age;// 28
O:
<?php
$christmas_2020 = ''December 25, 2020'';
$countdown = time_diff($christmas_2020);
print_r($countdown);
No sé si está utilizando un marco PHP o no, pero muchos marcos PHP tienen bibliotecas de fecha / hora y ayudantes para evitar que reinvente la rueda.
Por ejemplo, CodeIgniter tiene la función timespan()
. Simplemente ingrese dos marcas de tiempo Unix y generará automáticamente un resultado como este:
1 Year, 10 Months, 2 Weeks, 5 Days, 10 Hours, 16 Minutes
Para la versión php> = 5.3: Cree dos objetos de fecha y luego use la función date_diff()
. Se devolverá el objeto php DateInterval . ver documentación
$date1=date_create("2007-03-24");
$date2=date_create("2009-06-26");
$diff=date_diff($date1,$date2);
echo $diff->format("%R%a days");
Preferiría usar los objetos date_create
y date_diff
.
Código:
$date1 = date_create("2007-03-24");
$date2 = date_create("2009-06-26");
$dateDifference = date_diff($date1, $date2)->format(''%y years, %m months and %d days'');
echo $dateDifference;
Salida:
2 years, 3 months and 2 days
Para más información lea el manual de PHP date_diff
Según manual
date_diff
es un alias de DateTime::diff()
Puedes usar el
getdate()
función que devuelve una matriz que contiene todos los elementos de la fecha / hora suministrada:
$diff = abs($endDate - $startDate);
$my_t=getdate($diff);
print("$my_t[year] years, $my_t[month] months and $my_t[mday] days");
Si sus fechas de inicio y finalización están en formato de cadena, utilice
$startDate = strtotime($startDateStr);
$endDate = strtotime($endDateStr);
antes del codigo anterior
Sugiero usar los objetos DateTime y DateInterval.
$date1 = new DateTime("2007-03-24");
$date2 = new DateTime("2009-06-26");
$interval = $date1->diff($date2);
echo "difference " . $interval->y . " years, " . $interval->m." months, ".$interval->d." days ";
// shows the total amount of days (not divided into years, months and days like above)
echo "difference " . $interval->days . " days ";
leer más php DateTime :: diff manual
Del manual:
A partir de PHP 5.2.2, los objetos DateTime pueden compararse usando operadores de comparación.
$date1 = new DateTime("now");
$date2 = new DateTime("tomorrow");
var_dump($date1 == $date2); // bool(false)
var_dump($date1 < $date2); // bool(true)
var_dump($date1 > $date2); // bool(false)
También puede usar el siguiente código para devolver la diferencia de fecha por fracciones de ronda up $ date1 = $ duedate; // asignar fecha de vencimiento echo $ fecha2 = fecha ("Ymd"); // fecha actual $ ts1 = strtotime ($ date1); $ ts2 = strtotime ($ date2); $ seconds_diff = $ ts1 - $ ts2; echo $ datediff = ceil (($ seconds_diff / 3600) / 24); // regreso en dias
Si utiliza el método de piso de php en lugar de ceil, le devolverá la fracción redonda hacia abajo. Por favor verifique la diferencia aquí, algunas veces si la zona horaria de su servidor de ensayo es diferente, entonces la zona horaria del sitio en vivo en ese caso, puede obtener resultados diferentes, así que cambie las condiciones en consecuencia.
Tengo una lógica simple para eso:
<?php
per_days_diff(''2011-12-12'',''2011-12-29'')
function per_days_diff($start_date, $end_date) {
$per_days = 0;
$noOfWeek = 0;
$noOfWeekEnd = 0;
$highSeason=array("7", "8");
$current_date = strtotime($start_date);
$current_date += (24 * 3600);
$end_date = strtotime($end_date);
$seassion = (in_array(date(''m'', $current_date), $highSeason))?"2":"1";
$noOfdays = array('''');
while ($current_date <= $end_date) {
if ($current_date <= $end_date) {
$date = date(''N'', $current_date);
array_push($noOfdays,$date);
$current_date = strtotime(''+1 day'', $current_date);
}
}
$finalDays = array_shift($noOfdays);
//print_r($noOfdays);
$weekFirst = array("week"=>array(),"weekEnd"=>array());
for($i = 0; $i < count($noOfdays); $i++)
{
if ($noOfdays[$i] == 1)
{
//echo "This is week";
//echo "<br/>";
if($noOfdays[$i+6]==7)
{
$noOfWeek++;
$i=$i+6;
}
else
{
$per_days++;
}
//array_push($weekFirst["week"],$day);
}
else if($noOfdays[$i]==5)
{
//echo "This is weekend";
//echo "<br/>";
if($noOfdays[$i+2] ==7)
{
$noOfWeekEnd++;
$i = $i+2;
}
else
{
$per_days++;
}
//echo "After weekend value:- ".$i;
//echo "<br/>";
}
else
{
$per_days++;
}
}
/*echo $noOfWeek;
echo "<br/>";
echo $noOfWeekEnd;
echo "<br/>";
print_r($per_days);
echo "<br/>";
print_r($weekFirst);
*/
$duration = array("weeks"=>$noOfWeek, "weekends"=>$noOfWeekEnd, "perDay"=>$per_days, "seassion"=>$seassion);
return $duration;
?>
Tuve el mismo problema con PHP 5.2 y lo resolví con MySQL. Puede que no sea exactamente lo que estás buscando, pero esto hará el truco y devolverá el número de días:
$datediff_q = $dbh->prepare("SELECT DATEDIFF(:date2, :date1)");
$datediff_q->bindValue('':date1'', ''2007-03-24'', PDO::PARAM_STR);
$datediff_q->bindValue('':date2'', ''2009-06-26'', PDO::PARAM_STR);
$datediff = ($datediff_q->execute()) ? $datediff_q->fetchColumn(0) : false;
Más información aquí http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_datediff
Ver Horas y Minuts y Segundos.
$date1 = "2008-11-01 22:45:00";
$date2 = "2009-12-04 13:44:01";
$diff = abs(strtotime($date2) - strtotime($date1));
$years = floor($diff / (365*60*60*24));
$months = floor(($diff - $years * 365*60*60*24) / (30*60*60*24));
$days = floor(($diff - $years * 365*60*60*24 - $months*30*60*60*24)/ (60*60*24));
$hours = floor(($diff - $years * 365*60*60*24 - $months*30*60*60*24 - $days*60*60*24)/ (60*60));
$minuts = floor(($diff - $years * 365*60*60*24 - $months*30*60*60*24 - $days*60*60*24 - $hours*60*60)/ 60);
$seconds = floor(($diff - $years * 365*60*60*24 - $months*30*60*60*24 - $days*60*60*24 - $hours*60*60 - $minuts*60));
printf("%d years, %d months, %d days, %d hours, %d minuts/n, %d seconds/n", $years, $months, $days, $hours, $minuts, $seconds);
Voté por la answer porque es mi favorita, pero tengo una versión pre-php.5.3 ...
Me encontré trabajando en un problema similar, que es cómo llegué a esta pregunta en primer lugar, pero solo necesitaba una diferencia en horas. Pero mi función resolvió esto muy bien también y no tengo ningún lugar en mi propia biblioteca para mantenerla donde no se pierda ni se olvide, así que ... espero que esto sea útil para alguien.
/**
*
* @param DateTime $oDate1
* @param DateTime $oDate2
* @return array
*/
function date_diff_array(DateTime $oDate1, DateTime $oDate2) {
$aIntervals = array(
''year'' => 0,
''month'' => 0,
''week'' => 0,
''day'' => 0,
''hour'' => 0,
''minute'' => 0,
''second'' => 0,
);
foreach($aIntervals as $sInterval => &$iInterval) {
while($oDate1 <= $oDate2){
$oDate1->modify(''+1 '' . $sInterval);
if ($oDate1 > $oDate2) {
$oDate1->modify(''-1 '' . $sInterval);
break;
} else {
$iInterval++;
}
}
}
return $aIntervals;
}
Y la prueba:
$oDate = new DateTime();
$oDate->modify(''+111402189 seconds'');
var_dump($oDate);
var_dump(date_diff_array(new DateTime(), $oDate));
Y el resultado:
object(DateTime)[2]
public ''date'' => string ''2014-04-29 18:52:51'' (length=19)
public ''timezone_type'' => int 3
public ''timezone'' => string ''America/New_York'' (length=16)
array
''year'' => int 3
''month'' => int 6
''week'' => int 1
''day'' => int 4
''hour'' => int 9
''minute'' => int 3
''second'' => int 8
Obtuve la idea original de here , que modifiqué para mis usos (y espero que mi modificación se muestre también en esa página).
Puede eliminar fácilmente los intervalos que no desee (diga "semana") quitándolos de la matriz $aIntervals
, o tal vez agregando un parámetro $aExclude
, o simplemente los filtre cuando emita la cadena.
Ya que todos están publicando ejemplos de código, aquí hay otra versión.
Quería que una función mostrara las diferencias de segundos a años (solo una unidad). Para períodos de más de 1 día, quise que se reiniciara a la medianoche (10 am del lunes visto desde las 9 am del miércoles hace 2 días, no 1). Y durante períodos de más de un mes, quise que la reinversión fuera el mismo día del mes (incluidos los meses de 30/31 días y años bisiestos).
Esto es lo que se me ocurrió:
/**
* Returns how long ago something happened in the past, showing it
* as n seconds / minutes / hours / days / weeks / months / years ago.
*
* For periods over a day, it rolls over at midnight (so doesn''t depend
* on current time of day), and it correctly accounts for month-lengths
* and leap-years (months and years rollover on current day of month).
*
* $param string $timestamp in DateTime format
* $return string description of interval
*/
function ago($timestamp)
{
$then = date_create($timestamp);
// for anything over 1 day, make it rollover on midnight
$today = date_create(''tomorrow''); // ie end of today
$diff = date_diff($then, $today);
if ($diff->y > 0) return $diff->y.'' year''.($diff->y>1?''s'':'''').'' ago'';
if ($diff->m > 0) return $diff->m.'' month''.($diff->m>1?''s'':'''').'' ago'';
$diffW = floor($diff->d / 7);
if ($diffW > 0) return $diffW.'' week''.($diffW>1?''s'':'''').'' ago'';
if ($diff->d > 1) return $diff->d.'' day''.($diff->d>1?''s'':'''').'' ago'';
// for anything less than 1 day, base it off ''now''
$now = date_create();
$diff = date_diff($then, $now);
if ($diff->d > 0) return ''yesterday'';
if ($diff->h > 0) return $diff->h.'' hour''.($diff->h>1?''s'':'''').'' ago'';
if ($diff->i > 0) return $diff->i.'' minute''.($diff->i>1?''s'':'''').'' ago'';
return $diff->s.'' second''.($diff->s==1?'''':''s'').'' ago'';
}
DateInterval
Es genial pero tiene un par de advertencias:
- solo para PHP 5.3+ ( pero eso ya no es una buena excusa )
- solo admite años, meses, días, horas, minutos y segundos (sin semanas)
- calcula la diferencia con todos los + días anteriores (no puede obtener la diferencia solo en meses)
Para superar eso, codifiqué lo siguiente (mejorado de la respuesta @enobrev ):
function date_dif($since, $until, $keys = ''year|month|week|day|hour|minute|second'')
{
$date = array_map(''strtotime'', array($since, $until));
if ((count($date = array_filter($date, ''is_int'')) == 2) && (sort($date) === true))
{
$result = array_fill_keys(explode(''|'', $keys), 0);
foreach (preg_grep(''~^(?:year|month)~i'', $result) as $key => $value)
{
while ($date[1] >= strtotime(sprintf(''+%u %s'', $value + 1, $key), $date[0]))
{
++$value;
}
$date[0] = strtotime(sprintf(''+%u %s'', $result[$key] = $value, $key), $date[0]);
}
foreach (preg_grep(''~^(?:year|month)~i'', $result, PREG_GREP_INVERT) as $key => $value)
{
if (($value = intval(abs($date[0] - $date[1]) / strtotime(sprintf(''%u %s'', 1, $key), 0))) > 0)
{
$date[0] = strtotime(sprintf(''+%u %s'', $result[$key] = $value, $key), $date[0]);
}
}
return $result;
}
return false;
}
Se ejecuta dos bucles; el primero trata con los intervalos relativos (años y meses) a través del forzado bruto, y el segundo calcula los intervalos absolutos adicionales con aritmética simple (por lo que es más rápido)
echo humanize(date_dif(''2007-03-24'', ''2009-07-31'', ''second'')); // 74300400 seconds
echo humanize(date_dif(''2007-03-24'', ''2009-07-31'', ''minute|second'')); // 1238400 minutes, 0 seconds
echo humanize(date_dif(''2007-03-24'', ''2009-07-31'', ''hour|minute|second'')); // 20640 hours, 0 minutes, 0 seconds
echo humanize(date_dif(''2007-03-24'', ''2009-07-31'', ''year|day'')); // 2 years, 129 days
echo humanize(date_dif(''2007-03-24'', ''2009-07-31'', ''year|week'')); // 2 years, 18 weeks
echo humanize(date_dif(''2007-03-24'', ''2009-07-31'', ''year|week|day'')); // 2 years, 18 weeks, 3 days
echo humanize(date_dif(''2007-03-24'', ''2009-07-31'')); // 2 years, 4 months, 1 week, 0 days, 0 hours, 0 minutes, 0 seconds
function humanize($array)
{
$result = array();
foreach ($array as $key => $value)
{
$result[$key] = $value . '' '' . $key;
if ($value != 1)
{
$result[$key] .= ''s'';
}
}
return implode('', '', $result);
}
Estoy usando la siguiente función que escribí, cuando PHP 5.3 (respectivamente date_diff ()) no está disponible:
function dateDifference($startDate, $endDate)
{
$startDate = strtotime($startDate);
$endDate = strtotime($endDate);
if ($startDate === false || $startDate < 0 || $endDate === false || $endDate < 0 || $startDate > $endDate)
return false;
$years = date(''Y'', $endDate) - date(''Y'', $startDate);
$endMonth = date(''m'', $endDate);
$startMonth = date(''m'', $startDate);
// Calculate months
$months = $endMonth - $startMonth;
if ($months <= 0) {
$months += 12;
$years--;
}
if ($years < 0)
return false;
// Calculate the days
$measure = ($months == 1) ? ''month'' : ''months'';
$days = $endDate - strtotime(''+'' . $months . '' '' . $measure, $startDate);
$days = date(''z'', $days);
return array($years, $months, $days);
}
Muy simple:
<?php
$date1 = date_create("2007-03-24");
echo "Start date: ".$date1->format("Y-m-d")."<br>";
$date2 = date_create("2009-06-26");
echo "End date: ".$date2->format("Y-m-d")."<br>";
$diff = date_diff($date1,$date2);
echo "Difference between start date and end date: ".$diff->format("%y years, %m months and %d days")."<br>";
?>
Por favor revisa el siguiente enlace para más detalles:
Tenga en cuenta que es para PHP 5.3.0 o superior.
Por un centavo, por una libra: acabo de revisar varias soluciones, todas brindando una solución compleja utilizando floor () que luego redondea hasta 26 años 12 meses y 2 días de solución, por lo que debería haber sido 25 años, 11 meses y 20 dias !!!!
Aquí está mi versión de este problema: puede que no sea elegante, no esté bien codificado, pero ofrece una mayor proximidad a una respuesta si no cuenta los años LEAP, obviamente los años bisiestos podrían codificarse en esto, pero en este caso ... como dijo alguien más, tal vez podría proporcionar esta respuesta: He incluido todas las condiciones TEST y print_r para que pueda ver con mayor claridad la construcción de los resultados: aquí va,
// establece tus fechas / variables de entrada ::
$ISOstartDate = "1987-06-22";
$ISOtodaysDate = "2013-06-22";
// Necesitamos EXPLOTAR el formato ISO yyyy-mm-dd en yyyy mm dd, de la siguiente manera:
$ yDate [] = explode (''-'', $ ISOstartDate); print_r ($ yDate);
$ zDate [] = explode (''-'', $ ISOtodaysDate); print_r ($ zDate);
// Lets Sort of the Years!
// Lets Sort out the difference in YEARS between startDate and todaysDate ::
$years = $zDate[0][0] - $yDate[0][0];
// We need to collaborate if the month = month = 0, is before or after the Years Anniversary ie 11 months 22 days or 0 months 10 days...
if ($months == 0 and $zDate[0][1] > $ydate[0][1]) {
$years = $years -1;
}
// TEST result
echo "/nCurrent years => ".$years;
// Lets Sort out the difference in MONTHS between startDate and todaysDate ::
$months = $zDate[0][1] - $yDate[0][1];
// TEST result
echo "/nCurrent months => ".$months;
// Now how many DAYS has there been - this assumes that there is NO LEAP years, so the calculation is APPROXIMATE not 100%
// Lets cross reference the startDates Month = how many days are there in each month IF m-m = 0 which is a years anniversary
// We will use a switch to check the number of days between each month so we can calculate days before and after the years anniversary
switch ($yDate[0][1]){
case 01: $monthDays = ''31''; break; // Jan
case 02: $monthDays = ''28''; break; // Feb
case 03: $monthDays = ''31''; break; // Mar
case 04: $monthDays = ''30''; break; // Apr
case 05: $monthDays = ''31''; break; // May
case 06: $monthDays = ''30''; break; // Jun
case 07: $monthDays = ''31''; break; // Jul
case 08: $monthDays = ''31''; break; // Aug
case 09: $monthDays = ''30''; break; // Sept
case 10: $monthDays = ''31''; break; // Oct
case 11: $monthDays = ''30''; break; // Nov
case 12: $monthDays = ''31''; break; // Dec
};
// TEST return
echo "/nDays in start month ".$yDate[0][1]." => ".$monthDays;
// Lets correct the problem with 0 Months - is it 11 months + days, or 0 months +days???
$days = $zDate[0][2] - $yDate[0][2] +$monthDays;
echo "/nCurrent days => ".$days."/n";
// Lets now Correct the months to being either 11 or 0 Months, depending upon being + or - the years Anniversary date
// At the same time build in error correction for Anniversary dates not being 1yr 0m 31d... see if ($days == $monthDays )
if($days < $monthDays && $months == 0)
{
$months = 11; // If Before the years anniversary date
}
else {
$months = 0; // If After the years anniversary date
$years = $years+1; // Add +1 to year
$days = $days-$monthDays; // Need to correct days to how many days after anniversary date
};
// Day correction for Anniversary dates
if ($days == $monthDays ) // if todays date = the Anniversary DATE! set days to ZERO
{
$days = 0; // days set toZERO so 1 years 0 months 0 days
};
echo "/nTherefore, the number of years/ months/ days/ /nbetween start and todays date::/n/n";
printf("%d years, %d months, %d days/n", $years, $months, $days);
El resultado final es: 26 años, 0 meses, 0 días.
Ese es el tiempo que llevo en el negocio el 22 de junio de 2013 - ¡Ay!
Una función fácil
function time_difference($time_1, $time_2, $limit = null)
{
$val_1 = new DateTime($time_1);
$val_2 = new DateTime($time_2);
$interval = $val_1->diff($val_2);
$output = array(
"year" => $interval->y,
"month" => $interval->m,
"day" => $interval->d,
"hour" => $interval->h,
"minute" => $interval->i,
"second" => $interval->s
);
$return = "";
foreach ($output AS $key => $value) {
if ($value == 1)
$return .= $value . " " . $key . " ";
elseif ($value >= 1)
$return .= $value . " " . $key . "s ";
if ($key == $limit)
return trim($return);
}
return trim($return);
}
Utilizar como
echo time_difference ($time_1, $time_2, "day");
Volverá como 2 years 8 months 2 days
siempre puede usar la siguiente función que puede devolver la edad en años y meses (es decir, 1 año 4 meses)
function getAge($dob, $age_at_date)
{
$d1 = new DateTime($dob);
$d2 = new DateTime($age_at_date);
$age = $d2->diff($d1);
$years = $age->y;
$months = $age->m;
return $years.''.''.months;
}
o si desea que la edad se calcule en la fecha actual, puede usar
function getAge($dob)
{
$d1 = new DateTime($dob);
$d2 = new DateTime(date());
$age = $d2->diff($d1);
$years = $age->y;
$months = $age->m;
return $years.''.''.months;
}
Hace algún tiempo escribí una format_date
función, ya que ofrece muchas opciones sobre cómo quieres tu fecha :
function format_date($date, $type, $seperator="-")
{
if($date)
{
$day = date("j", strtotime($date));
$month = date("n", strtotime($date));
$year = date("Y", strtotime($date));
$hour = date("H", strtotime($date));
$min = date("i", strtotime($date));
$sec = date("s", strtotime($date));
switch($type)
{
case 0: $date = date("Y".$seperator."m".$seperator."d",mktime($hour, $min, $sec, $month, $day, $year)); break;
case 1: $date = date("D, F j, Y",mktime($hour, $min, $sec, $month, $day, $year)); break;
case 2: $date = date("d".$seperator."m".$seperator."Y",mktime($hour, $min, $sec, $month, $day, $year)); break;
case 3: $date = date("d".$seperator."M".$seperator."Y",mktime($hour, $min, $sec, $month, $day, $year)); break;
case 4: $date = date("d".$seperator."M".$seperator."Y h:i A",mktime($hour, $min, $sec, $month, $day, $year)); break;
case 5: $date = date("m".$seperator."d".$seperator."Y",mktime($hour, $min, $sec, $month, $day, $year)); break;
case 6: $date = date("M",mktime($hour, $min, $sec, $month, $day, $year)); break;
case 7: $date = date("Y",mktime($hour, $min, $sec, $month, $day, $year)); break;
case 8: $date = date("j",mktime($hour, $min, $sec, $month, $day, $year)); break;
case 9: $date = date("n",mktime($hour, $min, $sec, $month, $day, $year)); break;
case 10:
$diff = abs(strtotime($date) - strtotime(date("Y-m-d h:i:s")));
$years = floor($diff / (365*60*60*24));
$months = floor(($diff - $years * 365*60*60*24) / (30*60*60*24));
$days = floor(($diff - $years * 365*60*60*24 - $months*30*60*60*24)/ (60*60*24));
$date = $years . " years, " . $months . " months, " . $days . "days";
}
}
return($date);
}
$date = ''2012.11.13'';
$dateOfReturn = ''2017.10.31'';
$substract = str_replace(''.'', ''-'', $date);
$substract2 = str_replace(''.'', ''-'', $dateOfReturn);
$date1 = $substract;
$date2 = $substract2;
$ts1 = strtotime($date1);
$ts2 = strtotime($date2);
$year1 = date(''Y'', $ts1);
$year2 = date(''Y'', $ts2);
$month1 = date(''m'', $ts1);
$month2 = date(''m'', $ts2);
echo $diff = (($year2 - $year1) * 12) + ($month2 - $month1);
$date1 = date_create(''2007-03-24'');
$date2 = date_create(''2009-06-26'');
$interval = date_diff($date1, $date2);
echo "difference : " . $interval->y . " years, " . $interval->m." months, ".$interval->d." days ";
<?php
$today = strtotime("2011-02-03 00:00:00");
$myBirthDate = strtotime("1964-10-30 00:00:00");
printf("Days since my birthday: ", ($today - $myBirthDate)/60/60/24);
?>
// If you just want to see the year difference then use this function.
// Using the logic I''ve created you may also create month and day difference
// which I did not provide here so you may have the efforts to use your brain.
// :)
$date1=''2009-01-01'';
$date2=''2010-01-01'';
echo getYearDifference ($date1,$date2);
function getYearDifference($date1=strtotime($date1),$date2=strtotime($date2)){
$year = 0;
while($date2 > $date1 = strtotime(''+1 year'', $date1)){
++$year;
}
return $year;
}