Determining the difference between dates

I am trying to figure out how my program can take a date (for example, February 2, 2003) and show the difference between two with a different date (for example, April 2, 2012), excluding leap years. So far, I could only understand if the dates in that month corresponded simply by subtracting the “day”. In this program I use 2 sets of numbers "month", "day" and "year". I pretty much don't understand where to go. This is a completely optional part of my assignment, but I would like to get an idea of ​​how to make it work. It seems to me that this is a hassle, but maybe there is a simple mathematical formula that I do not think about?

Sorry, I do not have any pre-existing code for this part, because the rest of the job deals with the fact that the user enters dates, and then adds and subtracts one day.

+6
source share
8 answers

Here is the complete code for calculating the date difference in y / m / d.

Assuming that the to and from are date types and that the months and days begin with 1 (similar to 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; } 

I tried this algorithm and it works fine. Let me know if you have problems using / understanding this.

+4
source

Using only the standard library, you can convert a moderately crazy date structure to a number of seconds from an arbitrary zero point; then subtract and convert to days:

 #include <ctime> // 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; 

Using Boost.Date_Time is a little less strange:

 #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(); 

It seems to me that this is a hassle, but maybe there is a simple mathematical formula that I do not think about?

This is really a hassle, but there is a formula if you want to do the calculation yourself.

+11
source

Since you are looking for a mathematical formula, this will help you find a solution to your problem. Let Y be the year, M the month, and D the day. Make this calculation for both dates.

Total = Y * 365 + M * 30 + D, then find the difference between 2 sums of the corresponding dates.

If you multiply 30 by the value of M, you must indicate the number of days in this month. You can do this with #define value or if loop. You can do the same for a leap year by multiplying 366 by Y.

Hope this helps you ...

+7
source

New answer to old question:

chrono Related low-level date algorithms

has formulas for converting triples {year, month, day} to sequential counting of days and vice versa. You can use it to calculate the number of days between two dates, such as:

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

which outputs:

 3347 

Paper is a practical guide, not a library. It uses C ++ 14 to demonstrate formulas. Each formula contains a detailed description and conclusion, which you only need to read if you are interested in learning how this formula works.

The formulas are very effective and valid over an extremely large range. For example, using 32-bit arithmetic +/- 5 million years (more than enough).

A serial day is the number of days from (or to negative values) New Years 1970, which makes the formulas compatible with Unix Time and all known implementations of std::chrono::system_clock .

The days_from_civil algorithm days_from_civil not new, and it should be very similar to other algorithms to do the same. But, going the other way, from the number of days to {year, month, day} the three are more complicated. This is a formula documented by civil_from_days , and I have not seen other formulations that are as compact as this one.

The document provides examples of the use of typical calculations , std::chrono interoperability and extensive, demonstrating the accuracy of more than +/- 1 million years (using the proleptographic Gregorian calendar ).

All formulas and software are in the public domain.

+6
source

I'm not sure which platform are you on? Windows, Linux? But let's pretend that you would like to have a platform independent solution, and langugage is standard C ++.

If you can use libraries, you can use Boost :: Date_Time library (http://www.boost.org/doc/libs/1_49_0/doc/html/date_time.html)

If you cannot use libraries to solve your task, you will need to find a simple framework. Perhaps you could convert all dates in seconds or days by subtracting them, and then convert back to data again. Subjects of days or months as integers will not help, as this will lead to incorrect results if you do not take into account the rest. Hope this helps.

Like dbrank0, he pointed it out. :)

+2
source

There is another way ...

  • Given two dates, enter the year of the earlier date as a reference year .
  • Then calculate no. days between each of two given dates and 1/1 / <this year>
  • Keep a separate function that reports the number of days that have passed before a certain month.
  • The absolute difference between the two is not. days will give the difference between the two dates.
  • Also, be sure to consider leap years !

The code:

 #‎include‬<stdio.h> #include<math.h> 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 <i>no. of days</i> between d1, d2 and the reference year yref = (d1.y < d2.y)? d1.y: d2.y; //that <b>reference year</b> for (y = yref; y < d1.y; y++) if (isLeap(y)) //check if there is any leap year between the reference year and d1 year (exclusive) dd1++; if (isLeap(d1.y) && d1.m > 2) dd1++; //add another day if the date is past a leap year 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 <i>no. of days elapsed past the reference year</i> } 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)); } } 

Standard input:

 1 23 9 1960 11 3 2015 

Standard output:

 19892 

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

Better algorithms, optimizations and edits are always welcome!

+2
source

If you need to do this yourself, then one way to do it quite easily is to convert dates to Julian Day . You get the formulas at this link, and from the conversion you only work with floats, where every day is 1 unit.

+1
source

You should look at the DateTime class.

Also the msdn link for C ++ syntax.

0
source

Source: https://habr.com/ru/post/912288/


All Articles