-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtimeX.h
192 lines (154 loc) · 7.4 KB
/
timeX.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
// x_time.h
#pragma once
#include <time.h> // struct tm
#include "definitions.h" // no nested includes
#ifdef __cplusplus
extern "C" {
#endif
// ############################## BUILD: TimeZone structure support ################################
#define timexEPOCH_U32NTP 1
#define timexEPOCH_I32UNIX 2
#define timexEPOCH_U32UNIX 3
#define timexEPOCH_SELECTED timexEPOCH_U32UNIX
#define timexTZTYPE_POINTER 1
#define timexTZTYPE_FOURCHARS 2
#define timexTZTYPE_RFC5424 3
#define timexTZTYPE_SELECTED timexTZTYPE_RFC5424
// ##################### BUILD: Unix I32 vs NTP U32 vs proprietary U32 epoch #######################
#if (timexEPOCH_SELECTED == timexEPOCH_U32NTP)
#define SECONDS_IN_EPOCH_PAST 0UL // 00:00.00 UTC 1900/01/01
#define SECONDS_IN_EPOCH_FUTURE UINT32_MAX // ??h??m??s on 2036/02/07
#define YEAR_BASE_MIN 1900UL
#define YEAR_BASE_MAX 2036UL
#define EPOCH_SECONDS_DIFFERENCE 0UL // difference between selected epoch & NTP epoch
#define timeEPOCH_DAY_0_NUM 1 // 1900/01/01 was Monday, hence day 1
typedef u32_t seconds_t;
#elif (timexEPOCH_SELECTED == timexEPOCH_I32UNIX)
#define SECONDS_IN_EPOCH_PAST 0 // No support for dates prior to 1 Jan 1970
#define SECONDS_IN_EPOCH_FUTURE INT32_MAX // 03:14:07 UTC 2038/01/19 Tue
#define YEAR_BASE_MIN 1970L
#define YEAR_BASE_MAX 2038L
#define EPOCH_SECONDS_DIFFERENCE 2208988800L // difference between selected epoch & NTP epoch
#define timeEPOCH_DAY_0_NUM 4 // 1970/01/01 was Thursday, hence day 4
typedef int32_t seconds_t;
#warning "UNTESTED configuration !!"
#elif (timexEPOCH_SELECTED == timexEPOCH_U32UNIX)
/* Non standard interpretation for seconds based on U32 but with the base
* date & time (0seconds) being 1970/01/01T00:00.00.000, same as I32 Unix */
#define SECONDS_IN_EPOCH_PAST 0UL // 00:00.00 UTC 1970/01/01
#define SECONDS_IN_EPOCH_FUTURE UINT32_MAX
#define YEAR_BASE_MIN 1970 // 00:00.00 UTC 1970/01/01
#define YEAR_BASE_MAX 2106 // ??:??.?? UTC 2106/02/07
#define EPOCH_SECONDS_DIFFERENCE 2208988800L // difference between selected epoch & NTP epoch
#define timeEPOCH_DAY_0_NUM 4 // 1970/01/01 was Thursday, hence day 4
typedef u32_t seconds_t;
#else
#error "Cannot determine epoch, invalid base year specified"
#endif
// ################################## TZ DST UTC and time related ##################################
#if (timexTZTYPE_SELECTED == timexTZTYPE_POINTER)
#define configTZ_EST {-1*SECONDS_IN_HOUR, -5*SECONDS_IN_HOUR, "EST", "EST" }
#define configTZ_UTC { 0, 0, "UTC", 0 }
#define configTZ_SAST { 0, 2*SECONDS_IN_HOUR, "SAST", 0 }
#define configTZ_ACT {-1*SECONDS_IN_HOUR, 10.5*SECONDS_IN_HOUR, "ACT", "ACT" }
#define configTIME_MAX_LEN_DSTNAME 48 // "Australian Central Daylight Savings Time" = 42
#define configTIME_MAX_LEN_TZNAME 48 // "America/Argentina/ComodRivadavia" == 33
#define configTIME_MAX_LEN_TZINFO (sizeof("+12h34()") + configTIME_MAX_LEN_DSTNAME)
#elif (timexTZTYPE_SELECTED == timexTZTYPE_FOURCHARS)
#define configTZ_EST {-1*SECONDS_IN_HOUR, -5*SECONDS_IN_HOUR, {'E','S','T',0}, {'E','S','T',0} }
#define configTZ_UTC { 0, 0, {'U','T','C',0}, {'N','/','A',0} }
#define configTZ_SAST { 0, 2*SECONDS_IN_HOUR, {'S','A','S','T'}, {'N','/','A',0} }
#define configTZ_ACT {-1*SECONDS_IN_HOUR, 10.5*SECONDS_IN_HOUR, {'A','C','T',0}, {'A','C','T',0} }
#define configTIME_MAX_LEN_DSTNAME 4
#define configTIME_MAX_LEN_TZNAME 4
#define configTIME_MAX_LEN_TZINFO (sizeof("+12h34()") + configTIME_MAX_LEN_DSTNAME)
#elif (timexTZTYPE_SELECTED == timexTZTYPE_RFC5424)
#define configTZ_EST {-1*SECONDS_IN_HOUR, -5*SECONDS_IN_HOUR, 0, 0 }
#define configTZ_UTC { 0, 0, 0, 0 }
#define configTZ_SAST { 0, 2*SECONDS_IN_HOUR, 0, 0 }
#define configTZ_ACT {-1*SECONDS_IN_HOUR, 10.5*SECONDS_IN_HOUR, 0, 0 }
#define configTIME_MAX_LEN_DSTNAME 48 // "Australian Central Daylight Savings Time" = 42
#define configTIME_MAX_LEN_TZNAME 48 // "America/Argentina/ComodRivadavia" == 33
#define configTIME_MAX_LEN_TZINFO sizeof("(+12h34)")
#else
#error "Invalid or undefined 'timexTZTYPE_SELECTED' value"
#endif
// ############################### fractional seconds manipulation #################################
#define FRACTIONS_PER_MILLISEC (0x100000000ULL / 1000ULL)
#define FRACTIONS_PER_MICROSEC (0x100000000ULL / 1000000ULL)
/*
* xTimeFractionToMillis()
* @brief convert NTP fractions of a second to milliseconds
* @param[in] fraction of a second
* @param[out] none
* @return fraction of a second as a number of milliseconds
*/
#define xTimeFractionToMillis(x) ((u32_t) x / (u32_t) FRACTIONS_PER_MILLISEC)
#define xTimeMillisToFraction(x) ((u32_t) x * (u32_t) FRACTIONS_PER_MILLISEC)
/*
* xTimeFractionToMicros()
* @brief convert NTP fractions of a second to microseconds
* @param[in] fraction of a second
* @param[out] none
* @return fraction of a second as a number of microseconds
*/
#define xTimeFractionToMicros(x) ((u32_t) x / (u32_t) FRACTIONS_PER_MICROSEC)
#define xTimeMicrosToFraction(x) ((u32_t) x * (u32_t) FRACTIONS_PER_MICROSEC)
// ####################################### structures & unions #####################################
typedef struct tm tm_t;
/*
* TIME ZONE STRUCTURE DEFINITION
*/
typedef struct __attribute__((__packed__)) tz_t {
short daylight;
int timezone;
#if (timexTZTYPE_SELECTED == timexTZTYPE_POINTER)
char * pcTZName;
char * pcDSTName;
#elif (timexTZTYPE_SELECTED == timexTZTYPE_RFC5424)
char TZid[configTIME_MAX_LEN_TZNAME];
char TZname[configTIME_MAX_LEN_DSTNAME];
#elif (timexTZTYPE_SELECTED == timexTZTYPE_FOURCHARS)
char tzname[4];
char dstname[4];
#endif
} tz_t;
DUMB_STATIC_ASSERT((configTIME_MAX_LEN_TZNAME + configTIME_MAX_LEN_DSTNAME + 6) == sizeof(tz_t));
typedef struct __attribute__((__packed__)) tsz_t {
u64_t usecs; // Must ALWAYS be UTC based value, adjust for local TZ
tz_t * pTZ; // TZ info to be used for local DTZ calculation
} tsz_t;
DUMB_STATIC_ASSERT(sizeof(tsz_t) == (8 + sizeof(void*)));
// ###################################### x_time related ###########################################
int xTimeIsLeapYear(int);
int xTimeCountLeapYears(int);
int xTimeGetDayNumber(char *);
int xTimeGetMonthNumber(char *);
int xTimeCalcDaysMonth(int Year, int Month);
int xTimeCalcDaysInMonth(tm_t *);
int xTimeCalcDaysYTD(tm_t *);
int xTimeCalcDaysToDate(tm_t *);
char * xTimeGetDayName(int);
char * xTimeGetMonthName(int);
void xTimeGMTime(seconds_t, tm_t *, int);
seconds_t xTimeCalcSeconds(tm_t *, int);
seconds_t xTimeCalcLocalTimeSeconds(tsz_t *);
seconds_t xTimeReport(tm_t *psTM);
/**
* @brief Convert 64_t timestamp to u32_t seconds value
* @return u32_t seconds value
*/
static inline u32_t __attribute__((always_inline)) xTimeStampSeconds(u64_t Timestamp) { return (u32_t) (Timestamp / MICROS_IN_SECOND); }
static inline u32_t __attribute__((always_inline)) xTimeStampMicros(u64_t Timestamp) { return (u32_t) (Timestamp % MICROS_IN_SECOND); }
static inline u32_t __attribute__((always_inline)) xTimeStampMillis(u64_t Timestamp) { return (u32_t) ((Timestamp % MICROS_IN_SECOND) / MICROS_IN_MILLISEC); }
/**
* @brief Convert u32_t seconds & microseconds values to u64_t timestamp
* @return u64_t timestamp representing the seconds & microseconds combined
*/
inline u64_t xTimeMakeTimeStamp(u32_t Sec, u32_t uSec) {
return ((u64_t) Sec * (u64_t) MICROS_IN_SECOND) + (u64_t) uSec;
}
void xTimeTest(void);
#ifdef __cplusplus
}
#endif