1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/msw/wince/time.cpp
3 // Purpose:     Implements missing time functionality for WinCE
4 // Author:      Marco Cavallini (MCK) - wx@koansoftware.com
5 // Modified by: Vadim Zeitlin for VC8 support
6 // Created:     31-08-2003
7 // RCS-ID:      $Id: time.cpp 43076 2006-11-04 23:27:15Z VZ $
8 // Copyright:   (c) Marco Cavallini
9 // Licence:     wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11 
12 // ===========================================================================
13 // declarations
14 // ===========================================================================
15 
16 // ---------------------------------------------------------------------------
17 // headers
18 // ---------------------------------------------------------------------------
19 
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
22 
23 #ifdef __BORLANDC__
24     #pragma hdrstop
25 #endif
26 
27 #ifndef WX_PRECOMP
28     #include "wx/msw/wrapwin.h"
29 #endif
30 
31 #include "wx/msw/wince/time.h"
32 
33 #if defined(__VISUALC__) && (__VISUALC__ >= 1400)
34 
35 // VC8 does provide the time functions but not the standard ones
36 #include <altcecrt.h>
37 
time(time_t * t)38 time_t __cdecl time(time_t *t)
39 {
40     __time64_t t64;
41     if ( !_time64(&t64) )
42         return (time_t)-1;
43 
44     if ( t )
45         *t = (time_t)t64;
46 
47     return (time_t)t64;
48 }
49 
mktime(struct tm * t)50 time_t __cdecl mktime(struct tm *t)
51 {
52     return (time_t)_mktime64(t);
53 }
54 
55 #else // !VC8
56 
57 /////////////////////////////////////////////////////////////////////////////////////////////
58 //                                                                                         //
59 //                             strftime() - taken from OpenBSD                             //
60 //                                                                                         //
61 /////////////////////////////////////////////////////////////////////////////////////////////
62 
63 #define IN_NONE	0
64 #define IN_SOME	1
65 #define IN_THIS	2
66 #define IN_ALL	3
67 #define CHAR_BIT      8
68 
69 #define TYPE_BIT(type)	(sizeof (type) * CHAR_BIT)
70 #define TYPE_SIGNED(type) (((type) -1) < 0)
71 
72 #define INT_STRLEN_MAXIMUM(type) \
73     ((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 1000 + 1 + TYPE_SIGNED(type))
74 
75 #define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
76 
77 #define MONSPERYEAR	12
78 #define DAYSPERWEEK	7
79 #define TM_YEAR_BASE	1900
80 #define HOURSPERDAY	24
81 #define DAYSPERNYEAR	365
82 #define DAYSPERLYEAR	366
83 
84 static char		wildabbr[] = "WILDABBR";
85 
86 char *			tzname[2] = {
87 	wildabbr,
88 	wildabbr
89 };
90 
91 
92 #define Locale	(&C_time_locale)
93 
94 struct lc_time_T {
95 	const char *	mon[MONSPERYEAR];
96 	const char *	month[MONSPERYEAR];
97 	const char *	wday[DAYSPERWEEK];
98 	const char *	weekday[DAYSPERWEEK];
99 	const char *	X_fmt;
100 	const char *	x_fmt;
101 	const char *	c_fmt;
102 	const char *	am;
103 	const char *	pm;
104 	const char *	date_fmt;
105 };
106 
107 static const struct lc_time_T	C_time_locale = {
108 	{
109 		"Jan", "Feb", "Mar", "Apr", "May", "Jun",
110 		"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
111 	}, {
112 		"January", "February", "March", "April", "May", "June",
113 		"July", "August", "September", "October", "November", "December"
114 	}, {
115 		"Sun", "Mon", "Tue", "Wed",
116 		"Thu", "Fri", "Sat"
117 	}, {
118 		"Sunday", "Monday", "Tuesday", "Wednesday",
119 		"Thursday", "Friday", "Saturday"
120 	},
121 
122 	/* X_fmt */
123 	"%H:%M:%S",
124 
125 	/*
126 	** x_fmt
127 	** C99 requires this format.
128 	** Using just numbers (as here) makes Quakers happier;
129 	** it's also compatible with SVR4.
130 	*/
131 	"%m/%d/%y",
132 
133 	/*
134 	** c_fmt
135 	** C99 requires this format.
136 	** Previously this code used "%D %X", but we now conform to C99.
137 	** Note that
138 	**      "%a %b %d %H:%M:%S %Y"
139 	** is used by Solaris 2.3.
140 	*/
141 	"%a %b %e %T %Y",
142 
143 	/* am */
144 	"AM",
145 
146 	/* pm */
147 	"PM",
148 
149 	/* date_fmt */
150 	"%a %b %e %H:%M:%S %Z %Y"
151 };
152 
153 
154 static char *
_add(const char * str,char * pt,const char * const ptlim)155 _add(const char * str, char * pt, const char * const ptlim)
156 {
157 	while (pt < ptlim && (*pt = *str++) != '\0')
158 		++pt;
159 	return pt;
160 }
161 
162 
163 static char *
_conv(const int n,const char * const format,char * const pt,const char * const ptlim)164 _conv(const int n, const char * const format, char * const pt, const char * const ptlim)
165 {
166 	char	buf[INT_STRLEN_MAXIMUM(int) + 1];
167 
168 	(void) _snprintf(buf, sizeof buf, format, n);
169 	return _add(buf, pt, ptlim);
170 }
171 
172 
173 static char *
_fmt(const char * format,const struct tm * const t,char * pt,const char * const ptlim,int * warnp)174 _fmt(const char * format, const struct tm * const t, char * pt, const char * const ptlim, int * warnp)
175 {
176 	for ( ; *format; ++format) {
177 		if (*format == '%') {
178 label:
179 			switch (*++format) {
180 			case '\0':
181 				--format;
182 				break;
183 			case 'A':
184 				pt = _add((t->tm_wday < 0 ||
185 					t->tm_wday >= DAYSPERWEEK) ?
186 					"?" : Locale->weekday[t->tm_wday],
187 					pt, ptlim);
188 				continue;
189 			case 'a':
190 				pt = _add((t->tm_wday < 0 ||
191 					t->tm_wday >= DAYSPERWEEK) ?
192 					"?" : Locale->wday[t->tm_wday],
193 					pt, ptlim);
194 				continue;
195 			case 'B':
196 				pt = _add((t->tm_mon < 0 ||
197 					t->tm_mon >= MONSPERYEAR) ?
198 					"?" : Locale->month[t->tm_mon],
199 					pt, ptlim);
200 				continue;
201 			case 'b':
202 			case 'h':
203 				pt = _add((t->tm_mon < 0 ||
204 					t->tm_mon >= MONSPERYEAR) ?
205 					"?" : Locale->mon[t->tm_mon],
206 					pt, ptlim);
207 				continue;
208 			case 'C':
209 				/*
210 				** %C used to do a...
211 				**	_fmt("%a %b %e %X %Y", t);
212 				** ...whereas now POSIX 1003.2 calls for
213 				** something completely different.
214 				** (ado, 1993-05-24)
215 				*/
216 				pt = _conv((t->tm_year + TM_YEAR_BASE) / 100,
217 					"%02d", pt, ptlim);
218 				continue;
219 			case 'c':
220 				{
221 				int warn2 = IN_SOME;
222 
223 				pt = _fmt(Locale->c_fmt, t, pt, ptlim, warnp);
224 				if (warn2 == IN_ALL)
225 					warn2 = IN_THIS;
226 				if (warn2 > *warnp)
227 					*warnp = warn2;
228 				}
229 				continue;
230 			case 'D':
231 				pt = _fmt("%m/%d/%y", t, pt, ptlim, warnp);
232 				continue;
233 			case 'd':
234 				pt = _conv(t->tm_mday, "%02d", pt, ptlim);
235 				continue;
236 			case 'E':
237 			case 'O':
238 				/*
239 				** C99 locale modifiers.
240 				** The sequences
241 				**	%Ec %EC %Ex %EX %Ey %EY
242 				**	%Od %oe %OH %OI %Om %OM
243 				**	%OS %Ou %OU %OV %Ow %OW %Oy
244 				** are supposed to provide alternate
245 				** representations.
246 				*/
247 				goto label;
248 			case 'e':
249 				pt = _conv(t->tm_mday, "%2d", pt, ptlim);
250 				continue;
251 			case 'F':
252 				pt = _fmt("%Y-%m-%d", t, pt, ptlim, warnp);
253 				continue;
254 			case 'H':
255 				pt = _conv(t->tm_hour, "%02d", pt, ptlim);
256 				continue;
257 			case 'I':
258 				pt = _conv((t->tm_hour % 12) ?
259 					(t->tm_hour % 12) : 12,
260 					"%02d", pt, ptlim);
261 				continue;
262 			case 'j':
263 				pt = _conv(t->tm_yday + 1, "%03d", pt, ptlim);
264 				continue;
265 			case 'k':
266 				/*
267 				** This used to be...
268 				**	_conv(t->tm_hour % 12 ?
269 				**		t->tm_hour % 12 : 12, 2, ' ');
270 				** ...and has been changed to the below to
271 				** match SunOS 4.1.1 and Arnold Robbins'
272 				** strftime version 3.0.  That is, "%k" and
273 				** "%l" have been swapped.
274 				** (ado, 1993-05-24)
275 				*/
276 				pt = _conv(t->tm_hour, "%2d", pt, ptlim);
277 				continue;
278 #ifdef KITCHEN_SINK
279 			case 'K':
280 				/*
281 				** After all this time, still unclaimed!
282 				*/
283 				pt = _add("kitchen sink", pt, ptlim);
284 				continue;
285 #endif /* defined KITCHEN_SINK */
286 			case 'l':
287 				/*
288 				** This used to be...
289 				**	_conv(t->tm_hour, 2, ' ');
290 				** ...and has been changed to the below to
291 				** match SunOS 4.1.1 and Arnold Robbin's
292 				** strftime version 3.0.  That is, "%k" and
293 				** "%l" have been swapped.
294 				** (ado, 1993-05-24)
295 				*/
296 				pt = _conv((t->tm_hour % 12) ?
297 					(t->tm_hour % 12) : 12,
298 					"%2d", pt, ptlim);
299 				continue;
300 			case 'M':
301 				pt = _conv(t->tm_min, "%02d", pt, ptlim);
302 				continue;
303 			case 'm':
304 				pt = _conv(t->tm_mon + 1, "%02d", pt, ptlim);
305 				continue;
306 			case 'n':
307 				pt = _add("\n", pt, ptlim);
308 				continue;
309 			case 'p':
310 				pt = _add((t->tm_hour >= (HOURSPERDAY / 2)) ?
311 					Locale->pm :
312 					Locale->am,
313 					pt, ptlim);
314 				continue;
315 			case 'R':
316 				pt = _fmt("%H:%M", t, pt, ptlim, warnp);
317 				continue;
318 			case 'r':
319 				pt = _fmt("%I:%M:%S %p", t, pt, ptlim, warnp);
320 				continue;
321 			case 'S':
322 				pt = _conv(t->tm_sec, "%02d", pt, ptlim);
323 				continue;
324 			case 's':
325 				{
326 					struct tm	tm;
327 					char		buf[INT_STRLEN_MAXIMUM(
328 								time_t) + 1];
329 					time_t		mkt;
330 
331 					tm = *t;
332 					mkt = mktime(&tm);
333 					if (TYPE_SIGNED(time_t))
334 						(void) _snprintf(buf, sizeof buf,
335 						    "%ld", (long) mkt);
336 					else	(void) _snprintf(buf, sizeof buf,
337 						    "%lu", (unsigned long) mkt);
338 					pt = _add(buf, pt, ptlim);
339 				}
340 				continue;
341 			case 'T':
342 				pt = _fmt("%H:%M:%S", t, pt, ptlim, warnp);
343 				continue;
344 			case 't':
345 				pt = _add("\t", pt, ptlim);
346 				continue;
347 			case 'U':
348 				pt = _conv((t->tm_yday + DAYSPERWEEK -
349 					t->tm_wday) / DAYSPERWEEK,
350 					"%02d", pt, ptlim);
351 				continue;
352 			case 'u':
353 				/*
354 				** From Arnold Robbins' strftime version 3.0:
355 				** "ISO 8601: Weekday as a decimal number
356 				** [1 (Monday) - 7]"
357 				** (ado, 1993-05-24)
358 				*/
359 				pt = _conv((t->tm_wday == 0) ?
360 					DAYSPERWEEK : t->tm_wday,
361 					"%d", pt, ptlim);
362 				continue;
363 			case 'V':	/* ISO 8601 week number */
364 			case 'G':	/* ISO 8601 year (four digits) */
365 			case 'g':	/* ISO 8601 year (two digits) */
366 				{
367 					int	year;
368 					int	yday;
369 					int	wday;
370 					int	w;
371 
372 					year = t->tm_year + TM_YEAR_BASE;
373 					yday = t->tm_yday;
374 					wday = t->tm_wday;
375 					for ( ; ; ) {
376 						int	len;
377 						int	bot;
378 						int	top;
379 
380 						len = isleap(year) ?
381 							DAYSPERLYEAR :
382 							DAYSPERNYEAR;
383 						/*
384 						** What yday (-3 ... 3) does
385 						** the ISO year begin on?
386 						*/
387 						bot = ((yday + 11 - wday) %
388 							DAYSPERWEEK) - 3;
389 						/*
390 						** What yday does the NEXT
391 						** ISO year begin on?
392 						*/
393 						top = bot -
394 							(len % DAYSPERWEEK);
395 						if (top < -3)
396 							top += DAYSPERWEEK;
397 						top += len;
398 						if (yday >= top) {
399 							++year;
400 							w = 1;
401 							break;
402 						}
403 						if (yday >= bot) {
404 							w = 1 + ((yday - bot) /
405 								DAYSPERWEEK);
406 							break;
407 						}
408 						--year;
409 						yday += isleap(year) ?
410 							DAYSPERLYEAR :
411 							DAYSPERNYEAR;
412 					}
413 					if (*format == 'V')
414 						pt = _conv(w, "%02d",
415 							pt, ptlim);
416 					else if (*format == 'g') {
417 						*warnp = IN_ALL;
418 						pt = _conv(year % 100, "%02d",
419 							pt, ptlim);
420 					} else	pt = _conv(year, "%04d",
421 							pt, ptlim);
422 				}
423 				continue;
424 			case 'v':
425 				pt = _fmt("%e-%b-%Y", t, pt, ptlim, warnp);
426 				continue;
427 			case 'W':
428 				pt = _conv((t->tm_yday + DAYSPERWEEK -
429 					(t->tm_wday ?
430 					(t->tm_wday - 1) :
431 					(DAYSPERWEEK - 1))) / DAYSPERWEEK,
432 					"%02d", pt, ptlim);
433 				continue;
434 			case 'w':
435 				pt = _conv(t->tm_wday, "%d", pt, ptlim);
436 				continue;
437 			case 'X':
438 				pt = _fmt(Locale->X_fmt, t, pt, ptlim, warnp);
439 				continue;
440 			case 'x':
441 				{
442 				int	warn2 = IN_SOME;
443 
444 				pt = _fmt(Locale->x_fmt, t, pt, ptlim, &warn2);
445 				if (warn2 == IN_ALL)
446 					warn2 = IN_THIS;
447 				if (warn2 > *warnp)
448 					*warnp = warn2;
449 				}
450 				continue;
451 			case 'y':
452 				*warnp = IN_ALL;
453 				pt = _conv((t->tm_year + TM_YEAR_BASE) % 100,
454 					"%02d", pt, ptlim);
455 				continue;
456 			case 'Y':
457 				pt = _conv(t->tm_year + TM_YEAR_BASE, "%04d",
458 					pt, ptlim);
459 				continue;
460 			case 'Z':
461 				if (t->tm_isdst >= 0)
462 					pt = _add(tzname[t->tm_isdst != 0],
463 						pt, ptlim);
464 				/*
465 				** C99 says that %Z must be replaced by the
466 				** empty string if the time zone is not
467 				** determinable.
468 				*/
469 				continue;
470 			case 'z':
471 				{
472 				int		diff = -timezone;
473 				char const *	sign;
474 
475 				if (diff < 0) {
476 					sign = "-";
477 					diff = -diff;
478 				} else	sign = "+";
479 				pt = _add(sign, pt, ptlim);
480 				diff /= 60;
481 				pt = _conv((diff/60)*100 + diff%60,
482 					"%04d", pt, ptlim);
483 				}
484 				continue;
485 			case '+':
486 				pt = _fmt(Locale->date_fmt, t, pt, ptlim,
487 					warnp);
488 				continue;
489 			case '%':
490 			default:
491 				break;
492 			}
493 		}
494 		if (pt == ptlim)
495 			break;
496 		*pt++ = *format;
497 	}
498 	return pt;
499 }
500 
501 size_t
strftime(char * const s,const size_t maxsize,const char * format,const struct tm * const t)502 strftime(char * const s, const size_t maxsize, const char *format, const struct tm * const t)
503 {
504 	char *	p;
505 	int	warn;
506 
507 	//tzset();
508 
509 	warn = IN_NONE;
510 	p = _fmt(((format == NULL) ? "%c" : format), t, s, s + maxsize, &warn);
511 
512 	if (p == s + maxsize) {
513 		if (maxsize > 0)
514 			s[maxsize - 1] = '\0';
515 		return 0;
516 	}
517 	*p = '\0';
518 	return p - s;
519 }
520 
521 extern "C"
522 {
523 
524 /* Not needed in VS Studio 2005 */
525 
wcsftime(wchar_t * s,const size_t maxsize,const wchar_t * format,const struct tm * t)526 size_t wcsftime(wchar_t *s,
527                 const size_t maxsize,
528                 const wchar_t *format,
529                 const struct tm *t)
530 {
531     wxCharBuffer sBuf(maxsize/sizeof(wchar_t));
532 
533     wxString formatStr(format);
534     wxCharBuffer bufFormatStr(formatStr.mb_str());
535 
536     size_t sz = strftime(sBuf.data(), maxsize/sizeof(wchar_t), bufFormatStr, t);
537 
538     wxMB2WC(s, sBuf, maxsize);
539 
540     return sz;
541 }
542 
543 } /* extern "C" */
544 
545 #define is_leap(y)   (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0))
546 #define SECONDS_IN_ONE_MINUTE      60
547 #define DAYS_IN_ONE_YEAR          365
548 #define SECONDS_IN_ONE_MIN         60
549 #define SECONDS_IN_ONE_HOUR      3600
550 #define SECONDS_IN_ONE_DAY      86400
551 #define DEFAULT_TIMEZONE        28800
552 #define DO_GMTIME                   0
553 #define DO_LOCALTIME                1
554 
555 
556 long timezone ; // global variable
557 
558 
559 ////////////////////////////////////////////////////////////////////////
560 // Common code for localtime and gmtime (static)
561 ////////////////////////////////////////////////////////////////////////
562 
common_localtime(const time_t * t,BOOL bLocal)563 static struct tm * __cdecl common_localtime(const time_t *t, BOOL bLocal)
564 {
565     wxLongLong i64;
566     FILETIME   ft;
567     wxString str ;
568     SYSTEMTIME SystemTime;
569     TIME_ZONE_INFORMATION pTz;
570     static struct tm st_res ;             // data holder
571     static struct tm * res = &st_res ;    // data pointer
572     int iLeap;
573     const unsigned short int __mon_yday[2][13] =
574     {
575         // Normal years
576         { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
577         // Leap years
578         { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
579     };
580 
581     if (!*t)
582         ::GetLocalTime(&SystemTime);
583     else
584     {
585         i64 = *t;
586         i64 = i64 * 10000000 + 116444736000000000;
587 
588         ft.dwLowDateTime  = i64.GetLo();
589         ft.dwHighDateTime = i64.GetHi();
590 
591         ::FileTimeToSystemTime(&ft, &SystemTime);
592     }
593 
594     ::GetTimeZoneInformation(&pTz);
595 
596     ///////////////////////////////////////////////
597     // Set timezone
598     timezone = pTz.Bias * SECONDS_IN_ONE_MINUTE ;
599     ///////////////////////////////////////////////
600 
601     iLeap = is_leap(SystemTime.wYear) ;
602 
603     res->tm_hour = SystemTime.wHour;
604     res->tm_min  = SystemTime.wMinute;
605     res->tm_sec  = SystemTime.wSecond;
606 
607     res->tm_mday = SystemTime.wDay;
608     res->tm_mon = SystemTime.wMonth - 1; // this the correct month but localtime returns month aligned to zero
609     res->tm_year = SystemTime.wYear;     // this the correct year
610     res->tm_year = res->tm_year - 1900;  // but localtime returns the value starting at the 1900
611 
612     res->tm_wday = SystemTime.wDayOfWeek;
613     res->tm_yday = __mon_yday[iLeap][res->tm_mon] + SystemTime.wDay - 1; // localtime returns year-day aligned to zero
614 
615     // if localtime behavior and daylight saving
616     if (bLocal && pTz.DaylightBias != 0)
617         res->tm_isdst = 1;
618     else
619         res->tm_isdst = 0; // without daylight saving or gmtime
620 
621     return res;
622 }
623 
624 extern "C"
625 {
626 
627 ////////////////////////////////////////////////////////////////////////
628 // Receive the number of seconds elapsed since midnight(00:00:00)
629 // and convert a time value and corrects for the local time zone
630 ////////////////////////////////////////////////////////////////////////
localtime(const time_t * t)631 struct tm * __cdecl localtime(const time_t * t)
632 {
633     return common_localtime(t, DO_LOCALTIME) ;
634 }
635 
636 ////////////////////////////////////////////////////////////////////////
637 // Receives the number of seconds elapsed since midnight(00:00:00)
638 // and converts a time value WITHOUT correcting for the local time zone
639 ////////////////////////////////////////////////////////////////////////
gmtime(const time_t * t)640 struct tm * __cdecl gmtime(const time_t *t)
641 {
642     return common_localtime(t, DO_GMTIME) ;
643 }
644 
645 }
646 
647 ////////////////////////////////////////////////////////////////////////
648 // Common code for conversion of struct tm into time_t   (static)
649 ////////////////////////////////////////////////////////////////////////
common_tm_to_time(int day,int month,int year,int hour,int minute,int second)650 static time_t __cdecl common_tm_to_time(int day, int month, int year, int hour, int minute, int second)
651 {
652 #if 1
653     // Use mktime since it seems less broken
654     tm t;
655     t.tm_isdst = -1;
656     t.tm_hour = hour;
657     t.tm_mday = day;
658     t.tm_min = minute;
659     t.tm_mon = month-1;
660     t.tm_sec = second;
661     t.tm_wday = -1;
662     t.tm_yday = -1;
663     t.tm_year = year - 1900;
664     return mktime(& t);
665 #else
666     time_t prog = 0 ;
667     static int mdays[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 } ;
668 
669     while (--month)
670     {
671         prog += mdays[month - 1] ;
672         if (month == 2 && is_leap(year))
673             prog++ ;
674     }
675 
676     // Calculate seconds in elapsed days
677     prog = day - 1 ;        // align first day of the year to zero
678     prog += (DAYS_IN_ONE_YEAR * (year - 1970) + (year - 1901) / 4 - 19) ;
679     prog *= SECONDS_IN_ONE_DAY ;
680 
681     // Add Calculated elapsed seconds in the current day
682     prog += (hour * SECONDS_IN_ONE_HOUR + minute *
683                                SECONDS_IN_ONE_MIN + second) ;
684 
685     return prog ;
686 #endif
687 }
688 
689 extern "C"
690 {
691 
692 ////////////////////////////////////////////////////////////////////////
693 // Returns the number of seconds elapsed since
694 // midnight(00:00:00) of 1 January 1970
695 ////////////////////////////////////////////////////////////////////////
time(time_t * t)696 time_t __cdecl time(time_t *t)
697 {
698     time_t prog = 0 ;
699 
700     if (t != NULL)
701     {
702         SYSTEMTIME SystemTime;
703 
704         ::GetLocalTime(&SystemTime) ;
705         prog = common_tm_to_time(SystemTime.wDay, SystemTime.wMonth, SystemTime.wYear,
706                                  SystemTime.wHour, SystemTime.wMinute, SystemTime.wSecond) ;
707         *t = prog ;
708     }
709 
710     return prog ;
711 }
712 
713 ////////////////////////////////////////////////////////////////////////
714 // Converts the local time provided by struct tm
715 // into a time_t calendar value
716 // Implementation from OpenBSD
717 ////////////////////////////////////////////////////////////////////////
718 
719 #if 1
720 int month_to_day[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
721 
mktime(struct tm * t)722 time_t mktime(struct tm *t)
723 {
724         short  month, year;
725         time_t result;
726 
727         month = t->tm_mon;
728         year = t->tm_year + month / 12 + 1900;
729         month %= 12;
730         if (month < 0)
731         {
732                 year -= 1;
733                 month += 12;
734         }
735         result = (year - 1970) * 365 + (year - 1969) / 4 + month_to_day[month];
736         result = (year - 1970) * 365 + month_to_day[month];
737         if (month <= 1)
738                 year -= 1;
739         result += (year - 1968) / 4;
740         result -= (year - 1900) / 100;
741         result += (year - 1600) / 400;
742         result += t->tm_mday;
743         result -= 1;
744         result *= 24;
745         result += t->tm_hour;
746         result *= 60;
747         result += t->tm_min;
748         result *= 60;
749         result += t->tm_sec;
750         return(result);
751 }
752 
753 #else
mktime(struct tm * t)754 time_t __cdecl mktime(struct tm *t)
755 {
756     return (common_tm_to_time(t->tm_mday, t->tm_mon+1, t->tm_year+1900, t->tm_hour, t->tm_min, t->tm_sec)) ;
757 }
758 #endif
759 
760 } // extern "C"
761 
762 #endif // VC8/!VC8
763