c++64-bitc++-chronotime-tyear2038

C++ chrono: store and retrieve date and time in 64 bit format for 2038 rollover


2038 is coming...I have to think date time in 64 bit! I'm trying to understand how to do this in C++, with chrono library, but I'm failing miserably so far.

I will have to communicate a date time format to a device that will receive 8 bytes to set its date and will return me the same 8 bytes when requested.

These my experiments so far:

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

using namespace std::chrono;

int main()
{

    typedef std::chrono::duration<int64_t, std::ratio<1,1>> dur_s;
    dur_s time_since_start(0x000000FFFFFFFFFF);
    std::cout << "time_since_start: " << time_since_start.count() << std::endl;

    time_point <system_clock, dur_s> time_point_since_start(time_since_start);
    std::cout << "time_point_since_start: " << 
    time_point_since_start.time_since_epoch().count() << std::endl;

    std::time_t date_since_start = system_clock::to_time_t(time_point_since_start); 

    std::cout << "date_since_start 0: " << date_since_start << std::endl;
    std::cout << "date_since_start 1: " << ctime(&date_since_start) << std::endl;

    return 0;
}

This is the output:

  time_since_start: 1099511627775
  time_point_since_start: 1099511627775
  date_since_start 0: -7293016647
  date_since_start 1: Sun Nov 23 02:52:29 1738

My intent is that to create a duration stored in an int64_t, with the precision of seconds (don't need any more resolution). From that I want to define a time_point and finally represent it as time_t. For my purpose I'm defining a duration that is bigger than 32bit, but something is not working. When I do the system_clock::to_time_t the time_point gets truncated and the result is a date back in time.

I'm missing something obvious here.

I'm working on a recent Linux Mint on a 64bit VM. Code is with standard C++ 17 (can move up to 20 if needed). Compiler is gcc (Ubuntu 13.2.0-23ubuntu4) 13.2.0.


Solution

  • Thank to Howard Hinnant and to Alan Birtles comments I pointed out an easy path and a solution:

    Point 1
    The code can be cleaned up a lot. This helps ! Assuming I want to handle the number of seconds from epoch (1970-01-01...) and just think ahead of 2038 rollover the code can be re stated as follows:

    #include <iostream>
    #include <chrono>
    #include <ratio>
    #include <ctime>
    #include <iomanip>
    
    using namespace std::chrono;
    
    int main()
    {
    
        /** ******************************************************************** */
        /**     Time management                                                  */
        /** ******************************************************************** */
    
        int64_t timestamp = 0x000000FFFFFFFFFF;
    
        std::chrono::duration time_since_start          = std::chrono::seconds (timestamp);
        std::chrono::time_point time_point_since_start  = time_point<system_clock, seconds>(time_since_start);
        std::time_t date_since_start = time_point_since_start.time_since_epoch().count(); 
    
        std::cout << "time_point_since_start: " << time_point_since_start.time_since_epoch().count() << std::endl;
        std::cout << "date_since_start: " << ctime(&date_since_start) << std::endl;
    
        /** ******************************************************************** */
    
        return 0;
    }
    

    Point 2
    Time frame was way tooooo big, but this was not the issue...indeed

    Point 3
    I have a buggy implementation of to_time_t(...) that messed up things a lot ! So using simply the .time_since_epoch().count() of time_point made everything easy and clean.

    Now even with en exaggerate timestamp I have a coherent result

    time_point_since_start: 1099511627775
    date_since_start: Mon Feb 20 01:36:15 36812
    

    Thank you
    P.S. sizeof(std::time_t) = 8 !