1 #include <time.h>
2 #define _POSIX_C_SOURCE 1
3 #include <predict/predict.h>
4 #include <stdio.h>
5 #include "defs.h"
6 
7 /**
8  * Create time_t in UTC from struct tm.
9  *
10  * \param timeinfo_utc Broken down time, assumed to be in UTC
11  * \return Time in UTC
12  **/
mktime_utc(const struct tm * timeinfo_utc)13 time_t mktime_utc(const struct tm* timeinfo_utc)
14 {
15 	time_t curr_time = time(NULL);
16 	int timezone_diff = 0; //deviation of the current timezone from UTC in seconds
17 
18 	//get UTC time, interpret resulting tm as a localtime
19 	struct tm timeinfo_gmt;
20 	gmtime_r(&curr_time, &timeinfo_gmt);
21 	time_t time_gmt = mktime(&timeinfo_gmt);
22 
23 	//get localtime, interpret resulting tm as localtime
24 	struct tm timeinfo_local;
25 	localtime_r(&curr_time, &timeinfo_local);
26 	time_t time_local = mktime(&timeinfo_local);
27 
28 	//find the time difference between the two interpretations
29 	timezone_diff += difftime(time_local, time_gmt);
30 
31 	//hack for preventing mktime from assuming localtime: add timezone difference to the input struct.
32 	struct tm ret_timeinfo;
33 	ret_timeinfo.tm_sec = timeinfo_utc->tm_sec + timezone_diff;
34 	ret_timeinfo.tm_min = timeinfo_utc->tm_min;
35 	ret_timeinfo.tm_hour = timeinfo_utc->tm_hour;
36 	ret_timeinfo.tm_mday = timeinfo_utc->tm_mday;
37 	ret_timeinfo.tm_mon = timeinfo_utc->tm_mon;
38 	ret_timeinfo.tm_year = timeinfo_utc->tm_year;
39 	ret_timeinfo.tm_isdst = timeinfo_utc->tm_isdst;
40 	return mktime(&ret_timeinfo);
41 }
42 
43 /**
44  * Helper function for getting the Julian day start date (1979-12-31 00:00 UTC) as time_t.
45  *
46  * \return Internally defined Julian start date (fixed)
47  **/
get_julian_start_day()48 time_t get_julian_start_day()
49 {
50 	struct tm start_time;
51 	start_time.tm_sec = 0;
52 	start_time.tm_min = 0;
53 	start_time.tm_hour = 0;
54 	start_time.tm_mday = 31;
55 	start_time.tm_mon = 11;
56 	start_time.tm_year = 1979-1900;
57 	start_time.tm_isdst = 0;
58 	return mktime_utc(&start_time);
59 }
60 
predict_to_julian(time_t input_time)61 predict_julian_date_t predict_to_julian(time_t input_time)
62 {
63 	//get number of seconds since 1979-12-31 00:00:00 UTC, convert to days
64 	double seconds = difftime(input_time, get_julian_start_day());
65 	return seconds/SECONDS_PER_DAY;
66 }
67 
predict_from_julian(predict_julian_date_t date)68 time_t predict_from_julian(predict_julian_date_t date)
69 {
70 	double seconds_since = date*SECONDS_PER_DAY;
71 	time_t ret_time = get_julian_start_day();
72 
73 	//add number of seconds since julian start day to the julian start day, get current time_t
74 	struct tm timeinfo;
75 	gmtime_r(&ret_time, &timeinfo);
76 	timeinfo.tm_sec += seconds_since;
77 	ret_time = mktime_utc(&timeinfo);
78 	return ret_time;
79 }
80