(file) Return to datetime.cpp CVS log (file) (dir) Up to [OMI] / omi / micxx

  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

ViewCVS 0.9.2