Déterminer la différence entre les dates

J’essaie de trouver un moyen pour que mon programme prenne une date (comme le 2 février 2003) et montre la différence entre les deux et une autre date (comme le 2 avril 2012), à l’exclusion des années bissextiles. Jusqu’à présent, je n’ai pu déterminer si les dates sont dans le même mois, en soustrayant simplement le “jour”. Dans ce programme, j’utilise 2 ensembles de nombres entiers “mois”, “jour” et “année”. Je ne sais pas trop où aller à partir de maintenant. C’est une partie complètement optionnelle de mon travail, mais j’aimerais avoir une idée sur la façon de le faire fonctionner. Cela me semble compliqué, mais peut-être n’y a-t-il pas une formule mathématique simple à laquelle je ne pense pas?

Désolé, je n’ai pas de code préexistant pour cette partie car le rest de la tâche consiste simplement à demander à l’utilisateur de saisir des dates, puis d’append et de soustraire un jour.

Voici un code complet pour calculer la différence de date en y / m / j.

En supposant que les types de date à et de , et que les mois et les jours commencent à partir de 1 (semblable à Qt):

static int increment[12] = { 1, -2, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1 }; int daysInc = 0; if (to.day() - from.day() < 0) { int month = to.month() - 2; // -1 from zero, -1 previous month. if (month < 0) month = 11; // Previous month is December. daysInc = increment[month]; if ( (month == 1) && (to.year()%4 == 0) ) daysInc++; // Increment days for leap year. } int total1 = from.year()*360 + from.month()*30 + from.day(); int total2 = to.year()*360 + to.month()*30 + to.day(); int diff = total2 - total1; int years = diff/360; int months = (diff - years*360)/30; int days = diff - years*360 - months*30 + daysInc; // Extra calculation when we can pass one month instead of 30 days. if (from.day() == 1 && to.day() == 31) { months--; days = 30; } 

J'ai essayé cet algorithme et ça fonctionne bien. Faites-moi savoir si vous avez des difficultés à utiliser / comprendre.

En utilisant uniquement la bibliothèque standard, vous pouvez convertir une structure de date moyennement folle en nombre de secondes depuis un point zéro arbitraire; puis soustrayez et convertissez en jours:

 #include  // Make a tm structure representing this date std::tm make_tm(int year, int month, int day) { std::tm tm = {0}; tm.tm_year = year - 1900; // years count from 1900 tm.tm_mon = month - 1; // months count from January=0 tm.tm_mday = day; // days count from 1 return tm; } // Structures representing the two dates std::tm tm1 = make_tm(2012,4,2); // April 2nd, 2012 std::tm tm2 = make_tm(2003,2,2); // February 2nd, 2003 // Arithmetic time values. // On a posix system, these are seconds since 1970-01-01 00:00:00 UTC std::time_t time1 = std::mktime(&tm1); std::time_t time2 = std::mktime(&tm2); // Divide by the number of seconds in a day const int seconds_per_day = 60*60*24; std::time_t difference = (time1 - time2) / seconds_per_day; // To be fully portable, we shouldn't assume that these are Unix time; // instead, we should use "difftime" to give the difference in seconds: double portable_difference = std::difftime(time1, time2) / seconds_per_day; 

Utiliser Boost.Date_Time est un peu moins bizarre:

 #include "boost/date_time/gregorian/gregorian_types.hpp" using namespace boost::gregorian; date date1(2012, Apr, 2); date date2(2003, Feb, 2); long difference = (date1 - date2).days(); 

Cela me semble compliqué, mais peut-être n’y a-t-il pas une formule mathématique simple à laquelle je ne pense pas?

C’est certes un problème, mais il existe une formule si vous voulez faire le calcul vous-même.

Puisque vous recherchez une formule mathématique, cela vous aidera à trouver une solution à votre problème. Soit Y l’année, M le mois et D le jour. Faites ce calcul pour les deux dates.

Total = Y * 365 + M * 30 + D, puis trouvez la différence entre 2 totaux aux dates correspondantes.

En multipliant 30 par M, vous devez donner le nombre de jours de ce mois. Vous pouvez le faire avec #define value ou if loop. De la même façon, vous pouvez aussi faire une année bissextile en multipliant 366 par Y.

J’espère que cela vous aidera ….

Nouvelle réponse à une vieille question:

Algorithmes de date de bas niveau compatibles chrono

contient des formules pour convertir un sortingplet {année, mois, jour} en un compte séquentiel de jours et retour. Vous pouvez l’utiliser pour calculer le nombre de jours entre deux dates comme ceci:

 std::cout << days_from_civil(2012, 4, 2) - days_from_civil(2003, 2, 2) << '\n'; 

qui produit:

 3347 

Le document est un manuel d'utilisation, pas une bibliothèque. Il utilise C ++ 14 pour démontrer les formules. Chaque formule est accompagnée d'une description détaillée et d'une dérivation que vous ne devez lire que si vous vous souciez de savoir comment la formule fonctionne.

Les formules sont très efficaces et valables sur une très large gamme. Par exemple, en utilisant l'arithmétique 32 bits, +/- 5 millions d'années (plus que suffisant).

Le nombre de jours en série est un nombre de jours depuis (ou avant pour les valeurs négatives) le Nouvel An 1970, rendant les formules compatibles avec Unix Time et toutes les implémentations connues de std::chrono::system_clock .

L'algorithme days_from_civil n'est pas nouveau et il devrait ressembler beaucoup aux autres algorithmes permettant de faire la même chose. Mais aller dans le sens inverse, compter le nombre de jours jusqu'à un sortingplet {année, mois, jour} est plus délicat. C'est la formule documentée par civil_from_days et je n'ai pas vu d'autres formulations aussi compactes que celle-ci.

Le document comprend des exemples d’utilisations illustrant des calculs types , l’ interopérabilité std::chrono et des tests unitaires approfondis démontrant son exactitude sur plus de 1 million d’années (en utilisant un calendrier proleptique Grégorien ).

Toutes les formules et tous les logiciels sont dans le domaine public.

Je ne suis pas sûr de quelle plate-forme êtes-vous? Windows, Linux? Mais supposons que vous souhaitiez une solution indépendante de la plate-forme et que le langage utilisé soit le C ++ standard.

Si vous pouvez utiliser des bibliothèques, vous pouvez utiliser la bibliothèque Boost :: Date_Time (http://www.boost.org/doc/libs/1_49_0/doc/html/date_time.html).

Si vous ne pouvez pas utiliser les bibliothèques pour résoudre votre tâche, vous devrez trouver un terrain simple et commun. Vous pourriez peut-être convertir toutes les dates en secondes, ou les jours, les soustraire, puis les reconvertir en données. Soustraire des jours ou des mois sous forme de nombres entiers ne vous aidera pas, car cela conduira à des résultats incorrects, à moins que vous ne preniez pas en compte le rest. J’espère que cela pourra aider.

Comme l’a fait remarquer Dbranko. 🙂

Il y a un autre moyen de contourner …

  • Étant donné deux dates, prenez l’année de la date la plus proche comme année de référence .
  • Puis calcule non. de jours entre chacune des deux dates données et que 1/1 /
  • Conservez une fonction distincte indiquant le nombre de jours écoulés jusqu’à un mois donné.
  • La différence absolue de ces deux non. de jours donnera la différence entre les deux dates données.
  • De plus, n’oubliez pas de considérer les années bissextiles !

Le code:

 #‎include‬ #include typedef struct { int d, m, y; } Date; int isLeap (int y) { return (y % 4 == 0) && ( y % 100 != 0) || (y % 400 == 0); } int diff (Date d1, Date d2) //logic here! { int dd1 = 0, dd2 = 0, y, yref; //dd1 and dd2 store the no. of days between d1, d2 and the reference year yref = (d1.y < d2.y)? d1.y: d2.y; //that reference year for (y = yref; y < d1.y; y++) if (isLeap(y)) //check if there is any leap year between the reference year and d1's year (exclusive) dd1++; if (isLeap(d1.y) && d1.m > 2) dd1++; //add another day if the date is past a leap year's February dd1 += daysTill(d1.m) + d1.d + (d1.y - yref) * 365; //sum up all the tiny bits (days) for (y = yref; y < d2.y; y++) //repeat for d2 if(isLeap(y)) dd2++; if (isLeap(y) && d2.m > 2) dd2++; dd2 += daysTill(d2.m) + d2.d + (d2.y - yref) * 365; return abs(dd2 - dd1); //return the absolute difference between the two no. of days elapsed past the reference year } int daysTill (int month) //some logic here too!! { int days = 0; switch (month) { case 1: days = 0; break; case 2: days = 31; break; case 3: days = 59; break; case 4: days = 90; //number of days elapsed before April in a non-leap year break; case 5: days = 120; break; case 6: days = 151; break; case 7: days = 181; break; case 8: days = 212; break; case 9: days = 243; break; case 10:days = 273; break; case 11:days = 304; break; case 12:days = 334; break; } return days; } main() { int t; //no. of test cases Date d1, d2; //d1 is the first date, d2 is the second one! obvious, duh!? scanf ("%d", &t); while (t--) { scanf ("%d %d %d", &d1.d, &d1.m, &d1.y); scanf ("%d %d %d", &d2.d, &d2.m, &d2.y); printf ("%d\n", diff(d1, d2)); } } 

Entrée standard:

 1 23 9 1960 11 3 2015 

Sortie standard:

 19892 

Code en action: https://ideone.com/RrADFR

De meilleurs algorithmes, optimisations et modifications sont toujours les bienvenus!

Si vous avez besoin de le faire vous-même, alors une façon de le faire très facilement consiste à convertir des dates en un jour de Julien . Vous obtenez des formules sur ce lien, et à partir de la conversion, vous ne travaillez qu’avec des flottants, où chaque jour correspond à 1 unité.

Vous devriez regarder la classe DateTime .

Également la référence msdn pour la syntaxe C ++.