Reputation: 93
Whats the best way to compare dates in c++ which are made into a structure that has a day,month and year variable i.e how to check that 30 days have passed since a event and so on. I personally found that when comparing 2 dates in the same year I make both dates into "days-dates" using a array that holds the day count of all the months of the year and then convert the dates into days and do the calculations I need. Is there a easier way to compare the dates ?
Upvotes: 1
Views: 3410
Reputation: 218720
Here is a very good C++11/14 library for handling dates1. It allows you to have {year, month, day}
structures (called date::year_month_day
), and {count-of-days}
structures (called sys_days
). It also allows easy and efficient conversions between these two structures. And naturally there are comparison operators.
The entire library is essentially an extension of <chrono>
into calendar types.
Video introduction found here:
https://www.youtube.com/watch?v=tzyGjOm8AKo
Here is a detailed explanation of the underlying algorithms to convert between the {year, month, day}
structure and the {count-of-days}
structure:
http://howardhinnant.github.io/date_algorithms.html
Here are some date creation and comparison examples for both field (year_month_day
) and serial (sys_days
) data structures:
#include "date.h"
int
main()
{
using namespace date::literals;
// create and compare {year, month, day} structures
constexpr auto ymd1 = 2017_y/jan/21;
constexpr auto ymd2 = ymd1 + date::months{15};
static_assert(ymd2 > ymd1, "ymd2 is 15 months after ymd1");
static_assert(ymd2 == 2018_y/apr/21, "ymd2 is 2018-04-21");
// create and compare {count_of_days} structures
constexpr date::sys_days sd2 = ymd2;
static_assert(sd2 == ymd2, "sd2 is the same day as ymd2");
static_assert(sd2.time_since_epoch().count() == 17642, "sd2 is day 17642");
constexpr date::sys_days sd1 = sd2 - date::days{465};
static_assert(sd1 < sd2, "sd1 is 465 days before sd2");
static_assert(sd1.time_since_epoch().count() == 17177, "sd1 is day 17177");
static_assert(sd1 == 2017_y/jan/11, "sd1 is 2017-01-11");
}
The constexpr
/ static_assert
requires a fully conforming C++14 compiler. For C++11, remove the constexpr
and change static_assert
to assert
(and eliminate the static_assert
message).
date::sys_days
is a typedef for the chrono::time_point
:
time_point<system_clock, duration<int, ratio<86400>>
The above example code requires only "date.h"
, and no other C++ source files (no installation). There is also available a timezone library at this same github location, but that does require some installation.
1 I am the principal author of this library.
Upvotes: 3
Reputation: 44238
If you need to implement it yourself then simplest way is to keep date as a single integer - Julian day As you can see on the article calculation from month/day/year into Julian day and back is pretty trivial (from computer perspective of course). When you keep dates as a single number calculate difference in days or compare them is trivial. Or if you say that it is already implemented as a structure you can convert your dates into Julian day on the fly (or keep mutable field to cache that value).
Upvotes: 1
Reputation: 8926
For what you describe, the standard C style routines are probably going to work best: http://en.cppreference.com/w/cpp/chrono/c
Here is a rough example using C style coding
#include <ctime>
const int SECONDS_PER_DAY = 24 * 60 * 60;
tm day1;
memset( &day1, 0, sizeof(day1) );
day1.tm_year = 2016 - 1900; // tm_year is the years since 1900
// so to represent 2016, the value is 116.
day1.tm_mon = 0;
day1.tm_mday = 20;
time_t day1a = mktime( &day1 );
tm day2;
memset( &day2, 0, sizeof(day2) );
day1.tm_year = 2008 - 1900;
day1.tm_mon = 0;
day1.tm_mday = 20;
time_t day2a = mktime( &day2 );
double day_delta = difftime( day1, day2 ); // returns number of seconds
double days_past = (day_delta / SECONDS_PER_DAY)
This is standard and will work on everywhere.
N.B. the POSIX standard defines time_t
as an integral type
Upvotes: 1