I\'m trying to figure out a way for my program to take a date (like February 2nd, 2003) and show the difference between the two with another date (like April 2nd, 2012), exc
Using just the standard library, you can convert a moderately insane date structure into a count of seconds since an arbitrary zero point; then subtract and convert into 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 weird:
#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 like a hassle to me, but maybe there's a simple math formula I'm not thinking about?
It is indeed a hassle, but there is a formula, if you want to do the calculation yourself.
New answer for an old question:
chrono-Compatible Low-Level Date Algorithms
has formulas for converting a {year, month, day} triple to a serial count of days and back. You can use it to calculate the number of days between two dates like this:
std::cout << days_from_civil(2012, 4, 2) - days_from_civil(2003, 2, 2) << '\n';
which outputs:
3347
The paper is a how-to manual, not a library. It uses C++14 to demonstrate the formulas. Each formula comes with a detailed description and derivation, that you only have to read if you care about knowing how the formula works.
The formulas are very efficient, and valid over an extremely large range. For example using 32 bit arithmetic, +/- 5 million years (more than enough).
The serial day count is a count of days since (or prior to for negative values) New Years 1970, making the formulas compatible with Unix Time and all known implementations of std::chrono::system_clock
.
The days_from_civil algorithm is not novel, and it should look very similar to other algorithms for doing the same thing. But going the other way, from a count of days back to a {year, month, day} triple is trickier. This is the formula documented by civil_from_days and I have not seen other formulations that are as compact as this one.
The paper includes example uses showing typical computations, std::chrono interoperability, and extensive unit tests demonstrating the correctness over +/- 1 million years (using a proleptic Gregorian calendar).
All of the formulas and software are in the public domain.