In my data stream, I have seconds since midnight and days since January 1st...I will be manually specifying a year, so I need to be able to convert those three values to a correct date/time to output to another program. Here's my code:
int currentDay = XPLMGetDatai(gLocalDate); // days since Jan 1st
float currentTime = XPLMGetDataf(gZuluTime); // seconds since midnight
int currentYear = 2015;
struct tm t;
struct tm * ct;
time_t t_of_day;
t.tm_year = currentYear - 1900;
t.tm_yday = currentDay;
t.tm_hour = (int)(currentTime / 3600);
t.tm_min = (int)(currentTime - (t.tm_hour * 3600)) / 60;
t.tm_sec = (int)currentTime - ((t.tm_hour * 3600) + (t.tm_min * 60));
t_of_day = mktime(&t); // should convert t into a valid time_t
ct = gmtime(&t_of_day); // should give me a valid UTC from t
// Send data to Celestial Control
CCelC.SetDay(ct->tm_mday);
CCelC.SetHour(ct->tm_hour);
CCelC.SetMinute(ct->tm_min);
CCelC.SetMonth(ct->tm_mon);
CCelC.SetYear(currentYear);
The problem I seem to be having is the fact that currentDay being plugged into tm_yday is getting obliterated when the mktime(&t) gets called. So I end up with a ct->tm_mon of 0, which is incorrect in my test run of currentday 90 (April 1).
So given any year, any seconds since midnight, and any days since jan 1, how can I generate correct day(1-31), hour(0-23), min(0-59), mon(1-12), year values?
You can't use mktime
to do this in the way you want to. From these docs
The values of the members tm_wday and tm_yday of timeptr are ignored
.....
A call to this function automatically adjusts the values of the members of
timeptr
if they are off-range or -in the case oftm_wday
andtm_yday
- if they have values that do not match the date described by the other members."
However you can take advantage of this behavior to populate the other fields correctly. If you instead set up the fields of the struct tm
like so
struct tm t = {0};
t.tm_mday = currentDay + 1;
t.tm_year = currentYear - 1900;
t.tm_sec = currentTime;
mktime(&t);
This method works because of the automatically adjusting behavior of mktime
As a fully working example
#include <ctime>
#include <iostream>
int main()
{
int currentDay = 90;
int currentTime = (12*3600 + 52*60 + 31);
int currentYear = 2015;
struct tm t = {0};
t.tm_mday = currentDay + 1;
t.tm_year = currentYear - 1900;
t.tm_sec = currentTime;
// mktime will now correctly populate
// tm_sec, tm_min, tm_hour
// tm_day, tm_mon, tm_year
mktime(&t);
// Print the time to make sure!
std::cout << asctime(&t);
}
Will output
Wed Apr 1 12:52:31 2015