Boost logo

Boost :

Subject: Re: [boost] [gsoc 2013] draft proposal for chrono::date
From: Howard Hinnant (howard.hinnant_at_[hidden])
Date: 2013-05-07 17:46:23


On May 7, 2013, at 5:32 PM, Anders Dalvander <boost_at_[hidden]> wrote:

> On 2013-05-06 05:29, Howard Hinnant wrote:
>>
>> Btw, I'm getting better at this (speaking of manual dexterity more than coding):
>>
>> day_point d = year(2013) / may / day(5);
>> auto t = hours(22) + minutes(55) + seconds(55);
>> auto dt = d + t;
>> auto EDT = -hours(4);
>> dt -= EDT;
>> auto dt_now = system_clock::now();
>> auto diff = dt_now - dt;
>> std::cout << duration_cast<milliseconds>(diff).count() << " ms\n";
>>
>> Output:
>>
>> 318 ms
>>
>> -------------------------
>>
>> My point in this post is that we have an existing std::chrono date_time facility and it would be good to interoperate with it. Dissecting this code line by line:
>>
>> day_point d = year(2013) / may / day(5);
>>
>> d is a std::chrono::time_point with the same epoch as std::chrono::system_clock::time_point, but has a much coarser resolution (technically day_point::period): std::ratio<86400>.
>>
>> Because d has the same epoch as system_clock::time_point, the two types can, by C++11 rules, have arithmetic together. You can subtract one from the other and it just works. The result is a std::chrono::duration with the precision of the common_type of the two precisions (typically the finer).
>>
>> So, the above code is proposed. But much of the following code is simply existing C++11, showing interoperability with the proposed code with C++11.
>>
>> auto t = hours(22) + minutes(55) + seconds(55);
>>
>> Nothing new about the above code. This is just a std::chrono::duration with a resolution of seconds. It exists today.
>>
>> auto dt = d + t;

Technically this time_point is in UTC, and means 22::55::55 after midnight. However that obviously was not the intent of the code. However I could have written:

auto dt = d + (t - EDT);

And then the time_point would have no point in which it doesn't point to the desired time.

>>
>> The proposal is that d has type time_point<system_clock, duration<int, ratio<86400>>>. If that is so, then it is, by C++11 rules, already legal to add such a time_point to a duration of seconds. The result is a
>>
>> time_point<system_clock, duration<system_clock::rep, ratio<1>>>
>>
>> I.e. the result is a time_point with the same epoch as system_clock. A rep capable of holding the union of values from both d and t, and a precision capable of holding both all values from d and all values from t. In English: dt is a count of seconds from the system_clock epoch ... all by C++11 specification. Nothing invented here except day_point in the first line.
>>
>> auto EDT = -hours(4);
>>
>> This is just C++11. A duration type. It could have any units: hours, minutes, seconds, whatever.
>>
>> dt -= EDT;
> The above statement is the one which troubles me. Before executing the statement `dt` is supposedly in EDT, and after the statement has executed `dt` is in UTC (or is it the other way around). Anyway `dt` is of type `time_point<system_clock, duration<system_clock::rep, ratio<1>>>` as you wrote, but that type has a defined meaning. Each `time_point` is a single point in time, an instant. If we start to make exceptions to this rule, then we're back with the problems of `boost::date_time::ptime`.
>
> And what about the `system_clock::to_time_t` and `time_point::time_since_epoch` functions? Shouldn't it be possible to call them at any given time and not worry if someone has adjusted the time_point to be in the "correct" timezone?
>
> This is one of the things that I hoped the chrono library would solve by requiring the user to explicit.
>
> The C-library is this explicit, why shouldn't the chrono library be able to be explicit as well?

Perhaps it can be. The intent of the above snippet is to show that:

1. chrono::time_point has a critical role here. It is a serial type. When it has precision finer than a day, it is a serial date_time type. When it has precision of a day, it is a serial date_days type. And if time_points of different precision share a clock, you can do time_point arithmetic with them, even though they have different precisions. The result will be a time_point (or duration) with a precision that can represent the result with no loss of precision.

2. 1. is useful! We can use 1 to effortlessly handle timezone differences, even ridiculous timezone offsets in minutes or seconds.

3. There is a direct correspondence with std::system_clock.

The above doesn't have to be the final or everyday syntax that the client uses. But (imho) it demonstrates a solid foundation which we should build upon.

Howard


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