Boost logo

Boost :

Subject: Re: [boost] [gsoc 2013] draft proposal for chrono::date
From: Anders Dalvander (boost_at_[hidden])
Date: 2013-05-05 07:41:34


On 2013-05-05 01:33, Vicente J. Botet Escriba wrote:
> Le 04/05/13 23:09, Howard Hinnant a écrit :
>> On May 4, 2013, at 4:15 PM, "Vicente J. Botet Escriba"
>> <vicente.botet_at_[hidden]> wrote:
>>> class date;
>>>
>>> date today();
>> In what timezone?
> UTC
I thought that `chrono::date` was an abstract representation of a date,
and not at all connected to a timezone. And that in order to convert to
and from a `chrono::system_clock` or any other clock an explicit
timezone would be needed.
>
>> What is the internal representation?
> I'm not talking here of a concrete date class yet, but much more of an
> archetype of Date concept. We could see the if it is better to make
> concrete classes that provide less as not efficient.
>
Exactly, we should discuss the Date concept, and not focus on the
concrete *classes*.
>>
>>> explicit date(system_clock::time_point);
>>> operator system_clock::time_point() const;
>> Do the above two assume the UTC timezone?
> Copy/paste from your original proposal.
>
> explicit date(chrono::system_clock::time_point tp);
>
> /Effects:/ |tp| is converted to UTC, and then trucated to 00:00:00
> hours. A |date |is created which reflects this point in time.
> /Throws:/ If the conversion from |tp| overflows the range of |date|,
> throws an exception of type |bad_date|.
> explicit operator chrono::system_clock::time_point () const;
>
> /Returns:/ A |chrono::system_clock::time_point| which represents the
> date referred to by |*this| at 00:00:00 UTC.
> /Throws:/ If the conversion to |tp| overflows the range of
> |chrono::system_clock::time_point|, throws an exception of type
> |bad_date|.
Same here, the date May 5th 2013 represent the time range [2013-05-05
00:00, 2013-05-05 24:00), but that time range is different for different
people around the world. It would be, in my humble opinion, better to
keep `chrono::date` abstract, without any connection to a timezone.

Same with `chrono::time` (or whatever it would be called), it could be
the time 12:34:56, but that cannot be represented as an instant in time
(i.e. `chrono::time_point`). Neither can the combined `chrono::date` and
`chrono::time`, it is still without any connection to a timezone.
Perhaps it's better to explain myself with code:

chrono::date d = year(2013) / may / day(5);
chrono::time t = hours(12) + minutes(34) + seconds(56);
chrono::date_time dt(d, t);
// Here `dt` should be the representation of May 5th 2013 at 12:34:56,
but that in turn occurred at different instants for different people
around the world.
// In order to convert it to a `system_time` a timezone would be needed:
chono::system_time st = dt.in_timezone(chrono::timezones::utc); // or
perhaps `dt.in_utc()` for short.

I believe this is one of the few ways to resolve the many ambiguities of
dates and times once and for all.

Below is a rant, but first a disclaimer: I like the Boost.DateTime
library very much, it has helped me greatly.
The Boost.DateTime library has some flaws, one of them is the ambiguity
of the `boost::date_time::ptime` class regarding timezones. It can
represent time in different timezones, and you never know which. It can
be local or UTC, or whatever. It's easy to use it incorrectly, it even
have two factory functions (`second_clock::universal_time` and
`second_clock::local_time`) which both create a `ptime`, but in
different timezones, and after it has been created you can never know
which. It can easily be resolved, as described above, and the compiler
will tell you if you try to do something wrong.
Not even the old C `time_t` had this issue, you are always explicit when
converting it to local time (`localtime`) or UTC time (`gmtime`), but
here the `tm` struct was used for both.

Let's not make the same mistakes once again with `chrono::date`.

Best regards,
Anders Dalvander


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