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.
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
Year/Month/Day/WeekDay arithmetic 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<chrono::system_clock, chrono::days> 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<system_clock, days>); //and time_point<system_clock, days> 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-... Sent from the Boost - Dev mailing list archive at Nabble.com.