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 ?
-
[`std::tie`](http://en.cppreference.com/w/cpp/utility/tuple/tie) will be useful – NathanOliver Jan 20 '17 at 15:46
-
If you're checking durations, then there's really no good alternative to converting to a single date number. There are multiple standards to choose from, probably the most popular is [Unix time](https://en.wikipedia.org/wiki/Unix_time), the number of elapsed seconds since 1/1/1970. You might want to see what your available libraries support. – Mark Ransom Jan 20 '17 at 15:46
-
2Which date/time library are you using? Have you done any research into solutions? – Lightness Races in Orbit Jan 20 '17 at 15:47
-
Id depens how impelmented date. C++ many years has not standard here – Jacek Cz Jan 20 '17 at 15:47
-
@MarkRansom: If you want anything better than "number of seconds", you have a lot of work to do to make a UNIX timestamp diff useful. – Lightness Races in Orbit Jan 20 '17 at 15:47
-
@JacekCz: C++ several years has standard here :) http://en.cppreference.com/w/cpp/chrono – Lightness Races in Orbit Jan 20 '17 at 15:48
-
@LightnessRacesinOrbit I said it was the most popular, I didn't say anything as to whether it was most appropriate for this question. Which is impossible because the question doesn't have many details. – Mark Ransom Jan 20 '17 at 15:49
-
Boost has a date and time library: http://www.boost.org/doc/libs/1_63_0/doc/html/date_time.html – Francesco Montesano Jan 20 '17 at 15:49
-
@LightnessRacesinOrbit I keep forgetting about `chrono`, never had a chance to use it. That would probably make a good answer. – Mark Ransom Jan 20 '17 at 15:50
-
@LightnessRacesinOrbit Yes :) But cant see applications with it. In reality CDateTime, TDate :Qt::Something, char[8] or integer since 1970 – Jacek Cz Jan 20 '17 at 15:50
-
@JacekCz: 1970 was quite a while ago. If you want to see an application that uses modern technology (including `std::chrono`), apply for a job at my company and if you're lucky you'll get to work on one :) – Lightness Races in Orbit Jan 20 '17 at 17:32
3 Answers
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.

- 206,506
- 52
- 449
- 577
-
It _is_ a very good library. Not sure how I feel about you introducing your own library as "a very good library" without explicitly disclosing that you wrote it, though! – Lightness Races in Orbit Jan 20 '17 at 17:34
-
More people are contributing to as time goes on: https://github.com/HowardHinnant/date/graphs/contributors :-) I would have a hard time keeping it portable by myself. Yes, I am the principal author. James Beach just ported it to VS-2017 yesterday. – Howard Hinnant Jan 20 '17 at 18:09
-
Maybe a slight tweak to the opening sentence of your answer is called for :) – Lightness Races in Orbit Jan 20 '17 at 18:11
-
Thou your library from my quick glance and low knowledge is useful, but the library has to be already pre installed in visuals studio 2015 – Blackwolf23 Jan 21 '17 at 21:17
-
1@Blackwolf23: The part you asked about (comparing dates), is a single-header-only file (date.h) which needs no installation on any platform, and is known to work on VS-2015 (and VS-2013, and just recently ported to VS-2017). If you need timezone support, here are the installation instructions: https://howardhinnant.github.io/date/tz.html#Installation (includes Windows-specific instructions). – Howard Hinnant Jan 21 '17 at 21:33
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

- 8,757
- 2
- 32
- 36
-
This probably doesn't pass code review in my team these days. Also it does not account for leap seconds, to the best of my knowledge (although it should be aware of other human timing oddities). – Lightness Races in Orbit Jan 20 '17 at 17:34
-
It wouldn't pass code review with me either. As I said, it's a rough example to show the general usage and introduce him to `tm`, `mktime()`, `time_t`, et al. He's asking about measuring days elapsed. I doubt he cares to measure it to seconds, so leap seconds don't play into it. – Rob K Jan 20 '17 at 17:56
-
It will after 86400 of them ^_^ I'm curious as to why you wrote an answer recommending a solution that you would reject in your own work. Ah well. – Lightness Races in Orbit Jan 20 '17 at 18:04
-
The example code here, I would reject. Using these routines, I would not. – Rob K Jan 20 '17 at 18:39
-
Ok then to be clear it's both that would not be accepted in my team – Lightness Races in Orbit Jan 21 '17 at 00:18
-
I'm glad you don't work on my team. These routines are perfectly adequate for the use mentioned in the question. The're not just familiar, but in the standard and supported everywhere that matters. – Rob K Jan 23 '17 at 16:10
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).

- 43,454
- 1
- 47
- 90