Boost logo

Boost :

Subject: Re: [boost] [gsoc 2013] chrono::date
From: Howard Hinnant (hinnant_at_[hidden])
Date: 2013-04-24 21:00:03


On Apr 24, 2013, at 7:05 PM, Anurag Kalia <anurag.kalia_at_[hidden]> wrote:

> After going through related docs and general information, I have some questions regarding the chrono::date library.
> What is the origin of the name 'chrono'? I have assumed till now, it has something to do with chronology, but I am not sure.Why is date a part of 'chrono' at all? As I understand, chrono::date library is supposed to be based on the counts of sunrises. I am in favour of it because it elegantly circumvents the complications of leap seconds which are unnecessary with date-related arithmetic. But if we want it to be compatible with the rest of chrono library, complications arise:If we use a definition in line with principles of chrono (i.e. not using sunrises for a moment), a date really becomes a time-interval defined by the 00:00:00 of that date + a duration of 1 day, if we follow the rules of chrono library. But the length of a day can be changed today due to insertion/deletion of leap seconds to the conventional 24-hour day, if needed. Moreover, this change is arbitrary, since leap seconds are used to keep the time in sync with earth's rotations, which changes without a fixed
> pattern.The length of month and year similarly are complicated, not only by the length of days in it (see above) but also by the variable number of days. For example January has 31 days, April has 30 days and February has 28 or 29 days depending upon common year or leap year respectively. Due to the latter, length of year also varies between 365 and 366 days.In essence, there is no fixed duration of day, month or year; unlike the rest of chrono library which fundamentally is based on 'duration' class.Now if we revert to our original definition, our library basically becomes a count of sunrises since epoch. Aren't we forming an independent library from chrono then?What does one mean when one says the chrono::date library interoperates with rest of chrono library? This question is an offshoot of previous question. I am confused as to how far can both parts interoperate given the above-mentioned complications.
> Subtraction of dates yields us theoretically a duration of a number of days. But since actual time duration of a day is ill-defined (see above), we have to return the answer in resolution of seconds, if we use 'duration' at all. I am unable to think of more possibilities of cross-pollination between the two parts.
> Am I correct in my reasoning? I am genuinely stuck at this clubbing up of unrelated (to me) classes. Even more so because Boost already supplies such a vast number of header files with least number of interdependencies. A smaller self-contained date library seems (to me) more in line with its principles.
> Thanks,Anurag Kalia.

From:

http://en.wikipedia.org/wiki/False_precision

> A tour guide at a museum says a dinosaur skeleton is 100,000,005 years old, because an expert told him that it was 100 million years old when he started working there 5 years ago.

If we were to say:

typedef std::chrono::duration
<
std::int32_t, std::ratio_multiply<std::chrono::hours::period, std::ratio<24>>
> days;

typedef std::chrono::time_point
<
std::chrono::system_clock, days
> day_point;

We would have a time_point and duration with a precision suitable for counting sunrises. We could also easily create a clock that ticked once per sunrise.

Now when you get 1000 ticks of this clock, you can know that 1000 days have passed. And yes, 1000 days can be converted to seconds. And when doing so you'll get 86,400,000 seconds. And if it matters that the correct answer is 86,400,001 seconds because you've crossed a leap second boundary, then you need specialized tools for that level of precision. People who need such precision rightly don't trust general purpose tools.

To put this into perspective, the std::chrono::system_clock on your computer (if it is implemented on your platform) is counting seconds since New Years 1970 UTC, with a precision of seconds, or perhaps milliseconds, or maybe even microseconds (on my system it is microseconds). As I write this, my computer claims it is 1,366,849,370,271,425 microseconds past New Years 1970 UTC. And absolutely no one sends in bug reports that this number is 25,000,000 microseconds too low (http://en.wikipedia.org/wiki/Leap_seconds). No one cares or expects the precision to be better than 0.00000001829024.

The very few people who do care, refuse to use UTC. They use TAI (http://en.wikipedia.org/wiki/International_Atomic_Time) instead, which does not include leap seconds. And needless to say, they aren't using the POSIX getimeofday() on their laptop to get the current time (which is what std::chrono::system_clock is commonly based on). They've got atomic clocks ticking 9,192,631,770 times a second.

To verify my claims about your std::chrono::system_clock, I encourage you to play with the following code. If you discover I'm wrong, I would really appreciate being corrected. I do not have in my possession all implementations of <chrono>, nor access to all platforms. So I depend upon people such as yourself to tell me what you're seeing.

#include <chrono>
#include <ctime>
#include <iostream>

int
main()
{
    using namespace std;
    using namespace std::chrono;
    typedef duration<int, ratio_multiply<hours::period, ratio<24> >::type> days;
    system_clock::time_point now = system_clock::now();
    system_clock::duration tp = now.time_since_epoch();
    days d = duration_cast<days>(tp);
    tp -= d;
    hours h = duration_cast<hours>(tp);
    tp -= h;
    minutes m = duration_cast<minutes>(tp);
    tp -= m;
    seconds s = duration_cast<seconds>(tp);
    tp -= s;
    std::cout << d.count() << "d " << h.count() << ':'
              << m.count() << ':' << s.count();
    std::cout << " " << tp.count() << "["
              << system_clock::duration::period::num << '/'
              << system_clock::duration::period::den << "]\n";

    time_t tt = system_clock::to_time_t(now);
    tm utc_tm = *gmtime(&tt);
    std::cout << utc_tm.tm_year + 1900 << '-';
    std::cout << utc_tm.tm_mon + 1 << '-';
    std::cout << utc_tm.tm_mday << ' ';
    std::cout << utc_tm.tm_hour << ':';
    std::cout << utc_tm.tm_min << ':';
    std::cout << utc_tm.tm_sec << '\n';
}

Howard


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