1 mike 1.1 /*
2 **==============================================================================
3 **
4 ** Open Management Infrastructure (OMI)
5 **
6 ** Copyright (c) Microsoft Corporation
7 **
8 ** Licensed under the Apache License, Version 2.0 (the "License"); you may not
9 ** use this file except in compliance with the License. You may obtain a copy
10 ** of the License at
11 **
12 ** http://www.apache.org/licenses/LICENSE-2.0
13 **
14 ** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 ** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
16 ** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
17 ** MERCHANTABLITY OR NON-INFRINGEMENT.
18 **
19 ** See the Apache 2 License for the specific language governing permissions
20 ** and limitations under the License.
21 **
22 mike 1.1 **==============================================================================
23 */
24
25 #include "datetime.h"
26 #include <base/strings.h>
27 #include <base/io.h>
28 #include <base/helpers.h>
29
30 #if defined(_MSC_VER)
31 # include <windows.h>
32 # include <time.h>
33 #else
34 # include <unistd.h>
35 # include <sys/time.h>
36 # include <sys/types.h>
37 # include <time.h>
38 #endif
39
40 #define T MI_T
41
42 MI_BEGIN_NAMESPACE
43 mike 1.1
44 static int _StrToU32(
45 const MI_Char* s,
46 size_t offset,
47 size_t size,
48 MI_Uint32* x)
49 {
50 MI_Char buf[64];
51 MI_Char* end;
52
53 if (size >= MI_COUNT(buf))
54 return -1;
55
56 memcpy(buf, &s[offset], size * sizeof(MI_Char));
57 buf[size] = '\0';
58
59 *x = (MI_Uint32)Ztoul(buf, &end, 10);
60
61 if (*end != '\0')
62 return -1;
63
64 mike 1.1 /* Success */
65 return 0;
66 }
67
68 static bool _StrToDatetime(const MI_Char* s, MI_Datetime* x)
69 {
70 if (Zlen(s) != 25)
71 return false;
72
73 memset(x, 0, sizeof(MI_Datetime));
74
75 if (s[21] == '+' || s[21] == '-')
76 {
77 MI_Uint32 utc;
78
79 /* It must be a timestamp (YYYYMMDDHHMMSS.MMMMMMSUTC) */
80 if (_StrToU32(s, 0, 4, &x->u.timestamp.year) != 0 ||
81 _StrToU32(s, 4, 2, &x->u.timestamp.month) != 0 ||
82 _StrToU32(s, 6, 2, &x->u.timestamp.day) != 0 ||
83 _StrToU32(s, 8, 2, &x->u.timestamp.hour) != 0 ||
84 _StrToU32(s, 10, 2, &x->u.timestamp.minute) != 0 ||
85 mike 1.1 _StrToU32(s, 12, 2, &x->u.timestamp.second) != 0 ||
86 s[14] != '.' ||
87 _StrToU32(s, 15, 6, &x->u.timestamp.microseconds) != 0 ||
88 _StrToU32(s, 22, 3, &utc) != 0)
89 {
90 return false;
91 }
92
93 if (s[21] == '+')
94 x->u.timestamp.utc = (MI_Sint32)utc;
95 else
96 x->u.timestamp.utc = -(MI_Sint32)utc;
97
98 x->isTimestamp = 1;
99 }
100 else if (s[21] == ':')
101 {
102 /* It must be an interval (DDDDDDDDHHMMSS.MMMMMM:000) */
103 if (_StrToU32(s, 0, 8, &x->u.interval.days) != 0 ||
104 _StrToU32(s, 8, 2, &x->u.interval.hours) != 0 ||
105 _StrToU32(s, 10, 2, &x->u.interval.minutes) != 0 ||
106 mike 1.1 _StrToU32(s, 12, 2, &x->u.interval.seconds) != 0 ||
107 s[14] != '.' ||
108 _StrToU32(s, 15, 6, &x->u.interval.microseconds) != 0 ||
109 s[22] != '0' || s[23] != '0' || s[24] != '0')
110 {
111 return false;
112 }
113
114 x->isTimestamp = 0;
115 }
116 else
117 {
118 return false;
119 }
120
121 return true;
122 }
123
124 static int _GetCurrentTimeInUsec(MI_Uint64& usec)
125 {
126 #if defined(_MSC_VER)
127 mike 1.1 FILETIME ft;
128 ULARGE_INTEGER tmp;
129
130 GetSystemTimeAsFileTime(&ft);
131 tmp.u.LowPart = ft.dwLowDateTime;
132 tmp.u.HighPart = ft.dwHighDateTime;
133 tmp.QuadPart -= 0X19DB1DED53E8000;
134 usec = tmp.QuadPart / (UINT64)10;
135
136 return 0;
137 #else
138 struct timeval tv;
139 struct timezone tz;
140 memset(&tv, 0, sizeof(tv));
141 memset(&tz, 0, sizeof(tz));
142
143 if (gettimeofday(&tv, &tz) != 0)
144 return -1;
145
146 usec = (MI_Uint64)tv.tv_sec * (MI_Uint64)1000000 + (MI_Uint64)tv.tv_usec;
147 return 0;
148 mike 1.1 #endif
149 }
150
151 Datetime::Datetime(
152 MI_Uint32 year,
153 MI_Uint32 month,
154 MI_Uint32 day,
155 MI_Uint32 hour,
156 MI_Uint32 minute,
157 MI_Uint32 second,
158 MI_Uint32 microseconds,
159 MI_Sint32 utc)
160 {
161 _rep.isTimestamp = MI_TRUE;
162 _rep.u.timestamp.year = year;
163 _rep.u.timestamp.month = month;
164 _rep.u.timestamp.day = day;
165 _rep.u.timestamp.hour = hour;
166 _rep.u.timestamp.minute = minute;
167 _rep.u.timestamp.second = second;
168 _rep.u.timestamp.microseconds = microseconds;
169 mike 1.1 _rep.u.timestamp.utc = utc;
170 }
171
172 Datetime::Datetime(
173 MI_Uint32 days,
174 MI_Uint32 hours,
175 MI_Uint32 minutes,
176 MI_Uint32 seconds,
177 MI_Uint32 microseconds)
178 {
179 _rep.isTimestamp = MI_FALSE;
180 _rep.u.interval.days = days;
181 _rep.u.interval.hours = hours;
182 _rep.u.interval.minutes = minutes;
183 _rep.u.interval.seconds = seconds;
184 _rep.u.interval.microseconds = microseconds;
185 }
186
187 bool Datetime::Set(
188 MI_Uint32 year,
189 MI_Uint32 month,
190 mike 1.1 MI_Uint32 day,
191 MI_Uint32 hour,
192 MI_Uint32 minute,
193 MI_Uint32 second,
194 MI_Uint32 microseconds,
195 MI_Sint32 utc)
196 {
197 // ATTN: check ranges!
198 _rep.isTimestamp = MI_TRUE;
199 _rep.u.timestamp.year = year;
200 _rep.u.timestamp.month = month;
201 _rep.u.timestamp.day = day;
202 _rep.u.timestamp.hour = hour;
203 _rep.u.timestamp.minute = minute;
204 _rep.u.timestamp.second = second;
205 _rep.u.timestamp.microseconds = microseconds;
206 _rep.u.timestamp.utc = utc;
207 return true;
208 }
209
210 bool Datetime::Set(
211 mike 1.1 MI_Uint32 days,
212 MI_Uint32 hours,
213 MI_Uint32 minutes,
214 MI_Uint32 seconds,
215 MI_Uint32 microseconds)
216 {
217 // ATTN: check ranges!
218 _rep.isTimestamp = MI_FALSE;
219 _rep.u.interval.days = days;
220 _rep.u.interval.hours = hours;
221 _rep.u.interval.minutes = minutes;
222 _rep.u.interval.seconds = seconds;
223 _rep.u.interval.microseconds = microseconds;
224
225 return 0;
226 }
227
228 bool Datetime::Set(const MI_Char* str)
229 {
230 if (!_StrToDatetime(str, &_rep))
231 {
232 mike 1.1 Clear();
233 return false;
234 }
235
236 return true;
237 }
238
239 bool Datetime::Get(
240 MI_Uint32& year,
241 MI_Uint32& month,
242 MI_Uint32& day,
243 MI_Uint32& hour,
244 MI_Uint32& minute,
245 MI_Uint32& second,
246 MI_Uint32& microseconds,
247 MI_Sint32& utc) const
248 {
249 if (!_rep.isTimestamp)
250 return false;
251
252 year = _rep.u.timestamp.year;
253 mike 1.1 month = _rep.u.timestamp.month;
254 day = _rep.u.timestamp.day;
255 hour = _rep.u.timestamp.hour;
256 minute = _rep.u.timestamp.minute;
257 second = _rep.u.timestamp.second;
258 microseconds = _rep.u.timestamp.microseconds;
259 utc = _rep.u.timestamp.utc;
260
261 return true;
262 }
263
264 bool Datetime::Get(
265 MI_Uint32& days,
266 MI_Uint32& hours,
267 MI_Uint32& minutes,
268 MI_Uint32& seconds,
269 MI_Uint32& microseconds) const
270 {
271 if (_rep.isTimestamp)
272 return false;
273
274 mike 1.1 days = _rep.u.interval.days;
275 hours = _rep.u.interval.hours;
276 minutes = _rep.u.interval.minutes;
277 seconds = _rep.u.interval.seconds;
278 microseconds = _rep.u.interval.microseconds;
279
280 return true;
281 }
282
283 void Datetime::ToString(MI_Char buffer[26]) const
284 {
285 const MI_Datetime* p = (const MI_Datetime*)&_rep;
286 DatetimeToStr(p, buffer);
287 }
288
289 bool Datetime::Equal(const Datetime& x) const
290 {
291 if (_rep.isTimestamp)
292 {
293 return x._rep.isTimestamp &&
294 _rep.u.timestamp.year == x._rep.u.timestamp.year &&
295 mike 1.1 _rep.u.timestamp.month == x._rep.u.timestamp.month &&
296 _rep.u.timestamp.day == x._rep.u.timestamp.day &&
297 _rep.u.timestamp.hour == x._rep.u.timestamp.hour &&
298 _rep.u.timestamp.minute == x._rep.u.timestamp.minute &&
299 _rep.u.timestamp.second == x._rep.u.timestamp.second &&
300 _rep.u.timestamp.microseconds == x._rep.u.timestamp.microseconds &&
301 _rep.u.timestamp.utc == x._rep.u.timestamp.utc;
302 }
303 else
304 {
305 return !x._rep.isTimestamp &&
306 _rep.u.interval.days == x._rep.u.interval.days &&
307 _rep.u.interval.hours == x._rep.u.interval.hours &&
308 _rep.u.interval.minutes == x._rep.u.interval.minutes &&
309 _rep.u.interval.seconds == x._rep.u.interval.seconds &&
310 _rep.u.interval.microseconds == x._rep.u.interval.microseconds;
311 }
312 }
313
314 void Datetime::Print(FILE* os) const
315 {
316 mike 1.1 MI_Char buffer[26];
317 ToString(buffer);
318 Fzprintf(os, T("%s"), buffer);
319 }
320
321 #define TIMESTAMP_SIZE 128
322
323 bool Datetime::SetCurrent()
324 {
325 /* ATTN: get UTC offset */
326 MI_Uint64 usec;
327
328 if (_GetCurrentTimeInUsec(usec) != 0)
329 return false;
330
331 MI_Uint32 year;
332 MI_Uint32 month;
333 MI_Uint32 day;
334 MI_Uint32 hour;
335 MI_Uint32 minute;
336 MI_Uint32 second;
337 mike 1.1 MI_Uint32 microseconds = 0;
338 MI_Sint32 utc = 0;
339
340 #if defined(_MSC_VER)
341 {
342 time_t t = usec / 1000000;
343 struct tm tm;
344 localtime_s(&tm, &t);
345 year = tm.tm_year + 1900;
346 month = tm.tm_mon + 1;
347 day = tm.tm_mday;
348 hour = tm.tm_hour;
349 minute = tm.tm_min;
350 second = tm.tm_sec;
351 microseconds = (MI_Uint32)(usec % MI_Uint64(1000000));
352 }
353 #else
354 {
355 time_t t = usec / 1000000;
356 struct tm tm;
357 localtime_r(&t, &tm);
358 mike 1.1 year = tm.tm_year + 1900;
359 month = tm.tm_mon + 1;
360 day = tm.tm_mday;
361 hour = tm.tm_hour;
362 minute = tm.tm_min;
363 second = tm.tm_sec;
364 microseconds = (MI_Uint32)(usec % MI_Uint64(1000000));
365 }
366 #endif
367
368 return Set(year, month, day, hour, minute, second, microseconds, utc);
369 }
370
371 Datetime Datetime::Now()
372 {
373 Datetime result;
374 result.SetCurrent();
375 return result;
376 }
377
378 MI_END_NAMESPACE
|