1 // $Id: OS_NS_time.cpp 82693 2008-09-09 11:37:41Z johnnyw $
3 #include "ace/OS_NS_time.h"
5 ACE_RCSID(ace
, OS_NS_time
, "$Id: OS_NS_time.cpp 82693 2008-09-09 11:37:41Z johnnyw $")
7 #if !defined (ACE_HAS_INLINED_OSCALLS)
8 # include "ace/OS_NS_time.inl"
9 #endif /* ACE_HAS_INLINED_OSCALLS */
11 #if defined (ACE_LACKS_STRPTIME)
12 # include "ace/os_include/os_ctype.h"
13 #endif /* ACE_LACKS_STRPTIME */
15 #include "ace/OS_NS_Thread.h"
16 #include "ace/Object_Manager_Base.h"
18 #if defined (ACE_HAS_WINCE)
19 # include "ace/OS_NS_stdio.h" /* Need ACE_OS::sprintf() */
23 ACE_TCHAR
const * const ACE_OS_day_of_week_name
[] =
34 ACE_TCHAR
const * const ACE_OS_month_name
[] =
50 static ACE_TCHAR
const ACE_OS_CTIME_R_FMTSTR
[] = ACE_TEXT ("%3s %3s %02d %02d:%02d:%02d %04d\n");
51 } /* end blank namespace */
52 #endif /* ACE_HAS_WINCE */
54 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
56 # if defined (ACE_HAS_WINCE)
58 ACE_OS::ctime_r (const time_t *clock
, ACE_TCHAR
*buf
, int buflen
)
60 // buflen must be at least 26 wchar_t long.
61 if (buflen
< 26) // Again, 26 is a magic number.
66 // This is really stupid, converting FILETIME to timeval back and
67 // forth. It assumes FILETIME and DWORDLONG are the same structure
69 ULARGE_INTEGER _100ns
;
70 _100ns
.QuadPart
= (DWORDLONG
) *clock
* 10000 * 1000
71 + ACE_Time_Value::FILETIME_to_timval_skew
;
73 file_time
.dwLowDateTime
= _100ns
.LowPart
;
74 file_time
.dwHighDateTime
= _100ns
.HighPart
;
78 FileTimeToLocalFileTime (&file_time
, &localtime
);
79 FileTimeToSystemTime (&localtime
, &systime
);
80 ACE_OS::sprintf (buf
, ACE_OS_CTIME_R_FMTSTR
,
81 ACE_OS_day_of_week_name
[systime
.wDayOfWeek
],
82 ACE_OS_month_name
[systime
.wMonth
- 1],
90 # endif /* ACE_HAS_WINCE */
92 # if defined (ACE_LACKS_DIFFTIME)
94 ACE_OS::difftime (time_t t1
, time_t t0
)
96 /* return t1 - t0 in seconds */
97 struct tm tms
[2], *ptms
[2], temp
;
101 /* extract the tm structure from time_t */
102 ptms
[1] = ::gmtime_r (&t1
, &tms
[1]);
103 if (ptms
[1] == 0) return 0.0;
105 ptms
[0] = ::gmtime_r (&t0
, &tms
[0]);
106 if (ptms
[0] == 0) return 0.0;
108 /* make sure t1 is > t0 */
109 if (tms
[1].tm_year
< tms
[0].tm_year
)
111 else if (tms
[1].tm_year
== tms
[0].tm_year
)
113 if (tms
[1].tm_yday
< tms
[0].tm_yday
)
115 else if (tms
[1].tm_yday
== tms
[0].tm_yday
)
117 if (tms
[1].tm_hour
< tms
[0].tm_hour
)
119 else if (tms
[1].tm_hour
== tms
[0].tm_hour
)
121 if (tms
[1].tm_min
< tms
[0].tm_min
)
123 else if (tms
[1].tm_min
== tms
[0].tm_min
)
125 if (tms
[1].tm_sec
< tms
[0].tm_sec
)
133 temp
= tms
[0], tms
[0] = tms
[1], tms
[1] = temp
;
136 if (tms
[1].tm_year
> tms
[0].tm_year
)
138 // Accumulate the time until t[0] catches up to t[1]'s year.
139 seconds
= 60 - tms
[0].tm_sec
;
142 seconds
+= 60 * (60 - tms
[0].tm_min
);
145 seconds
+= 60*60 * (24 - tms
[0].tm_hour
);
149 # define ISLEAPYEAR(y) ((y)&3u?0:(y)%25u?1:(y)/25u&12?0:1)
151 if (ISLEAPYEAR(tms
[0].tm_year
))
152 seconds
+= 60*60*24 * (366 - tms
[0].tm_yday
);
154 seconds
+= 60*60*24 * (365 - tms
[0].tm_yday
);
159 while (tms
[1].tm_year
> tms
[0].tm_year
)
161 if (ISLEAPYEAR(tms
[0].tm_year
))
162 seconds
+= 60*60*24 * 366;
164 seconds
+= 60*60*24 * 365;
175 if (tms
[1].tm_sec
< tms
[0].tm_sec
)
177 if (tms
[1].tm_min
== 0)
179 if (tms
[1].tm_hour
== 0)
182 tms
[1].tm_hour
+= 24;
190 tms
[1].tm_sec
-= tms
[0].tm_sec
;
192 if (tms
[1].tm_min
< tms
[0].tm_min
)
194 if (tms
[1].tm_hour
== 0)
197 tms
[1].tm_hour
+= 24;
202 tms
[1].tm_min
-= tms
[0].tm_min
;
204 if (tms
[1].tm_hour
< tms
[0].tm_hour
)
207 tms
[1].tm_hour
+= 24;
209 tms
[1].tm_hour
-= tms
[0].tm_hour
;
211 tms
[1].tm_yday
-= tms
[0].tm_yday
;
214 // accumulate the seconds
215 seconds
+= tms
[1].tm_sec
;
216 seconds
+= 60 * tms
[1].tm_min
;
217 seconds
+= 60*60 * tms
[1].tm_hour
;
218 seconds
+= 60*60*24 * tms
[1].tm_yday
;
222 # endif /* ACE_LACKS_DIFFTIME */
225 ACE_OS::localtime_r (const time_t *t
, struct tm
*res
)
227 ACE_OS_TRACE ("ACE_OS::localtime_r");
228 #if defined (ACE_HAS_REENTRANT_FUNCTIONS)
229 # if defined (DIGITAL_UNIX)
230 ACE_OSCALL_RETURN (::_Plocaltime_r (t
, res
), struct tm
*, 0);
232 ACE_OSCALL_RETURN (::localtime_r (t
, res
), struct tm
*, 0);
233 # endif /* DIGITAL_UNIX */
234 #elif defined (ACE_HAS_TR24731_2005_CRT)
235 ACE_SECURECRTCALL (localtime_s (res
, t
), struct tm
*, 0, res
);
237 #elif !defined (ACE_HAS_WINCE)
240 ACE_UNUSED_ARG (res
);
241 struct tm
* res_ptr
= 0;
242 ACE_OSCALL (::localtime (t
), struct tm
*, 0, res_ptr
);
250 #elif defined (ACE_HAS_WINCE)
251 // This is really stupid, converting FILETIME to timeval back and
252 // forth. It assumes FILETIME and DWORDLONG are the same structure
255 TIME_ZONE_INFORMATION pTz
;
257 const unsigned short int __mon_yday
[2][13] =
260 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
262 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
265 ULARGE_INTEGER _100ns
;
266 ::GetTimeZoneInformation (&pTz
);
268 _100ns
.QuadPart
= (DWORDLONG
) *t
* 10000 * 1000 + ACE_Time_Value::FILETIME_to_timval_skew
;
270 file_time
.dwLowDateTime
= _100ns
.LowPart
;
271 file_time
.dwHighDateTime
= _100ns
.HighPart
;
275 FileTimeToLocalFileTime (&file_time
, &localtime
);
276 FileTimeToSystemTime (&localtime
, &systime
);
278 res
->tm_hour
= systime
.wHour
;
280 if(pTz
.DaylightBias
!=0)
286 iLeap
= (res
->tm_year
% 4 == 0 && (res
->tm_year
% 100 != 0 || res
->tm_year
% 400 == 0));
287 // based on leap select which group to use
289 res
->tm_mday
= systime
.wDay
;
290 res
->tm_min
= systime
.wMinute
;
291 res
->tm_mon
= systime
.wMonth
- 1;
292 res
->tm_sec
= systime
.wSecond
;
293 res
->tm_wday
= systime
.wDayOfWeek
;
294 res
->tm_yday
= __mon_yday
[iLeap
][systime
.wMonth
] + systime
.wDay
;
295 res
->tm_year
= systime
.wYear
;// this the correct year but bias the value to start at the 1900
296 res
->tm_year
= res
->tm_year
- 1900;
300 // @@ Same as ACE_OS::localtime (), you need to implement it
303 ACE_UNUSED_ARG (res
);
304 ACE_NOTSUP_RETURN (0);
305 #endif /* ACE_HAS_REENTRANT_FUNCTIONS */
309 ACE_OS::mktime (struct tm
*t
)
311 ACE_OS_TRACE ("ACE_OS::mktime");
312 # if defined (ACE_HAS_WINCE)
315 t_sys
.wSecond
= t
->tm_sec
;
316 t_sys
.wMinute
= t
->tm_min
;
317 t_sys
.wHour
= t
->tm_hour
;
318 t_sys
.wDay
= t
->tm_mday
;
319 t_sys
.wMonth
= t
->tm_mon
+ 1; // SYSTEMTIME is 1-indexed, tm is 0-indexed
320 t_sys
.wYear
= t
->tm_year
+ 1900; // SYSTEMTIME is real; tm is since 1900
321 t_sys
.wDayOfWeek
= t
->tm_wday
; // Ignored in below function call.
322 if (SystemTimeToFileTime (&t_sys
, &t_file
) == 0)
324 ACE_Time_Value
tv (t_file
);
327 # if defined (ACE_HAS_THREADS) && !defined (ACE_HAS_MT_SAFE_MKTIME)
329 # endif /* ACE_HAS_THREADS && ! ACE_HAS_MT_SAFE_MKTIME */
331 ACE_OSCALL_RETURN (ACE_STD_NAMESPACE::mktime (t
), time_t, (time_t) -1);
332 # endif /* ACE_HAS_WINCE */
335 #if defined (ACE_HAS_POWERPC_TIMER) && defined (ghs)
337 ACE_OS::readPPCTimeBase (u_long
&most
, u_long
&least
)
339 ACE_OS_TRACE ("ACE_OS::readPPCTimeBase");
341 // This function can't be inline because it depends on the arguments
342 // being in particular registers (r3 and r4), in conformance with the
343 // EABI standard. It would be nice if we knew how to put the variable
344 // names directly into the assembler instructions . . .
352 asm("stw r5, 0(r3)");
353 asm("stw r6, 0(r4)");
355 #endif /* ACE_HAS_POWERPC_TIMER && ghs */
357 #if defined (ACE_LACKS_STRPTIME) && !defined (ACE_REFUSE_STRPTIME_EMULATION)
359 ACE_OS::strptime_emulation (const char *buf
, const char *format
, struct tm
*tm
)
363 bool percent
= false;
368 ACE_OS::memset (tm
, 0, sizeof (struct tm
));
370 while (format
[fi
] != '\0')
377 case '%': // an escaped %
384 return const_cast<char*> (buf
+ bi
);
387 /* not supported yet: weekday via locale long/short names
388 case 'a': / * weekday via locale * /
390 case 'A': / * long/short names * /
394 /* not supported yet:
395 case 'b': / * month via locale * /
397 case 'B': / * long/short names * /
403 /* not supported yet:
404 case 'c': / * %x %X * /
408 /* not supported yet:
409 case 'C': / * date & time - * /
410 / * locale long format * /
414 case 'd': /* day of month (1-31) */
417 if (!ACE_OS::strptime_getnum
418 (buf
+ bi
, &tm
->tm_mday
, &bi
, &fi
, 1, 31))
419 return const_cast<char*> (buf
+ bi
);
423 case 'D': /* %m/%d/%y */
424 if (!ACE_OS::strptime_getnum
425 (buf
+ bi
, &tm
->tm_mon
, &bi
, &fi
, 1, 12))
426 return const_cast<char*> (buf
+ bi
);
432 return const_cast<char*> (buf
+ bi
);
436 if (!ACE_OS::strptime_getnum
437 (buf
+ bi
, &tm
->tm_mday
, &bi
, &fi
, 1, 31))
438 return const_cast<char*> (buf
+ bi
);
442 return const_cast<char*> (buf
+ bi
);
444 if (!ACE_OS::strptime_getnum
445 (buf
+ bi
, &tm
->tm_year
, &bi
, &fi
, 0, 99))
446 return const_cast<char*> (buf
+ bi
);
447 if (tm
->tm_year
< 69)
451 case 'H': /* hour (0-23) */
454 if (!ACE_OS::strptime_getnum
455 (buf
+ bi
, &tm
->tm_hour
, &bi
, &fi
, 0, 23))
456 return const_cast<char*> (buf
+ bi
);
459 /* not supported yet:
460 case 'I': / * hour (0-12) * /
466 case 'j': /* day of year (0-366) */
467 if (!ACE_OS::strptime_getnum
468 (buf
+ bi
, &tm
->tm_yday
, &bi
, &fi
, 1, 366))
469 return const_cast<char*> (buf
+ bi
);
474 case 'm': /* an escaped % */
475 if (!ACE_OS::strptime_getnum
476 (buf
+ bi
, &tm
->tm_mon
, &bi
, &fi
, 1, 12))
477 return const_cast<char*> (buf
+ bi
);
482 case 'M': /* minute (0-59) */
483 if (!ACE_OS::strptime_getnum
484 (buf
+ bi
, &tm
->tm_min
, &bi
, &fi
, 0, 59))
485 return const_cast<char*> (buf
+ bi
);
489 /* not supported yet:
490 case 'p': / * am or pm for locale * /
494 /* not supported yet:
495 case 'r': / * %I:%M:%S %p * /
499 case 'R': /* %H:%M */
500 if (!ACE_OS::strptime_getnum
501 (buf
+ bi
, &tm
->tm_hour
, &bi
, &fi
, 0, 23))
502 return const_cast<char*> (buf
+ bi
);
506 return const_cast<char*> (buf
+ bi
);
508 if (!ACE_OS::strptime_getnum
509 (buf
+ bi
, &tm
->tm_min
, &bi
, &fi
, 0, 59))
510 return const_cast<char*> (buf
+ bi
);
514 case 'S': /* seconds (0-61) */
515 if (!ACE_OS::strptime_getnum
516 (buf
+ bi
, &tm
->tm_sec
, &bi
, &fi
, 0, 61))
517 return const_cast<char*> (buf
+ bi
);
520 case 'T': /* %H:%M:%S */
521 if (!ACE_OS::strptime_getnum
522 (buf
+ bi
, &tm
->tm_hour
, &bi
, &fi
, 0, 23))
523 return const_cast<char*> (buf
+ bi
);
527 return const_cast<char*> (buf
+ bi
);
529 if (!ACE_OS::strptime_getnum
530 (buf
+ bi
, &tm
->tm_min
, &bi
, &fi
, 0, 59))
531 return const_cast<char*> (buf
+ bi
);
535 return const_cast<char*> (buf
+ bi
);
537 if (!ACE_OS::strptime_getnum
538 (buf
+ bi
, &tm
->tm_sec
, &bi
, &fi
, 0, 61))
539 return const_cast<char*> (buf
+ bi
);
543 case 'w': /* day of week (0=Sun-6) */
544 if (!ACE_OS::strptime_getnum
545 (buf
+ bi
, &tm
->tm_wday
, &bi
, &fi
, 0, 6))
546 return const_cast<char*> (buf
+ bi
);
550 /* not supported yet: date, based on locale
551 case 'x': / * date, based on locale * /
555 /* not supported yet:
556 case 'X': / * time, based on locale * /
560 case 'y': /* the year - 1900 (0-99) */
561 if (!ACE_OS::strptime_getnum
562 (buf
+ bi
, &tm
->tm_year
, &bi
, &fi
, 0, 99))
563 return const_cast<char*> (buf
+ bi
);
565 if (tm
->tm_year
< 69)
569 case 'Y': /* the full year (1999) */
570 if (!ACE_OS::strptime_getnum
571 (buf
+ bi
, &tm
->tm_year
, &bi
, &fi
, 0, 0))
572 return const_cast<char*> (buf
+ bi
);
577 default: /* unrecognised */
578 return const_cast<char*> (buf
+ bi
);
579 } /* switch (format[fi]) */
584 if (format
[fi
] == '%')
591 if (format
[fi
] == buf
[bi
])
597 return const_cast<char*> (buf
+ bi
);
600 } /* while (format[fi] */
602 return const_cast<char*> (buf
+ bi
);
606 ACE_OS::strptime_getnum (const char *buf
,
615 while (isdigit (buf
[i
]))
617 tmp
= (tmp
* 10) + (buf
[i
] - '0');
618 if (max
&& (tmp
> max
))
635 #endif /* ACE_LACKS_STRPTIME && !ACE_REFUSE_STRPTIME_EMULATION */
637 ACE_END_VERSIONED_NAMESPACE_DECL