Boost logo

Boost :

Subject: Re: [boost] [chrono/date] date conversion and arithmetic with unvalidated dates
From: Anurag Kalia (anurag.kalia_at_[hidden])
Date: 2013-05-06 16:57:52


Vicente Botet wrote
> Le 06/05/13 15:22, Howard Hinnant a écrit :
>> On May 6, 2013, at 6:30 AM, "Vicente J. Botet Escriba" <

> vicente.botet@

> > wrote:
>>
>>> Hi,
>>>
>>> Note that N3344 suggest only day arithmetic for a day representation
>>> (which is always valid) and suggest only only a date representation.
>>>
>>> Could we apply arithmetic operations on a unvalidated date (without
>>> striving on UB)?
>>> e.g. day arithmetic on a ymd_date
>>>
>>> ymd_date d1(year(2013), may, day(66));
>>> ymd_date d2 = d1 + day(1);
>>>
>>> If defined, which must be the value of d2?
>>>
>>> Could we convert a date representation to another one if the source date
>>> is unvalidated (without striving on UB)? e.g. ymd_date -> days_date
>>>
>>> ymd_date d1(year(2013), may, day(66));
>>> days_date d2 = d1;
>>>
>>> If defined, which must be the value of d2?
>> My understanding is that all of these operations (if unchecked at
>> ymd_date construction time) are simply undefined behavior. This is what
>> N3344 seems to be asking for.
>
> N3344 doesn't suggest month and year arithmetic at all. They suggest to
> let these features for a higher layer.

I thought it does. It even includes a benchmark for increasing in terms of
months.

> Should the following pass.
>
> ymd_date dt(year(2012),feb,day(29));
> try {
> dt+=years(1);
> BOOST_TEST(false);
> } catch (...) {}
>
> Or should dt contain an invalid date? I would expect that an exception
> is thrown.
>
> In the same way we are proposing constructors and factories that allows
> the user to check/uncheck the validity of the entered date, arithmetic
> operators can be considered also as date factories
>
> I'd propose that arithmetic operators using operators validates the
> result. For those that don't want to pay for validity check we can add
> additional functions that don't check the validity
>
> date& date::inc(years);
> date& date::pre_inc();
> date& date::post_inc();
> date& date::dec(years);
> date& date::pre_dec();
> date& date::post_dec(years);
> date sum(date, years);
> date diff(date, years);
>
> Or shouldn't we have two different classes, validated and unvalidated
> dates, as Rob has suggested?
> More I analyze the subject more I believe the separation is unavoidable.
>
> validated_date dt(year(2012),feb,day(29));
> try {
> dt+=years(1);
> assert(false);
> } catch (...) {}
>
> unvalidated_date dt(year(2012),feb,day(29));
> try {
> dt+=years(1);
> // the result of dt is 2013/feb/29 which is unchecked and invalid
> } catch (...) {
> assert(false);
> }
>
> The user can move from one date type to the other
>
> unvalidated_date dt(year(2012),feb,day(29));
> try {
> dt=validate(dt) + years(1);
> } catch (...) {
> assert(false);
> }
>
> Best,
> Vicente

I am afraid I don't like this separation of dates. The current model as it
stands simply says that the dates constructed with "raw" constructor are
undefined. This doesn't mean that they are discarded and can't be used: one
natural interpretation is that the dates created are assumed to be valid.
The implementation essentially has faith in the programmer for feeding it
the correct value.

Also, dates constructed with validation check are of course valid. Combining
the two, we have always valid dates when created. Thus, operations define
their behaviour on valid dates only. It doesn't mean operation is always
defined for valid dates. As your example suggests, "2013-02-29" + 1 year =
"2013-02-29" which doesn't exist! Thus it is possible for valid dates to
have no defined answer for that operation. We can either throw an error, or
extend our operation to include those dates, say "29 feb" + 1 year maps to
"28-feb" now. The same can be said in the cases of underflow or overflow.
The path we choose for those dates can be argued and debated, but what we
are not arguing is the validity of the input dates.

But as you rightly ponder over is how to validate an unvalidated date. We
can always create a date from the previous date using functions that
validate it, say make_date(). To ease it, we can create function:

make_date(date unvalidated);

make_date() as before uses validation while construction of dates. The
question though remains whether we can ever check a date for validation. As
I said before, it is impossible for serial-based implementation. So, I am in
favour scrapping any such effort and dumping any interaction with an
unvalidated date in the undefined behaviour. It indicates to user to proceed
with caution. If he/she does, well good luck! They can always build
validation in their own system as they see fit.

--
View this message in context: http://boost.2283326.n4.nabble.com/chrono-date-date-conversion-and-arithmetic-with-unvalidated-dates-tp4646774p4646848.html
Sent from the Boost - Dev mailing list archive at Nabble.com.

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk