Boost logo

Boost :

Subject: Re: [boost] [gsoc 2013] draft proposal for chrono::date
From: Vicente Botet (vicente.botet_at_[hidden])
Date: 2013-04-30 13:59:03


Anurag Kalia wrote
> Hi Vicente,
>
> Before I start, I want to ask what I should submit as a proposal to
> Google? i know I am to implement date class. But the problem arises that
> the design and implementation are still taking time to set in.
> How can I tell them details that most probably would change in one way or
> another? What should I mention in the proposal beyond that I want to
> implement date class.

For me it is not enough to say you want to implement a date class. H.Hinnant
and myself already did that.
You need to mention what are the limitation on this proposal and how you
plan to solve them.

> Moreover, what am I expected to do? Should I make all the implementations
> of major representations and then test them in the course of making the
> date library? I think I should (and probably I would) but I am just asking
> about the expectations.

Again H.Hinnant and myself already do the major representations.
What needs to be done is to provide the interface that satisfy most of the
user expectations (don't forget that performances was one of the main issues
of H.H. proposal.

> And so on to the actual discussion...
>
>> I have just read the representation part. IIUC you choose a compact
>> representation of a YMD. It has the same liabilities than the YMD
>> representation (day arithmetic) and adds in addition some drawbacks as
>> you need to calculate the year, month and day from this representation.
> Yeah it does, now that I ponder more over it. My representation (let us
> call it serial YMD) has advantage in incrementing and decrementing of
> months and years. Currently, its day arithmetic is inefficient but I am
> sure it can be made better and mostly on the lines of YMD date only so not
> much difference there either way.
>
> Again comparison is a toss-up. Best case of serial YMD takes two
> comparisons but for the majority it suffices. YMD takes only one in best
> cases and restricts itself to three comparisons at most. I think, simple
> YMD has advantage here.
>
> And I/O in YMD can't be bested by any other representation in my opinion.
> I thought serial YMD is absorbing advantages of both representations but
> it seems to be the opposite.

Right, so no need to provide an additional representation.

>
>> I don't think that having a single representation would solve the design
>> of a Date library. I think that each representation could be more
>> efficient for day arithmetic while been less efficient for month/year
>> arithmetic and vice-versa. So several representation must be provided.
>> The problem is how to make all of them more efficient while preserving
>> the integrity.
> I was thinking of wrapping the storage fields of date into a class, e.g.
> ymd class, serial_raw class, serial_leap class, ymd_cache class etc. All
> of them surface the basic functions in the same way like setter and getter
> functions [year(), month(), etc], comparison, copy operations etc.
>
> Then the general date
> <rep>
> template is able to interact with any other date
> <rep2>
> . For example, an operation of date
> <ymd>
> - date
> <serial>
> should be possible through the general operator- function in date
> template only, returning a duration in days.
>
> I intend to code a working prototype to show it to you, but I am still in
> the middle of it though and should be demonstrable by the next day.

I don't mind if the different date class are provided by a
date<Representation> template class or by several classes that interact each
one with each other. The advantage of independent classes is that the user
could add its own date class that works well with the others.

>> The problem is how to make all of them more efficient while preserving
>> the integrity.
> I don't understand what is being conveyed here. Can I ask you to explain
> it better for me please? :)

You can see the project as: Given the H.Hinnant design and implementation,
what needs to be changed so that the performances are improved?
* date validation versus "sur parolle" valid dates,
* relative dates should not reduce the performances of absolute dates,
* some algorithms are more efficient with one or another representation.

>> date construction
>>
>> I don't like the functional construction.
>>
>> date d1_2 = date(1, 2, 2011, DMY);
>>
>> What do you think of the ways I included on my prototype?
>>
>> /**
>> * @Effect Constructs a @c ymd_date using the @c year, @c month, @c
>> day stored in the arguments as follows:
>> * If the value stored in @c d is outside the range of valid dates
>> for this month @c m and year @c y,
>> * throws an exception of type @c bad_date.
>> * Else constructs a @c ymd_date for which
>> <c>
>> get_year() == y && get_month() == m && get_day() == d
>> </c>
>> .
>> * @Throws @c bad_date if the specified @c ymd_date is invalid.
>> */
> I can see use of all constructors except the day_of_year constructor.

Why? This is an alternative representation.

> Since we are making it a p. gregorian calendar, such interface shouldn't
> be made public. It should rather be used in dayofyear_claendar where
> concept of months doesn't exist, shouldn't it?

I disagree here. 125th day of 2013 is a valid date.

> And I like the way you have designed the corresponding unchecked
> functions. As for implementation, one only needs combined representation
> month_day and the data if the year is leap or not.
>
> //rough idea:
>
> month_day = (month-1)*31 + (day-1)
>
> We check this value against the seven (six, if leap) days as mentioned in
> my serial YMD implementation.
> Actually, this approach can be used for any representation because of its
> compactness.

Sorry, but I don't see any added value to your compact YMD representation.

>> Having opaque types for year, month and day you can add as many
>> permutations as you desire.
>>
>> The following would not work
>> //operational
>> date d3_1 = weekday(wd)[_1st] / may / 2011;
>> //functional
>> date d3_2 = date( wd[_1st], may, 2011, DMY);
>>
>> The problem is that wd[_1st] is not really the same as a day.
> Yeah, I thought about that and decided to add a WMY constant. But it would
> have just added mental overload of users. It is there just to tell the
> compiler about the order of arguments to both compiler and a person who
> reads the code. Seeing ymd added to the definition automatically tells
> what the date constructor intends to do. weekday() is anyways of a
> different type than day() so we can just overload the functions. I
> genuinely am curious why adding that fourth parameter might be a bad
> design.

Well, this is a taste question. I will comeback to your functional format
later.

>> About the _1st, 2nd, ... , _31th, last constants and you symmetry
>> problem, what about having the nth to access the one before the last
>>
>> nth(-1)
>>
>> or just last_1st last_2nd, ...
> Again, this adds extra syntax when the current one can do it all the same.
> e.g. a second-to-last date can be constructed by the current syntax
> itself:
>
> date d = last / jan / 2001 - days(1);
>
> which is also perfectly readable. Shouldn't we avoid to add needless
> constants?

Good point.

>> I don't see nothing yet about validation of dates. IMO the usual
>> constructor must validate the date and one less fiendly could be provided
>> when the date must not be validated. I included a constructor for
>> unchecked dates in my prototype. What do you think?
>>
>> ymd_date(chrono::year y, chrono::month m, chrono::day d);
>> /**
>> * @Effect Constructs a @c ymd_date constructor from @c year, @c
>> month, @c day stored in the arguments as follows:
>> * Constructs a ymd_date so that
>> <c>
>> get_year() == y && get_month() = m && get_day() == d
>> </c>
>> .
>> */
>> ymd_date(year::rep y, month::rep m, day::rep d, no_check_t)
>> BOOST_NOEXCEPT;
> As I have said, I like this representation. Average user gets the full
> error-checking without any syntactic burden. The person in need of more of
> power however gets the uglier representation because it would be much less
> required.
>
>
> Year/Month/Day/WeekDay arithmetic
>> As your representation is equivalent to the YMD representation all the
>> algorithm in HH implementation are valid, so there is no need to extend
>> on this.
>> I/O again I don't see nothing about input.
> I am not sure about this. I thought date construction is only way one can
> make dates. Is it possible to change the values of an existing dates? if
> we want to change the whole date, we can just use constructors and make
> them assign the temporaries to the given date object.
>
> e.g.
> date d = date(1, 12, 2001);
> d = date(1, 12, 2001);
>
> If one wants to modify individual objects, the function modify may look
> like:
>
> date modify_year(int yr)
> {
> int diff_y = yr - year();
> *this += years(diff_y);
> return *this;
> }

I was talking about stream Input/output

>> Relations with chrono::system_clock
>>
>> I would say just that conversion between date and
>> chrono::time_point&lt;chrono::system_clock, chrono::days&gt; can be done
>> in both direction.
> If we want to convert into both directions, non-member functions can be
> employed:
>
> date to_date(time_point&lt;system_clock, days&gt;);
> //and
> time_point&lt;system_clock, days&gt; to_time_point(date);
>
> Moreover, I realized I should start putting my date classes into
> appropriate namespaces, eg. chrono::days.

What I mean is that a date can not inherit from a days point, this is
horrible.

More later,
Vicente

--
View this message in context: http://boost.2283326.n4.nabble.com/gsoc-2013-draft-proposal-for-chrono-date-tp4646142p4646364.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