Boost logo

Boost :

Subject: Re: [boost] [gsoc 2013] draft proposal for chrono::date
From: Anurag Kalia (anurag.kalia_at_[hidden])
Date: 2013-05-03 18:24:47

> Unchecked interface:
> --------------------
> date(year y, month m, day d);
> This is the only order, there is no checking, the year, month and date
> objects do no validation themselves. They exist only to disambiguate the
> order of this low level constructor. This single order is chosen above
> any other because of the ISO standards. The use of the year, month and
> day objects add some type safety with no run time overhead, and so are
> acceptable. Each of these objects will *explicitly* convert from int:
> date(year(2013), month(5), day(3)); // ok
> date(2013, 5, 3); // compile time error

Why are we not using following constructor?

date(int year, int month, int day);

To clarify my position, benefits are not apparent to me. Since the order is
strictly-defined, the writer of code has to remember the ordering in both
cases. OTOH an year is typically in thousands:

date(2013, 5, 3);

It should ring a bell towards the ymd notation. The fact that constructor is
named date already gives away its purpose. But then I haven't read any code
that isn't written by me, or when the docs are not at hand, so I can always
use second opinion.

> I dislike the use of no_check_t at this level because I see it as
> unnecessarily verbose and ugly, and I'll have to look up how to spell it
> every time I use it (see the checked interface for why).

> Checked interface:
> ------------------
> I like the use of factory functions here. I also like an
> easy-to-remember, convenience, forgiving, type-safety. My still-preferred
> spelling for the factory functions (yes, more than 1) is:
> date d = year(2013) / month(5) / day(3);
> date d = year(2013) / month(5) / 3;
> date d = month(5) / day(3) / year(2013);
> date d = month(5) / day(3) / 2013;
> date d = day(3) / month(5) / year(2013);
> date d = day(3) / month(5) / 2013;
> These 3 orders are chosen among the possible 6 because these are the 3
> that people actually use:
> The first two units have to explicit. The last unit can be implicit.
> Other rules are possible, but this one is a nice compromise between
> convenience and simplicity. It is an easy rule to remember, and the rule
> is easily checked by the compiler at compile time.

No questions there. I agree. And the fact that they can't be faster than
constructor variants, I think it is okay to make it optimized for usability

> I like this spelling of the checked factory function over:
> make_unchecked_date(2013, may, 3);
> or
> make_valid_date(2013, may, 3);
> because I know I will remember how to spell the former 3 years from now,
> but I will have to look the latter up in a reference, unless I'm dealing
> with dates often enough that I memorize it.
> In both interfaces, the year, month and day objects do no validity
> checking. The validity checks in the checked interface happen only at the
> time the full date is constructed.

Again, no bone of contention. And, orthogonal to the topic, i want to say
that I am still waving for functions like:

make_ordinal_date(2013, 45);
make_week_date(2013, w7, 5);

Because mixing them with other constructors would be confusing. Keeping the
notation to make them seprately, but part of same date class at the end, is
something like their relation with actual gregorian calendar.

At which point I wonder, why can't we be symmetrical and allow a function

make_date(2013, 2, 27);

As Rob says compiler will optimize this call due to RVO. we can make it
explicit using move constructor too.

> Two date types:
> 1. Serial:
> typedef duration<int, ratio_multiply<hours::period,
> ratio<24>>> days;
> typedef time_point<system_clock, days>
> day_point;
> day_point is the serial date type. This is nothing but integral
> arithmetic with no validity checking. It has some convenience conversions
> to/from the serial date_time type: system_clock::time_point, and the
> field-date type...
> 2. Field date-type:
> Something that stores year, month and day, maybe named date, maybe not.
> Provides conversions to and from day_point.
> These two date types are analogous to the two C date types: time_t and
> tm. I have come to the conclusion that two types are necessary because
> each has its strengths and weaknesses in terms of performance. Each type
> should offer only the operations which it can do fast. E.g. there is no
> month() accessor on the serial date type, only on the field date type. If
> you have serial and you need the month, convert to the field type, and
> then you have it.
> This design follows the philosophy of the containers, and whether or not
> any given container has an operator[](size_t), or a size() member. If you
> need an operation, and it isn't available on the container you have, you
> just have to move your data to a container that supports it. This aids in
> exposing performance bugs. It makes expensive operations explicit.

I don't think we should mirror the behaviour of tm and time_t here. Somebody
who needs only thin wrappers around actual functions can already use them.
The fact that they originated in C doesn't make them unusable.

The need for date class exists only because there isn't one around that
behaves like it. That means that we should provide a solid abstraction in
this case. Ultimately, passing objects around would lead to more sub-optimal
(and confusing) code.

Why would we forego the chance that C++ has of gaining a proper date type?

> Both checked and unchecked interfaces should be made constexpr. day_point
> is already constexpr (in C++14). The field date-type should be constexpr.
> Anurag, please feel free to adopt or ignore any or all of this. I can
> also offer services in the creation of constexpr field<->serial
> conversions if that would be helpful. Best of luck in your gsoc!

I will not negate that I have opinions. But I am grateful for the invaluable
feedback here. And we can't forget that my proposal rips off of yours. :D

constexpr conversions are a case in point. They might have never struck me
on my own. Maybe they might have, but who knows. I will try it on my own and
wouldn't hesitate to contact you if I have problems. It would be much more
rewarding that way. :-)

Thanks everybody!

View this message in context:
Sent from the Boost - Dev mailing list archive at

Boost list run by bdawes at, gregod at, cpdaniel at, john at