3

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.

theDmi
  • 17,546
  • 6
  • 71
  • 138
SSV
  • 33
  • 1
  • 5
  • Can you describe how you obtained `.625`? According to Google, that's the 199th day of the year, and `199/365 = 0.545` – AndyG Aug 17 '15 at 13:06

4 Answers4

3

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

Community
  • 1
  • 1
AndyG
  • 39,700
  • 8
  • 109
  • 143
  • memset is silly, you just correctly initialized every member on the previous line – Cubbi Aug 25 '15 at 13:03
  • @Cubbi: You are correct. I mistakenly thought it was needed for portable code, as I saw an issue in VS without it, however said issue was caused by not initializing to `{}` and not calling `memset` to compensate. I've edited the post. – AndyG Aug 25 '15 at 14:23
2

You could convert it into a broken down time using e.g. std::gmtime or std::localtime.

The broken down time structure contains the year, and a tm_yday member which is the days since January 1. You could use this tm_yday member to calculate the part after the decimal point.

If you want higher resolution, use the hours, minutes and seconds too.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
0

Use strftime

struct stat info; 
char buff[20]; 
struct tm * timeinfo;

stat(workingFile, &info); 

timeinfo = localtime (&(info.st_mtime)); 
strftime(buff, 20, "%b %d %H:%M", timeinfo); 
printf("%s",buff);

Formats:

%b - The abbreviated month name according to the current locale.

%d - The day of the month as a decimal number (range 01 to 31).

%H - The hour as a decimal number using a 24-hour clock (range 00 to 23).

%M - The minute as a decimal number (range 00 to 59).
Abhishek Dey
  • 1,601
  • 1
  • 15
  • 38
0

Use the following steps:

  • separate year from month and day using std::gmtime.
  • compute X = number of days in the day and month (keeping in mind that the year could be a leap year); For example, for the 3rd of February X will always be 31 + 3 = 34; For 3rd of March, it would be 31 + 28 + 3 = 62 or 31 + 29 + 3 = 63 for leap years;
  • compute Y = the number of days for the year
  • compute the percentage using the formula: (X * 100.) / Y and display it with three decimals
Community
  • 1
  • 1
utnapistim
  • 26,809
  • 3
  • 46
  • 82