
Boost : 
Subject: Re: [boost] [gsoc 2013] chrono::date
From: Howard Hinnant (howard.hinnant_at_[hidden])
Date: 20130425 23:18:16
On Apr 25, 2013, at 6:06 PM, Anurag Kalia <anurag.kalia_at_[hidden]> wrote:
> This example also proved invaluable. After tweaking it, I have a good idea now of how to use Julian Dates (+/ reasonable constant) to represent dates. Thank you!
In addition to:
typedef std::chrono::duration
<
std::int32_t, std::ratio_multiply<std::chrono::hours::period, std::ratio<24>>
> days;
which is a nonSI unit accepted for use with SI:
http://en.wikipedia.org/wiki/SI_units#NonSI_units_accepted_for_use_with_SI
One can then, taking the current definition of the civil (gregorian) calendar, create several more units which can be quite useful:
There are exactly 7 days in a week:
typedef std::chrono::duration
<
std::int32_t, std::ratio_multiply<days::period, std::ratio<7>>
> weeks;
There are exactly 146097 days in 400 years, which could rightly be called an era:
typedef std::chrono::duration
<
std::int32_t, std::ratio_multiply<days::period, std::ratio<146097>>
> eras;
There are exactly 400 years in an era:
typedef std::chrono::duration
<
std::int32_t, std::ratio_divide<eras::period, std::ratio<400>>
> years;
And there are exactly 12 months in a year:
typedef std::chrono::duration
<
std::int32_t, std::ratio_divide<years::period, std::ratio<12>>
> months;
Now the definitions of years and months must be understood to be the average length, when converted to other units. But this is not so different than days being 24 hours: this is an average length of a day.
No one is concerned that an average month is precisely 2,629,746 seconds long. However being able to say:
assert(round<months>(jul/first/2013  jan/first/2012).count() == 18);
is arguably quite useful. Many financial calculations are done by the month (e.g. loan interest), even though the unit of "month" isn't as precisely defined as say "second". But with a round function things could "just work".
template <class To, class Rep, class Period>
To
round(const std::chrono::duration<Rep, Period>& d)
{
To t0 = std::chrono::duration_cast<To>(d);
To t1 = t0;
++t1;
auto diff0 = d  t0;
auto diff1 = t1  d;
if (diff0 == diff1)
{
if (t0.count() & 1)
return t1;
return t0;
}
else if (diff0 < diff1)
return t0;
return t1;
}
I'm not positive, but I believe the latest C++14 additions would allow us to mark round with constexpr, making it that much more useful. For example we could then:
static_assert(round<months>(jul/first/2013  jan/first/2012).count() == 18, "Better be true!");
Howard
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk