I'm making a program that needs the duration (in time_t
) of a year.
In other ways, time_t
of DD/MM/YYYY + duration = time_t
of DD/MM/YYYY+1
So it may not always be 365 days (and 29/02/2012 will become 28/02/2013)
Here's the algorithm I came with :
if YEAR is leap than
if we are before the 29th feb' than return 365+1 days
else if we are the 29th feb' than return 365-1 days
else return 365 days
else if YEAR+1 is leap than
if we are before or the 28th feb' than return 365 days
else return 365+1 days
else return 365 days
Here, a day is 60 * 60 * 24 seconds
This algorithm seems to work. But I was wondering if there were another way to do this without all theses conditions and only 2 possible return values, or just some "trick" to optimize the thing.
I tried to increment tm_year
from the struct tm
like this :
// t is the input time_t
struct tm Tm (*localtime(&t));
if (Tm.tm_mon == 2 && Tm.tm_mday == 29) --Tm.tm_mday;
++Tm.tm_year;
return mktime(&Tm) - t;
But the result isn't what I want, I got -1 hour, or -25...
I guess it's because a year is not exactly 365 * 24 * 60 * 60.
I would use Boost for this, since it already implements what you are looking for:
#include <iostream>
#include <boost/date_time/gregorian/gregorian_types.hpp>
namespace date = boost::gregorian;
int main() {
date::date_period dp(date::date(2012, 6, 4), date::date(2013, 6, 4));
long days = dp.length().days();
std::cout << "Days between dates: " << days << std::endl;
}
If you wanted more precision, then you could use posix_time
from Boost too:
namespace ptime = boost::posix_time;
...
ptime::ptime t1(date::date(2012, 6, 4), ptime::hours(0));
ptime::ptime t2(date::date(2013, 6, 4), ptime::hours(0));
ptime::time_duration td = t2 - t1;
std::cout << "Milliseconds: " << td.total_milliseconds() << std::endl;
Typically time_t
is measured in seconds. Therefore, you would just need to call to td.total_seconds()
to obtain the value that you are looking for.
if YEAR is leap than
if we are before the 29th feb' than return 365+1 days
else if we are the 29th feb' than return 365-1 days
else return 365 days
else if YEAR+1 is leap than
if we are before or the 28th feb' than return 365 days
else return 365+1 days
else return 365 days
simplifies to:
if (YEAR is leap)
if (< 29th Feb) return 365+1
if (= 29th Feb) return 365-1
else if (YEAR+1 is leap)
if (> 29th Feb) return 365+1
return 365
But why would you want to do this? It's much better to have readable code than "trick" optimizations.
As @betabandido has suggested, something like date(year+1, mon, day) - date(year, mon, day)
would be much simpler, far more readable and able to handle leap years, leap seconds and September missing 11 days.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With