Je pense que le retour d'un nombre de jours négatif fournit des informations pertinentes. Et vous devriez utiliser $your_date-$now, si vous voulez qu'une date future retourne un entier positif.
Tim
23
Et les secondes intercalaires? Tous les jours n'ont pas exactement 24 * 60 * 60 secondes. Ce code peut être suffisant à des fins pratiques, mais il n'est pas exact dans certains cas extrêmement rares.
Benjamin Brizzi
49
Oubliez les secondes intercalaires (non, pensez-y également), mais cela ne tient PAS compte des changements d'heure d'été! Il peut être annulé d'une journée entière au-dessus de ces frontières chaque année. Vous devez utiliser les classes DateTime.
Levi
6
@billynoah Désolé, je ne suis jamais revenu pour mettre à jour mon commentaire. Vous devez être prudent avec les fuseaux horaires d'été. Si vous comparez une date avec l'heure d'été par rapport à une date sans celle-ci, au lieu de renvoyer par exemple 7 jours, elle renvoie 6,9 jours. Prendre la parole renvoie 6 au lieu de 7.
Alex Angelico
4
Non seulement strtotime () échoue en 20 ans, mais il est inutilisable en ce moment. Les dates spécifiées par l'OP, pas l'heure. Les dates peuvent être assez anciennes. Voici une réponse plus simple: $ NumberDays = gregoriantojd ($ EndM, $ EndD, $ EndY) - gregoriantojd ($ StartM, $ StartD, $ StartY); (pour une gamme inclusive). Contrairement à la classe Datetime, Gregorian to Julian est disponible dans la version v4. La plage valide est 4714 BC à 9999 AD Méfiez-vous de l'ordre des paramètres funky (comme vous avez besoin de cet avertissement pour php).
Guy Gordon
524
Si vous utilisez PHP 5.3 >, c'est de loin le moyen le plus précis de calculer la différence:
Notez que comme nous parlons d'intervalles de temps et non de points spécifiques dans le temps, la syntaxe de format est différente de la syntaxe date () et strftime (). La syntaxe d'intervalle de temps peut être trouvée ici: php.net/manual/en/dateinterval.format.php
Andrew
1
ou dans mon cas, le nombre de jours entre est $ date2-> diff ($ date1) -> format ("% a") - 1
xeo
13
Gardez à l'esprit que si vous avez des moments dans vos dates, cela ne fonctionnera pas comme vous pouvez vous y attendre. Par exemple, si vous avez un intervalle de 23h30 ... et qu'ils sont sur des jours différents, la différence sera de 0.
Layke
20
Si vous avez besoin d'un nombre relatif de jours (négatif quand $date1est antérieur à $date2), utilisez-le à la $diff = $date2->diff($date1)->format("%r%a");place.
Socce
1
Quel est le format de la date en DateTime("2010-07-06")?, Est-ce Y-m-dou Y-d-m?, Quel est le format du DateTimeparamètre. lequel est le jour?
Oui, cela semble mieux que la réponse acceptée, ce qui ne fonctionne pas dans certains cas. Comme: $ from = '2014-03-01'; $ à = '2014-03-31';
MBozic
1
Je suis d'accord, donc facile à suivre et fonctionne très bien !!! N'oubliez pas d'utiliser la fonction date_default_timezone_set () ou cela vous donnera des résultats étranges basés sur l'heure UTC.
zeckdude
2
Cette fonction a échoué à 0 des 14603 tests entre 1980 et 2020.
LSerni
128
Convertissez vos dates en horodatages Unix, puis soustrayez-les les unes des autres. Cela vous donnera la différence en secondes, que vous divisez par 86400 (quantité de secondes dans une journée) pour vous donner une quantité approximative de jours dans cette plage.
Si vos dates sont au format 25.1.2010, 01/25/2010ou 2010-01-25, vous pouvez utiliser la strtotimefonction:
L'utilisation ceilarrondit le nombre de jours jusqu'au jour complet suivant. Utilisez-le à la floorplace si vous souhaitez obtenir le nombre de jours entiers entre ces deux dates.
Si vos dates sont déjà au format d'horodatage Unix, vous pouvez ignorer la conversion et simplement faire la $days_betweenpartie. Pour les formats de date plus exotiques, vous devrez peut-être effectuer une analyse personnalisée pour bien faire les choses.
Permettez-moi de préciser: disons que ce matin à 3 heures du matin, presque toute l'Europe a reculé d'une heure. Cela signifie qu'aujourd'hui dispose de 3600 secondes supplémentaires, et cela devrait se refléter dans les horodatages UNIX. Si c'est le cas, cela signifie qu'aujourd'hui comptera pour deux jours avec la méthode ci-dessus pour calculer le nombre de jours. Et je ne commence même pas à propos des secondes intercalaires puisque ni PHP ni UNIX ne semblent en tenir compte (ce qui est en fait compréhensible par l'OMI). TL; DR: tous les jours ne durent pas 86 400 secondes .
toon81
2
@ toon81 Il n'y a PAS 3600 secondes de plus pour cette date. Il ne se passe rien du tout à l'horodatage UNIX lorsque vous allez vers ou depuis l'heure d'été.
nickdnk
1
Si rien n'arrive à l'horodatage UNIX, alors vous êtes d'accord avec moi: la différence entre l'horodatage UNIX à 13 h $dayet l'horodatage UNIX à 13 h $day+1n'est pas toujours de 86400 secondes dans les fuseaux horaires qui respectent l'heure d'été. Cela peut prendre 23 ou 25 heures de secondes au lieu de 24 heures.
toon81
112
TL; DR n'utilisent pas d' horodatage UNIX. Ne pas utilisertime() . Si vous le faites, soyez prêt si sa fiabilité à 98,0825% vous fait défaut. Utilisez DateTime (ou Carbon).
La bonne réponse est celle donnée par Saksham Gupta (les autres réponses sont également correctes):
/**
* 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');}
Avec une mise en garde: le «% a» semble indiquer le nombre absolu de jours. Si vous le voulez comme un entier signé, c'est-à-dire négatif lorsque la deuxième date est antérieure à la première, vous devez utiliser le préfixe '% r' (c'est-à-dire format('%r%a')).
Si vous devez vraiment utiliser des horodatages UNIX, définissez le fuseau horaire sur GMT pour éviter la plupart des pièges détaillés ci-dessous.
Réponse longue: pourquoi la division par 24 * 60 * 60 (aka 86400) n'est pas sûre
La plupart des réponses utilisant les horodatages UNIX (et 86400 pour les convertir en jours) émettent deux hypothèses qui, mises ensemble, peuvent conduire à des scénarios avec des résultats incorrects et des bogues subtils qui peuvent être difficiles à suivre, et se produisent même des jours, des semaines ou des mois après un déploiement réussi. Ce n'est pas que la solution ne fonctionne pas - elle fonctionne. Aujourd'hui. Mais cela pourrait cesser de fonctionner demain.
La première erreur n'est pas de considérer que lorsqu'on lui demande "Combien de jours se sont écoulés depuis hier?", Un ordinateur peut répondre à zéro si entre le présent et l'instant indiqué par "hier" moins d' une journée entière s'est écoulée.
Généralement, lors de la conversion d'un «jour» en horodatage UNIX, ce qui est obtenu est l'horodatage pour minuit de ce jour particulier.
Ainsi, entre la nuit du 1er octobre et le 15 octobre, quinze jours se sont écoulés. Mais entre 13h00 du 1er octobre et 14h55 du 15 octobre, quinze jours moins 5 minutes se sont écoulés, et la plupart des solutions utilisant floor()ou faisant une conversion implicite d'entiers rapporteront un jour de moins que prévu .
Donc, "il y a combien de jours Ymd H: i: s"? donnera la mauvaise réponse .
La deuxième erreur équivaut à un jour à 86400 secondes. C'est presque toujours vrai - cela arrive assez souvent pour ignorer les moments où cela ne se produit pas. Mais la distance en secondes entre deux minuit consécutifs n'est sûrement pas de 86400 au moins deux fois par an lorsque l'heure d'été entre en jeu. La comparaison de deux dates à travers une limite d'heure d'été donnera la mauvaise réponse.
Donc, même si vous utilisez le "hack" de forcer tous les horodatages de date à une heure fixe, disons minuit (cela est également implicitement fait par divers langages et frameworks lorsque vous spécifiez uniquement jour-mois-année et pas également heure-minute-seconde; même chose avec le type DATE dans les bases de données telles que MySQL), la formule largement utilisée
retournera, disons, 17 lorsque DATE1 et DATE2 sont dans le même segment DST de l'année; mais il peut renvoyer 17,042, et pire encore, 16,958. L'utilisation de floor () ou de toute troncature implicite en entier convertira alors ce qui aurait dû être un 17 en 16. Dans d'autres circonstances, des expressions comme "$ days> 17" truerenverront pour 17.042 même si cela indique que le nombre de jours écoulés a 18 ans.
Et les choses deviennent encore plus laides car un tel code n'est pas portable sur toutes les plates-formes, car certaines d'entre elles peuvent appliquer des secondes intercalaires et d'autres pas . Sur ces plates-formes qui le font , la différence entre deux dates ne sera pas 86400 mais 86401, ou peut-être 86399. Ainsi, le code qui a fonctionné en mai et qui a effectivement passé tous les tests se cassera en juin prochain lorsque 12,99999 jours sont considérés comme 12 jours au lieu de 13. Deux dates qui a fonctionné en 2015 ne fonctionnera pas en 2017 - les mêmes dates, et aucune des deux années n'est bissextile. Mais entre le 01/03/2018 et le 01/03/2017, sur ces plateformes qui s'en soucient, 366 jours se seront écoulés au lieu de 365, faisant de 2018 une année bissextile (ce qui n'est pas le cas).
Donc, si vous voulez vraiment utiliser les horodatages UNIX:
utiliser la round()fonction à bon escient, non floor().
comme alternative, ne calculez pas les différences entre D1-M1-YYY1 et D2-M2-YYY2. Ces dates seront réellement considérées comme D1-M1-YYY1 00:00:00 et D2-M2-YYY2 00:00:00. Convertissez plutôt entre D1-M1-YYY1 22:30:00 et D2-M2-YYY2 04:30:00. Vous obtiendrez toujours un reste d'une vingtaine d'heures. Cela peut devenir vingt et une heures ou dix-neuf, et peut-être dix-huit heures, cinquante-neuf minutes trente-six secondes. Peu importe. C'est une grande marge qui restera là et restera positive dans un avenir prévisible. Vous pouvez maintenant le tronquer floor()en toute sécurité.
La bonne solution, cependant, pour éviter les constantes magiques, les arrondis et les dettes de maintenance, consiste à
utiliser une bibliothèque de temps (Datetime, Carbon, peu importe); ne roule pas toi-même
écrire des cas de test complets en utilisant des choix de date vraiment mauvais - au-delà des limites de l'heure d'été, des années bissextiles, des secondes bissextiles, etc., ainsi que des dates courantes. Idéalement (les appels à datetime sont rapides !) Génèrent quatre années entières (et un jour) de dates en les assemblant à partir de chaînes, séquentiellement, et garantissent que la différence entre le premier jour et le jour testé augmente régulièrement de un. Cela garantira que si quelque chose change dans les routines de bas niveau et les corrections de secondes intercalaires, essayez de faire des ravages, au moins vous le saurez .
exécutez ces tests régulièrement avec le reste de la suite de tests. Ils sont une question de millisecondes et peuvent vous sauver littéralement des heures de grattage de tête.
Quelle que soit votre solution, testez-la!
La fonction funcdiffci-dessous implémente l'une des solutions (en l'occurrence, la solution acceptée) dans un scénario du monde réel.
<?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 September...");
$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";
Le résultat est,
Thisfunction failed 280of its 14603 tests
Histoire d'horreur: le coût du «gain de temps»
C'est arrivé il y a quelques mois. Un ingénieux programmeur a décidé d'économiser plusieurs microsecondes sur un calcul qui prenait environ trente secondes au maximum, en branchant le fameux code "(MidnightOfDateB-MidnightOfDateA) / 86400" à plusieurs endroits. C'était une optimisation si évidente qu'il ne l'a même pas documentée, et l'optimisation a passé les tests d'intégration et s'est cachée dans le code pendant plusieurs mois, tout cela sans être remarqué.
Cela s'est produit dans un programme qui calcule les salaires de plusieurs vendeurs les plus vendus, dont le moins a une influence beaucoup plus terrible qu'une humble équipe de programmeurs de cinq personnes réunies. Il y a un jour, il y a quelques mois, pour des raisons qui importent peu, le bug a frappé - et certains de ces gars ont été lésés une journée entière de grosses commissions. Ils n'étaient certainement pas amusés.
Infiniment pire, ils ont perdu la confiance (déjà très faible) qu'ils avaient dans le programme qui n'était pas conçu pour les manipuler subrepticement, et ont prétendu - et obtenu - une revue de code complète et détaillée avec des cas de test exécutés et commentés en termes simples (plus beaucoup) de traitement sur tapis rouge dans les semaines suivantes).
Que puis-je dire: du côté positif, nous nous sommes débarrassés de beaucoup de dettes techniques et avons été en mesure de réécrire et de remanier plusieurs morceaux d'un gâchis de spaghetti qui ont fait écho à une infestation de COBOL dans les années 90. Le programme fonctionne sans aucun doute mieux maintenant, et il y a beaucoup plus d'informations de débogage pour se concentrer rapidement lorsque quelque chose semble louche. J'estime que cette dernière chose permettra peut-être d'économiser un ou deux jours-homme par mois dans un avenir prévisible.
Du côté négatif, l'ensemble du brouhaha a coûté à l'entreprise environ 200 000 € à l'avance - plus le visage, plus sans aucun doute un certain pouvoir de négociation (et, par conséquent, encore plus d'argent).
Le gars responsable de "l'optimisation" avait changé d'emploi il y a un an, avant la catastrophe, mais il y avait toujours des discussions pour le poursuivre en dommages et intérêts. Et cela ne s'est pas bien passé avec les échelons supérieurs que c'était "la faute du dernier gars" - cela ressemblait à une configuration pour que nous puissions résoudre le problème, et à la fin, nous sommes toujours dans la niche. et l'un des membres de l'équipe prévoit de quitter.
Quatre-vingt-dix-neuf fois sur cent, le "hack 86400" fonctionnera parfaitement. (Par exemple, en PHP, strtotime()ignorera l'heure d'été et signalera qu'entre le milieu du dernier samedi d'octobre et celui du lundi suivant, exactement 2 * 24 * 60 * 60 secondes se sont écoulées, même si ce n'est manifestement pas vrai ... et deux torts feront heureusement un bien).
Mesdames et Messieurs, ce fut un cas où cela n'a pas été le cas. Comme avec les airbags et les ceintures de sécurité, vous n'aurez peut-être jamais vraiment besoin de la complexité (et de la facilité d'utilisation) de DateTimeou Carbon. Mais le jour où vous pourriez (ou le jour où vous devrez prouver que vous y avez pensé) viendra comme un voleur dans la nuit. Soyez prêt.
Quand j'ai vu ces réponses, j'ai pensé que j'étais stupide et fou parce que j'utilise toujours DateTime, mais vous m'avez fait comprendre que l'utilisation de DateTime est la bonne façon. Merci
Syncro
Hé, tout le monde ici, sur SO, est arrivé ici en cherchant dans google days between two days in phpou similaire, juste parce que la vie est trop courte pour tout écrire vous-même.
Denis Matafonov
1
explication détaillée. + 1
Anant Singh --- Alive to Die
1
Parfois, je souhaite que nous puissions privilégier les réponses au lieu de la question.
C'est une bonne façon procédurale de le faire en utilisant la classe DateTime. Il ne manque qu'une utilisation claire de l'objet intervalle ( $diffvariable dans ce cas). Quelque chose comme if ($diff->days > 30) { [doyourstuff]; }
Très vieux commentaire ci-dessus, mais il est incorrect. StackOverflow ne vous permet de répondre à votre question (même lorsque vous posez votre question). Répondre à la question vous-même après que quelqu'un a déjà publié la même solution est cependant considéré comme impoli.
Maarten Bodewes
Cette fonction a échoué 560 de ses 14603 tests entre 1980 et 2020.
LSerni
10
Eh bien, la réponse sélectionnée n'est pas la plus correcte car elle échouera en dehors de l'UTC. Selon le fuseau horaire ( liste ), il pourrait y avoir des ajustements de temps créant des jours "sans" 24 heures, ce qui entraînera l'échec du calcul (60 * 60 * 24).
En voici un exemple:
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**
La bonne solution sera donc d'utiliser DateTime
date_default_timezone_set('europe/lisbon');
$date1 =newDateTime("2016-03-27");
$date2 =newDateTime("2016-03-29");
echo $date2->diff($date1)->format("%a");^-- the output will be **2**
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 ";
Avec les questions plus anciennes qui ont des réponses existantes, il est utile d'expliquer quel nouvel aspect votre réponse apporte à la question. S'il y a lieu, il est également utile de reconnaître tout changement qui pourrait s'être produit depuis que la question a été posée.
// 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";
Bienvenue chez SO! Lorsque vous répondez à un message avec juste du code, veuillez l'expliquer un peu. Le code que vous lui apportez est en cours de calcul entre le 2019-11-10 et 2019-11-25. Il ne répond donc pas à la question. C’est pourquoi il est préférable d’expliquer votre PDV mieux que d’obtenir un vote négatif.
David García Bodego
0
Si vous utilisez 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]);
En général, j'utilise 'DateTime' pour trouver des jours entre 2 dates. Mais si pour une raison quelconque, la configuration de certains serveurs n'a pas activé 'DateTime', il utilisera un calcul simple (mais pas sûr) avec 'strtotime ()'.
(new DateTime("2010-01-11"))->diff(new DateTime("2019-08-19"))->days;
Réponses:
la source
$your_date-$now
, si vous voulez qu'une date future retourne un entier positif.Si vous utilisez
PHP 5.3 >
, c'est de loin le moyen le plus précis de calculer la différence:la source
$date1
est antérieur à$date2
), utilisez-le à la$diff = $date2->diff($date1)->format("%r%a");
place.DateTime("2010-07-06")
?, Est-ceY-m-d
ouY-d-m
?, Quel est le format duDateTime
paramètre. lequel est le jour?Depuis PHP version 5.3 et plus, de nouvelles fonctions date / heure ont été ajoutées pour faire la différence:
Résultat comme ci-dessous:
J'espère que cela aide !
la source
Convertissez vos dates en horodatages Unix, puis soustrayez-les les unes des autres. Cela vous donnera la différence en secondes, que vous divisez par 86400 (quantité de secondes dans une journée) pour vous donner une quantité approximative de jours dans cette plage.
Si vos dates sont au format
25.1.2010
,01/25/2010
ou2010-01-25
, vous pouvez utiliser lastrtotime
fonction:L'utilisation
ceil
arrondit le nombre de jours jusqu'au jour complet suivant. Utilisez-le à lafloor
place si vous souhaitez obtenir le nombre de jours entiers entre ces deux dates.Si vos dates sont déjà au format d'horodatage Unix, vous pouvez ignorer la conversion et simplement faire la
$days_between
partie. Pour les formats de date plus exotiques, vous devrez peut-être effectuer une analyse personnalisée pour bien faire les choses.la source
$day
et l'horodatage UNIX à 13 h$day+1
n'est pas toujours de 86400 secondes dans les fuseaux horaires qui respectent l'heure d'été. Cela peut prendre 23 ou 25 heures de secondes au lieu de 24 heures.TL; DR n'utilisent pas d' horodatage UNIX. Ne pas utiliser
time()
. Si vous le faites, soyez prêt si sa fiabilité à 98,0825% vous fait défaut. Utilisez DateTime (ou Carbon).La bonne réponse est celle donnée par Saksham Gupta (les autres réponses sont également correctes):
Ou de manière procédurale en une ligne:
Avec une mise en garde: le «% a» semble indiquer le nombre absolu de jours. Si vous le voulez comme un entier signé, c'est-à-dire négatif lorsque la deuxième date est antérieure à la première, vous devez utiliser le préfixe '% r' (c'est-à-dire
format('%r%a')
).Si vous devez vraiment utiliser des horodatages UNIX, définissez le fuseau horaire sur GMT pour éviter la plupart des pièges détaillés ci-dessous.
Réponse longue: pourquoi la division par 24 * 60 * 60 (aka 86400) n'est pas sûre
La plupart des réponses utilisant les horodatages UNIX (et 86400 pour les convertir en jours) émettent deux hypothèses qui, mises ensemble, peuvent conduire à des scénarios avec des résultats incorrects et des bogues subtils qui peuvent être difficiles à suivre, et se produisent même des jours, des semaines ou des mois après un déploiement réussi. Ce n'est pas que la solution ne fonctionne pas - elle fonctionne. Aujourd'hui. Mais cela pourrait cesser de fonctionner demain.
La première erreur n'est pas de considérer que lorsqu'on lui demande "Combien de jours se sont écoulés depuis hier?", Un ordinateur peut répondre à zéro si entre le présent et l'instant indiqué par "hier" moins d' une journée entière s'est écoulée.
Généralement, lors de la conversion d'un «jour» en horodatage UNIX, ce qui est obtenu est l'horodatage pour minuit de ce jour particulier.
Ainsi, entre la nuit du 1er octobre et le 15 octobre, quinze jours se sont écoulés. Mais entre 13h00 du 1er octobre et 14h55 du 15 octobre, quinze jours moins 5 minutes se sont écoulés, et la plupart des solutions utilisant
floor()
ou faisant une conversion implicite d'entiers rapporteront un jour de moins que prévu .Donc, "il y a combien de jours Ymd H: i: s"? donnera la mauvaise réponse .
La deuxième erreur équivaut à un jour à 86400 secondes. C'est presque toujours vrai - cela arrive assez souvent pour ignorer les moments où cela ne se produit pas. Mais la distance en secondes entre deux minuit consécutifs n'est sûrement pas de 86400 au moins deux fois par an lorsque l'heure d'été entre en jeu. La comparaison de deux dates à travers une limite d'heure d'été donnera la mauvaise réponse.
Donc, même si vous utilisez le "hack" de forcer tous les horodatages de date à une heure fixe, disons minuit (cela est également implicitement fait par divers langages et frameworks lorsque vous spécifiez uniquement jour-mois-année et pas également heure-minute-seconde; même chose avec le type DATE dans les bases de données telles que MySQL), la formule largement utilisée
ou
retournera, disons, 17 lorsque DATE1 et DATE2 sont dans le même segment DST de l'année; mais il peut renvoyer 17,042, et pire encore, 16,958. L'utilisation de floor () ou de toute troncature implicite en entier convertira alors ce qui aurait dû être un 17 en 16. Dans d'autres circonstances, des expressions comme "$ days> 17"
true
renverront pour 17.042 même si cela indique que le nombre de jours écoulés a 18 ans.Et les choses deviennent encore plus laides car un tel code n'est pas portable sur toutes les plates-formes, car certaines d'entre elles peuvent appliquer des secondes intercalaires et d'autres pas . Sur ces plates-formes qui le font , la différence entre deux dates ne sera pas 86400 mais 86401, ou peut-être 86399. Ainsi, le code qui a fonctionné en mai et qui a effectivement passé tous les tests se cassera en juin prochain lorsque 12,99999 jours sont considérés comme 12 jours au lieu de 13. Deux dates qui a fonctionné en 2015 ne fonctionnera pas en 2017 - les mêmes dates, et aucune des deux années n'est bissextile. Mais entre le 01/03/2018 et le 01/03/2017, sur ces plateformes qui s'en soucient, 366 jours se seront écoulés au lieu de 365, faisant de 2018 une année bissextile (ce qui n'est pas le cas).
Donc, si vous voulez vraiment utiliser les horodatages UNIX:
utiliser la
round()
fonction à bon escient, nonfloor()
.comme alternative, ne calculez pas les différences entre D1-M1-YYY1 et D2-M2-YYY2. Ces dates seront réellement considérées comme D1-M1-YYY1 00:00:00 et D2-M2-YYY2 00:00:00. Convertissez plutôt entre D1-M1-YYY1 22:30:00 et D2-M2-YYY2 04:30:00. Vous obtiendrez toujours un reste d'une vingtaine d'heures. Cela peut devenir vingt et une heures ou dix-neuf, et peut-être dix-huit heures, cinquante-neuf minutes trente-six secondes. Peu importe. C'est une grande marge qui restera là et restera positive dans un avenir prévisible. Vous pouvez maintenant le tronquer
floor()
en toute sécurité.La bonne solution, cependant, pour éviter les constantes magiques, les arrondis et les dettes de maintenance, consiste à
utiliser une bibliothèque de temps (Datetime, Carbon, peu importe); ne roule pas toi-même
écrire des cas de test complets en utilisant des choix de date vraiment mauvais - au-delà des limites de l'heure d'été, des années bissextiles, des secondes bissextiles, etc., ainsi que des dates courantes. Idéalement (les appels à datetime sont rapides !) Génèrent quatre années entières (et un jour) de dates en les assemblant à partir de chaînes, séquentiellement, et garantissent que la différence entre le premier jour et le jour testé augmente régulièrement de un. Cela garantira que si quelque chose change dans les routines de bas niveau et les corrections de secondes intercalaires, essayez de faire des ravages, au moins vous le saurez .
exécutez ces tests régulièrement avec le reste de la suite de tests. Ils sont une question de millisecondes et peuvent vous sauver littéralement des heures de grattage de tête.
Quelle que soit votre solution, testez-la!
La fonction
funcdiff
ci-dessous implémente l'une des solutions (en l'occurrence, la solution acceptée) dans un scénario du monde réel.Le résultat est,
Histoire d'horreur: le coût du «gain de temps»
C'est arrivé il y a quelques mois. Un ingénieux programmeur a décidé d'économiser plusieurs microsecondes sur un calcul qui prenait environ trente secondes au maximum, en branchant le fameux code "(MidnightOfDateB-MidnightOfDateA) / 86400" à plusieurs endroits. C'était une optimisation si évidente qu'il ne l'a même pas documentée, et l'optimisation a passé les tests d'intégration et s'est cachée dans le code pendant plusieurs mois, tout cela sans être remarqué.
Cela s'est produit dans un programme qui calcule les salaires de plusieurs vendeurs les plus vendus, dont le moins a une influence beaucoup plus terrible qu'une humble équipe de programmeurs de cinq personnes réunies. Il y a un jour, il y a quelques mois, pour des raisons qui importent peu, le bug a frappé - et certains de ces gars ont été lésés une journée entière de grosses commissions. Ils n'étaient certainement pas amusés.
Infiniment pire, ils ont perdu la confiance (déjà très faible) qu'ils avaient dans le programme qui n'était pas conçu pour les manipuler subrepticement, et ont prétendu - et obtenu - une revue de code complète et détaillée avec des cas de test exécutés et commentés en termes simples (plus beaucoup) de traitement sur tapis rouge dans les semaines suivantes).
Que puis-je dire: du côté positif, nous nous sommes débarrassés de beaucoup de dettes techniques et avons été en mesure de réécrire et de remanier plusieurs morceaux d'un gâchis de spaghetti qui ont fait écho à une infestation de COBOL dans les années 90. Le programme fonctionne sans aucun doute mieux maintenant, et il y a beaucoup plus d'informations de débogage pour se concentrer rapidement lorsque quelque chose semble louche. J'estime que cette dernière chose permettra peut-être d'économiser un ou deux jours-homme par mois dans un avenir prévisible.
Du côté négatif, l'ensemble du brouhaha a coûté à l'entreprise environ 200 000 € à l'avance - plus le visage, plus sans aucun doute un certain pouvoir de négociation (et, par conséquent, encore plus d'argent).
Le gars responsable de "l'optimisation" avait changé d'emploi il y a un an, avant la catastrophe, mais il y avait toujours des discussions pour le poursuivre en dommages et intérêts. Et cela ne s'est pas bien passé avec les échelons supérieurs que c'était "la faute du dernier gars" - cela ressemblait à une configuration pour que nous puissions résoudre le problème, et à la fin, nous sommes toujours dans la niche. et l'un des membres de l'équipe prévoit de quitter.
Quatre-vingt-dix-neuf fois sur cent, le "hack 86400" fonctionnera parfaitement. (Par exemple, en PHP,
strtotime()
ignorera l'heure d'été et signalera qu'entre le milieu du dernier samedi d'octobre et celui du lundi suivant, exactement 2 * 24 * 60 * 60 secondes se sont écoulées, même si ce n'est manifestement pas vrai ... et deux torts feront heureusement un bien).Mesdames et Messieurs, ce fut un cas où cela n'a pas été le cas. Comme avec les airbags et les ceintures de sécurité, vous n'aurez peut-être jamais vraiment besoin de la complexité (et de la facilité d'utilisation) de
DateTime
ouCarbon
. Mais le jour où vous pourriez (ou le jour où vous devrez prouver que vous y avez pensé) viendra comme un voleur dans la nuit. Soyez prêt.la source
days between two days in php
ou similaire, juste parce que la vie est trop courte pour tout écrire vous-même.Date_diff facile à utiliser
la source
$diff
variable dans ce cas). Quelque chose commeif ($diff->days > 30) { [doyourstuff]; }
Style orienté objet:
Style procédural:
la source
Utilisé ceci :)
Maintenant ça marche
la source
Eh bien, la réponse sélectionnée n'est pas la plus correcte car elle échouera en dehors de l'UTC. Selon le fuseau horaire ( liste ), il pourrait y avoir des ajustements de temps créant des jours "sans" 24 heures, ce qui entraînera l'échec du calcul (60 * 60 * 24).
En voici un exemple:
La bonne solution sera donc d'utiliser DateTime
la source
Calculez la différence entre deux dates:
Sortie: +272 jours
La fonction date_diff () renvoie la différence entre deux objets DateTime.
la source
la source
J'utilise Carbon dans mes projets de compositeur à cette fin et à des fins similaires.
Ce serait aussi simple que ça:
la source
Vous pouvez trouver des dates simplement en
la source
et, si nécessaire:
la source
Si vous avez les heures en secondes (horodatage IE unix), vous pouvez simplement soustraire les heures et diviser par 86400 (secondes par jour)
la source
la source
Vous pouvez essayer le code ci-dessous:
la source
la source
Si vous voulez faire écho tous les jours entre la date de début et la date de fin, j'ai trouvé ceci:
la source
Le moyen le plus simple de trouver la différence de jours entre deux dates
la source
la source
Voici ma version améliorée qui montre 1 an (s) 2 mois (s) 25 jour (s) si le 2ème paramètre est passé.
la source
la source
utilisé le code ci-dessus très simple. Merci.
la source
la source
Utilisation de cette fonction simple. Déclarer la fonction
et appelez cette fonction comme ça où vous voulez
la source
la source
Si vous utilisez MySql
}
}
la source
Essayez d'utiliser Carbon
Vous pouvez également utiliser
pour créer un objet de date Carbon en utilisant une chaîne d'horodatage donnée.
la source
En regardant toutes les réponses je compose la fonction universelle ce qui fonctionne sur toutes les versions PHP.
En général, j'utilise 'DateTime' pour trouver des jours entre 2 dates. Mais si pour une raison quelconque, la configuration de certains serveurs n'a pas activé 'DateTime', il utilisera un calcul simple (mais pas sûr) avec 'strtotime ()'.
la source