This repository has been archived by the owner on Nov 4, 2023. It is now read-only.
/
time.h
240 lines (202 loc) · 4.85 KB
/
time.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
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
/** ffos: date & time
2020, Simon Zolin
*/
/*
fftime_now
fftime_local
fftime_empty
fftime_null
Get time parts:
fftime_sec fftime_msec fftime_usec fftime_nsec
Convert:
fftime_to_msec fftime_to_usec
fftime_from_time_t fftime_to_time_t
fftime_from_timeval fftime_to_timeval
fftime_from_timespec fftime_to_timespec
fftime_from_winftime fftime_to_winftime
*/
#pragma once
#include <FFOS/base.h>
static int fferr_str(int code, char *buffer, ffsize cap);
#include <ffbase/time.h>
#include <time.h>
typedef struct fftime_zone {
int off; // UTC+X (in seconds)
ffuint have_dst; // may have daylight saving time rules
ffuint is_dst; // daylight saving time is active
int real_offset; // offset (seconds) considering DST
} fftime_zone;
#define fftime_empty(t) ((t)->sec == 0 && (t)->nsec == 0)
static inline void fftime_null(fftime *t)
{
t->sec = 0, t->nsec = 0;
}
#define fftime_sec(t) ((t)->sec)
#define fftime_msec(t) ((t)->nsec / 1000000)
#define fftime_usec(t) ((t)->nsec / 1000)
#define fftime_nsec(t) ((t)->nsec)
static inline void fftime_setsec(fftime *t, ffuint s)
{
t->sec = s;
}
static inline void fftime_setmsec(fftime *t, ffuint ms)
{
t->nsec = ms * 1000000;
}
static inline void fftime_setusec(fftime *t, ffuint us)
{
t->nsec = us * 1000;
}
static inline void fftime_setnsec(fftime *t, ffuint ns)
{
t->nsec = ns;
}
/** Get time value in milliseconds */
static inline ffuint64 fftime_to_msec(const fftime *t)
{
return t->sec * 1000 + t->nsec / 1000000;
}
/** Get time value in microseconds */
static inline ffuint64 fftime_to_usec(const fftime *t)
{
return t->sec * 1000000 + t->nsec / 1000;
}
/** time_t -> fftime */
static inline fftime fftime_from_time_t(time_t tt)
{
fftime t = {
.sec = tt,
.nsec = 0,
};
return t;
}
/** fftime -> time_t */
static inline time_t fftime_to_time_t(const fftime *t)
{
return t->sec;
}
#ifdef FF_UNIX
/** timeval -> fftime */
static inline fftime fftime_from_timeval(const struct timeval *tv)
{
fftime t = {
.sec = tv->tv_sec,
.nsec = (ffuint)tv->tv_usec * 1000,
};
return t;
}
/** fftime -> timeval */
static inline struct timeval fftime_to_timeval(const fftime *t)
{
struct timeval tv = {
.tv_sec = t->sec,
.tv_usec = t->nsec / 1000,
};
return tv;
}
/** timespec -> fftime */
static inline fftime fftime_from_timespec(const struct timespec *ts)
{
fftime t = {
.sec = ts->tv_sec,
.nsec = (ffuint)ts->tv_nsec,
};
return t;
}
/** fftime -> timespec */
static inline struct timespec fftime_to_timespec(const fftime *t)
{
struct timespec ts = {
.tv_sec = t->sec,
.tv_nsec = t->nsec,
};
return ts;
}
#endif
typedef struct fftime_winftime {
ffuint lo, hi;
} fftime_winftime;
#define FFTIME_100NS 116444736000000000ULL // 100-ns intervals within 1600..1970
/** Windows FILETIME -> fftime */
static inline fftime fftime_from_winftime(const fftime_winftime *ft)
{
fftime t = {};
ffuint64 i = ((ffuint64)ft->hi << 32) | ft->lo;
if (i > FFTIME_100NS) {
i -= FFTIME_100NS;
t.sec = i / (1000000 * 10);
t.nsec = (i % (1000000 * 10)) * 100;
}
return t;
}
/** fftime -> Windows FILETIME */
static inline fftime_winftime fftime_to_winftime(const fftime *t)
{
ffuint64 d = t->sec * 1000000 * 10 + t->nsec / 100 + FFTIME_100NS;
fftime_winftime ft = {
.lo = (ffuint)d,
.hi = (ffuint)(d >> 32),
};
return ft;
}
#ifdef FF_WIN
static inline void fftime_now(fftime *t)
{
FILETIME ft;
#if FF_WIN >= 0x0602
GetSystemTimePreciseAsFileTime(&ft);
#else
typedef VOID WINAPI (*_GetSystemTimePreciseAsFileTime_t)(LPFILETIME);
static _GetSystemTimePreciseAsFileTime_t _GetSystemTimePreciseAsFileTime = (_GetSystemTimePreciseAsFileTime_t)-1;
if (_GetSystemTimePreciseAsFileTime == (_GetSystemTimePreciseAsFileTime_t)-1)
_GetSystemTimePreciseAsFileTime = (_GetSystemTimePreciseAsFileTime_t)(void*)GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "GetSystemTimePreciseAsFileTime");
if (_GetSystemTimePreciseAsFileTime != NULL)
_GetSystemTimePreciseAsFileTime(&ft);
else
GetSystemTimeAsFileTime(&ft);
#endif
*t = fftime_from_winftime((fftime_winftime*)&ft);
}
static inline void fftime_local(fftime_zone *tz)
{
tzset();
tz->off = -timezone;
tz->have_dst = daylight;
struct tm tm;
time_t gt = time(NULL);
gmtime_s(&tm, >);
tm.tm_isdst = -1;
time_t lt = mktime(&tm);
tz->is_dst = tm.tm_isdst;
tz->real_offset = gt - lt;
}
#else
/** Get UTC time (since Jan 1 1970) */
static inline void fftime_now(fftime *t)
{
struct timespec ts = {};
(void)clock_gettime(CLOCK_REALTIME, &ts);
*t = fftime_from_timespec(&ts);
}
/** Get local timezone */
static inline void fftime_local(fftime_zone *tz)
{
time_t gt = time(NULL);
struct tm tm;
#ifdef FF_LINUX
tzset();
tz->off = -timezone;
tz->have_dst = daylight;
#else
tzset();
localtime_r(>, &tm);
tz->off = tm.tm_gmtoff;
tz->have_dst = 0;
#endif
gmtime_r(>, &tm);
tm.tm_isdst = -1;
time_t lt = mktime(&tm);
tz->is_dst = tm.tm_isdst;
tz->real_offset = gt - lt;
}
#endif