J'ai deux dates du formulaire:
Start Date: 2007-03-24
End Date: 2009-06-26
Maintenant, je dois trouver la différence entre ces deux sous la forme suivante:
2 years, 3 months and 2 days
Comment puis-je faire cela en PHP?
J'ai deux dates du formulaire:
Start Date: 2007-03-24
End Date: 2009-06-26
Maintenant, je dois trouver la différence entre ces deux sous la forme suivante:
2 years, 3 months and 2 days
Comment puis-je faire cela en PHP?
Réponses:
Utilisez-le pour le code hérité (PHP <5.3). Pour une solution à jour, voir la réponse de jurka ci-dessous
Vous pouvez utiliser strtotime () pour convertir deux dates en heure unix, puis calculer le nombre de secondes entre elles. À partir de là, il est assez facile de calculer différentes périodes.
$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);
Edit: De toute évidence, la façon préférée de le faire est comme décrit par jurka ci-dessous. Mon code n'est généralement recommandé que si vous n'avez pas PHP 5.3 ou mieux.
Plusieurs personnes dans les commentaires ont souligné que le code ci-dessus n'est qu'une approximation. Je pense toujours que, dans la plupart des cas, c'est très bien, car l'utilisation d'une plage est plus pour donner une idée du temps qui s'est écoulé ou reste plutôt que pour fournir une précision - si vous voulez le faire, il suffit de sortir la date.
Malgré tout cela, j'ai décidé de répondre aux plaintes. Si vous avez vraiment besoin d'une plage exacte mais que vous n'avez pas accès à PHP 5.3, utilisez le code ci-dessous (il devrait également fonctionner en PHP 4). Il s'agit d'un port direct du code que PHP utilise en interne pour calculer les plages, à l'exception qu'il ne prend pas en compte l'heure d'été. Cela signifie qu'il est éteint d'une heure au plus, mais à part cela, il devrait être correct.
<?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)));
&
signatures.
Je suggère d'utiliser des objets DateTime et 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 ";
en savoir plus php DateTime :: diff manual
Du manuel:
Depuis PHP 5.2.2, les objets DateTime peuvent être comparés à l'aide d'opérateurs de comparaison.
$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)
$date2->format('U') - $date1->format('U')
.
La meilleure solution consiste à utiliser les objets PHP DateTime
(et DateInterval
). Chaque date est encapsulée dans un DateTime
objet, puis une différence entre les deux peut être faite:
$first_date = new DateTime("2012-11-30 17:03:30");
$second_date = new DateTime("2012-12-21 00:00:00");
L' DateTime
objet acceptera n'importe quel format strtotime()
. Si un format de date encore plus spécifique est nécessaire, DateTime::createFromFormat()
peut être utilisé pour créer leDateTime
objet.
Une fois les deux objets instanciés, vous soustrayez l'un de l'autre avec DateTime::diff()
.
$difference = $first_date->diff($second_date);
$difference
contient maintenant un DateInterval
objet avec les informations de différence. A var_dump()
ressemble à ceci:
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
Pour formater l' DateInterval
objet, nous devons vérifier chaque valeur et l'exclure si elle est 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;
}
Il ne reste plus qu'à appeler notre fonction sur l' $difference
DateInterval
objet:
echo format_interval($difference);
Et nous obtenons le résultat correct:
20 jours 6 heures 56 minutes 30 secondes
Le code complet utilisé pour atteindre l'objectif:
/**
* 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);
DateTime()
n'est pas une fonction, c'est un objet, et il est là depuis PHP 5.2. Assurez-vous que votre serveur le prend en charge.
Afficher les heures et les minutes et les secondes.
$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);
Jetez un œil au lien suivant. C'est la meilleure réponse que j'ai trouvée jusqu'à présent .. :)
function dateDiff ($d1, $d2) {
// Return the number of days between the two dates:
return round(abs(strtotime($d1) - strtotime($d2))/86400);
} // end function dateDiff
Peu importe la date antérieure ou ultérieure lorsque vous transmettez les paramètres de date. La fonction utilise la valeur absolue PHP ABS () pour toujours renvoyer un nombre positif comme le nombre de jours entre les deux dates.
Gardez à l'esprit que le nombre de jours entre les deux dates N'INCLUT PAS les deux dates. Donc, si vous recherchez le nombre de jours représentés par toutes les dates comprises entre les dates entrées, y compris, vous devrez ajouter un (1) au résultat de cette fonction.
Par exemple, la différence (telle que renvoyée par la fonction ci-dessus) entre 2013-02-09 et 2013-02-14 est 5. Mais le nombre de jours ou de dates représenté par la plage de dates 2013-02-09 - 2013-02- 14 est 6.
J'ai voté pour Jurka de réponse que c'est mon préféré, mais j'ai une version pré-php.5.3 ...
Je me suis retrouvé à travailler sur un problème similaire - c'est ainsi que je suis arrivé à cette question en premier lieu - mais j'avais juste besoin d'une différence d'heures. Mais ma fonction a aussi bien résolu celui-ci et je n'ai nulle part dans ma propre bibliothèque pour le garder où il ne sera pas perdu et oublié, alors ... j'espère que cela sera utile à quelqu'un.
/**
*
* @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;
}
Et le test:
$oDate = new DateTime();
$oDate->modify('+111402189 seconds');
var_dump($oDate);
var_dump(date_diff_array(new DateTime(), $oDate));
Et le résultat:
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
J'ai l'idée originale d' ici , que j'ai modifiée pour mes utilisations (et j'espère que ma modification s'affichera également sur cette page).
Vous pouvez très facilement supprimer les intervalles dont vous ne voulez pas (par exemple "semaine") en les supprimant du $aIntervals
tableau, ou peut-être en ajoutant un $aExclude
paramètre, ou en les filtrant simplement lorsque vous sortez la chaîne.
week
index $aIntervals
(car DateDiff
n'utilise jamais cela).
<?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);
?>
Je ne sais pas si vous utilisez un framework PHP ou non, mais beaucoup de frameworks PHP ont des bibliothèques de date / heure et des aides pour vous empêcher de réinventer la roue.
Par exemple, CodeIgniter a la timespan()
fonction. Entrez simplement deux horodatages Unix et cela générera automatiquement un résultat comme celui-ci:
1 Year, 10 Months, 2 Weeks, 5 Days, 10 Hours, 16 Minutes
echo time_diff_string('2013-05-01 00:22:35', 'now');
echo time_diff_string('2013-05-01 00:22:35', 'now', true);
4 months ago
4 months, 2 weeks, 3 days, 1 hour, 49 minutes, 15 seconds ago
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';
}
J'ai une logique simple pour cela:
<?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;
?>
Vous pouvez utiliser le
getdate()
fonction qui retourne un tableau contenant tous les éléments de la date / heure fournie:
$diff = abs($endDate - $startDate);
$my_t=getdate($diff);
print("$my_t[year] years, $my_t[month] months and $my_t[mday] days");
Si vos dates de début et de fin sont au format chaîne, utilisez
$startDate = strtotime($startDateStr);
$endDate = strtotime($endDateStr);
avant le code ci-dessus
$my_t["year"] -= 1970
pour obtenir le bon nombre d'années. Vous devez également soustraire votre différence d'heure de GMT pour obtenir les bonnes heures. Vous devez également soustraire 1 du mois et de la date.
// 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;
}
C'est ma fonction. PHP requis> = 5.3.4. Il utilise la classe DateTime. Très rapide, rapide et peut faire la différence entre deux dates ou même le soi-disant "time since".
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;
}
}
Je préfère utiliser date_create
etdate_diff
objets.
Code:
$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;
Production:
2 years, 3 months and 2 days
Pour plus d'informations, lisez le date_diff
manuel PHP
Selon le manuel
date_diff
est un alias de DateTime :: diff ()
Cela tentera de détecter si un horodatage a été donné ou non, et renverra également les dates / heures futures sous forme de valeurs négatives:
<?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;
}
Exemple d'utilisation:
<?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
Ou:
<?php
$christmas_2020 = 'December 25, 2020';
$countdown = time_diff($christmas_2020);
print_r($countdown);
"si" la date est stockée dans MySQL, je trouve plus facile de faire le calcul de la différence au niveau de la base de données ... Ensuite, en fonction des sorties Jour, Heure, Min, Sec, analyser et afficher les résultats selon le cas ...
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)
J'ai trouvé votre article sur la page suivante, qui contient un certain nombre de références pour les calculs de date et d'heure PHP .
Calculez la différence entre deux dates (et l'heure) en utilisant PHP. La page suivante fournit une gamme de méthodes différentes (7 au total) pour effectuer des calculs de date / heure à l'aide de PHP, pour déterminer la différence de temps (heures, munites), jours, mois ou années entre deux dates.
Voir PHP Date Time - 7 méthodes pour calculer la différence entre 2 dates .
Vous pouvez également utiliser le code suivant pour renvoyer la différence de date par des fractions rondes jusqu'à $ date1 = $ duedate; // attribue l'échéance echo $ date2 = date ("Ymd"); // date actuelle $ ts1 = strtotime ($ date1); $ ts2 = strtotime ($ date2); $ seconds_diff = $ ts1 - $ ts2; echo $ dateiff = ceil (($ seconds_diff / 3600) / 24); // retour en jours
Si vous utilisez la méthode de plancher de php au lieu de plafond, cela vous renverra la fraction ronde. Veuillez vérifier la différence ici, parfois si le fuseau horaire de vos serveurs de transfert est différent, le fuseau horaire du site en direct dans ce cas, vous pouvez obtenir des résultats différents, modifiez donc les conditions en conséquence.
vous pouvez toujours utiliser la fonction suivante qui peut renvoyer l'âge en années et mois (c'est-à-dire 1 an 4 mois)
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;
}
ou si vous voulez que l'âge soit calculé à la date actuelle, vous pouvez utiliser
function getAge($dob)
{
$d1 = new DateTime($dob);
$d2 = new DateTime(date());
$age = $d2->diff($d1);
$years = $age->y;
$months = $age->m;
return $years.'.'.months;
}
Pour la version php> = 5.3: Créez deux objets de date puis utilisez la date_diff()
fonction. Il renverra l' objet php DateInterval . voir la documentation
$date1=date_create("2007-03-24");
$date2=date_create("2009-06-26");
$diff=date_diff($date1,$date2);
echo $diff->format("%R%a days");
J'ai eu le même problème avec PHP 5.2 et l'ai résolu avec MySQL. Peut-être pas exactement ce que vous cherchez, mais cela fera l'affaire et renverra le nombre de jours:
$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;
Plus d'informations ici http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_datediff
Puisque tout le monde publie des exemples de code, voici une autre version.
Je voulais une fonction pour afficher les différences de quelques secondes à plusieurs années (une seule unité). Pour les périodes de plus d'un jour, je voulais qu'il se déroule à minuit (10h lundi vu de 9h mercredi il y a 2 jours, pas 1). Et pour des périodes de plus d'un mois, je voulais que le roulement se fasse le même jour du mois (y compris pour les mois 30/31 jours et les années bissextiles).
Voici ce que j'ai trouvé:
/**
* 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';
}
Il y a quelque temps, j'ai écrit une format_date
fonction car cela donne de nombreuses options sur la façon dont vous voulez votre date :
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);
}
Très 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>";
?>
Veuillez vérifier le lien suivant pour plus de détails:
Notez que c'est pour PHP 5.3.0 ou supérieur.
Une fonction simple
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);
}
Utilisez comme
echo time_difference ($time_1, $time_2, "day");
Reviendra comme 2 years 8 months 2 days
Essayez cette réponse très simple en utilisant date_diff () , elle est testée.
$date1 = date_create("2017-11-27");
$date2 = date_create("2018-12-29");
$diff=date_diff($date1,$date2);
$months = $diff->format("%m months");
$years = $diff->format("%y years");
$days = $diff->format("%d days");
echo $years .' '.$months.' '.$days;
la sortie est:
1 years 1 months 2 days
J'utilise la fonction suivante que j'ai écrite, quand PHP 5.3 (respectivement date_diff ()) n'est pas 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);
}
DateInterval
est super mais il a quelques mises en garde:
Pour surmonter cela, j'ai codé ce qui suit (amélioré par rapport à la réponse @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;
}
Il exécute deux boucles; le premier traite des intervalles relatifs (années et mois) via le forçage brut, et le second calcule les intervalles absolus supplémentaires avec une arithmétique simple (donc c'est plus rapide):
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);
}