(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 krisbash 1.3 #include <pal/strings.h>
 27              #include <pal/format.h>
 28 mike     1.1 #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              
 44              static int _StrToU32(
 45                  const MI_Char* s, 
 46                  size_t offset, 
 47                  size_t size, 
 48                  MI_Uint32* x)
 49 mike     1.1 {
 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 krisbash 1.3     *x = (MI_Uint32)Tcstoul(buf, &end, 10);
 60 mike     1.1 
 61                  if (*end != '\0')
 62                      return -1;
 63              
 64                  /* Success */
 65                  return 0;
 66              }
 67              
 68              static bool _StrToDatetime(const MI_Char* s, MI_Datetime* x)
 69              {
 70 krisbash 1.3     if (Tcslen(s) != 25)
 71 mike     1.1         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                          _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 mike     1.1 
 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                          _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 mike     1.1 
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                  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 mike     1.1     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              #endif
149              }
150              
151              Datetime::Datetime(
152                  MI_Uint32 year,
153                  MI_Uint32 month,
154                  MI_Uint32 day,
155 mike     1.1     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                  _rep.u.timestamp.utc = utc;
170              }
171              
172              Datetime::Datetime(
173                  MI_Uint32 days,
174                  MI_Uint32 hours,
175                  MI_Uint32 minutes,
176 mike     1.1     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                  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 mike     1.1     // 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                  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 mike     1.1     _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                      Clear();
233                      return false;
234                  }
235              
236                  return true;
237              }
238              
239 mike     1.1 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                  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 mike     1.1 
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                  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 mike     1.1 }
282              
283 krisbash 1.3 _Use_decl_annotations_
284 mike     1.1 void Datetime::ToString(MI_Char buffer[26]) const
285              {
286                  const MI_Datetime* p = (const MI_Datetime*)&_rep;
287                  DatetimeToStr(p, buffer);
288              }
289              
290              bool Datetime::Equal(const Datetime& x) const
291              {
292                  if (_rep.isTimestamp)
293                  {
294                      return x._rep.isTimestamp &&
295                          _rep.u.timestamp.year == x._rep.u.timestamp.year &&
296                          _rep.u.timestamp.month == x._rep.u.timestamp.month &&
297                          _rep.u.timestamp.day == x._rep.u.timestamp.day &&
298                          _rep.u.timestamp.hour == x._rep.u.timestamp.hour &&
299                          _rep.u.timestamp.minute == x._rep.u.timestamp.minute &&
300                          _rep.u.timestamp.second == x._rep.u.timestamp.second &&
301                          _rep.u.timestamp.microseconds == x._rep.u.timestamp.microseconds &&
302                          _rep.u.timestamp.utc == x._rep.u.timestamp.utc;
303                  }
304                  else
305 mike     1.1     {
306                      return !x._rep.isTimestamp &&
307                          _rep.u.interval.days == x._rep.u.interval.days &&
308                          _rep.u.interval.hours == x._rep.u.interval.hours &&
309                          _rep.u.interval.minutes == x._rep.u.interval.minutes &&
310                          _rep.u.interval.seconds == x._rep.u.interval.seconds &&
311                          _rep.u.interval.microseconds == x._rep.u.interval.microseconds;
312                  }
313              }
314              
315              void Datetime::Print(FILE* os) const
316              {
317                  MI_Char buffer[26];
318                  ToString(buffer);
319 krisbash 1.3     Ftprintf(os, PAL_T("%T"), tcs(buffer));
320 mike     1.1 }
321              
322              #define TIMESTAMP_SIZE 128
323              
324              bool Datetime::SetCurrent()
325              {
326                  MI_Uint32 year;
327                  MI_Uint32 month;
328                  MI_Uint32 day;
329                  MI_Uint32 hour;
330                  MI_Uint32 minute;
331                  MI_Uint32 second;
332                  MI_Uint32 microseconds = 0;
333                  MI_Sint32 utc = 0;
334              
335              #if defined(_MSC_VER)
336                  {
337 krisbash 1.3         SYSTEMTIME st;
338                      GetLocalTime(&st);
339              
340                      year = st.wYear;
341                      month = st.wMonth;
342                      day = st.wDay;
343                      hour = st.wHour;
344                      minute = st.wMinute;
345                      second = st.wSecond;
346                      microseconds = st.wMilliseconds*1000;
347 mike     1.1     }
348              #else
349 krisbash 1.3     /* ATTN: get UTC offset */
350                  MI_Uint64 usec;
351              
352                  if (_GetCurrentTimeInUsec(usec) != 0)
353                      return false;
354              
355              
356 mike     1.1     {
357                      time_t t = usec / 1000000;
358                      struct tm tm;
359                      localtime_r(&t, &tm);
360                      year = tm.tm_year + 1900;
361                      month = tm.tm_mon + 1;
362                      day = tm.tm_mday;
363                      hour = tm.tm_hour;
364                      minute = tm.tm_min;
365                      second = tm.tm_sec;
366                      microseconds = (MI_Uint32)(usec % MI_Uint64(1000000));
367                  }
368              #endif
369              
370                  return Set(year, month, day, hour, minute, second, microseconds, utc);
371              }
372              
373              Datetime Datetime::Now()
374              {
375                  Datetime result;
376                  result.SetCurrent();
377 mike     1.1     return result;
378              }
379              
380              MI_END_NAMESPACE

ViewCVS 0.9.2