Search code examples
c++datetimetime-t

Convert `time_t` to decimal year in C++


How can I convert a time_t structure to years as decimal?

For example, for a date 2015-07-18 00:00:00 I would like to get 2015.625.


Solution

  • Following my comment seeking more information about how you came to .625, I will assume that you actually meant .55 because July 18th, 2015 is the 199th day of the year.

    You need to first use get_time to get time from a string into a std::tm structure. Then, with some help from mktime we should be able to get the day of the year. Following that, we can perform a quick calculation to see if the year is a leap year, and then perform division to get our ratio:

    Full Code

    Live Demo

    Includes

    #include <ctime>
    #include <iostream>
    #include <sstream>
    #include <locale>
    #include <iomanip>
    #include <string.h>
    

    Main

    int main()
    {
        std::tm theTime = {};
        
    

    Properly calling get_time

        // initialize timeToConvert with the Year-Month-Day Hours:Minutes:Seconds string you want
        std::string timeToConvert = "2015-07-18 00:00:00";
        std::istringstream timeStream(timeToConvert);
        
        // need to use your locale (en-US)
        timeStream.imbue(std::locale("en_US.UTF-8"));
        timeStream >> std::get_time(&theTime, "%Y-%m-%d %H:%M:%S");
        if (timeStream.fail()) 
        {
            std::cerr << "Parse failed\n";
            exit(0);
        } 
    

    mktime

        // call mktime to fill out other files in theTime
        std::mktime(&theTime);
        
    

    Get day of year and number of days in the year

        // get years since 1900
        int year = theTime.tm_year + 1900;
        
        /* determine if year is leap year:
        If the year is evenly divisible by 4, go to step 2. ...
        If the year is evenly divisible by 100, go to step 3. ...
        If the year is evenly divisible by 400, go to step 4. ...
        The year is a leap year (it has 366 days).
        The year is not a leap year (it has 365 days).
        */
        bool isLeapYear =  year % 4 == 0 &&
                            year % 100 == 0 &&
                            year % 400 == 0;
        
        // get number of days since January 1st
        int days = theTime.tm_yday+1; // Let January 1st be the 1st day of year, not 0th
      
        
        // get number of days in this year (either 365 or 366 if leap year)
        int daysInYear = isLeapYear ? 366 : 365;
        
    

    Finally perform division and print the resulting value

        double yearAsFloat = static_cast<double>(year) + static_cast<double>(days)/static_cast<double>(daysInYear);
        
        std::cout << timeToConvert << " is " << yearAsFloat << std::endl;
    }
    

    Output:

    2015-07-18 00:00:00 is 2015.55