src/3rdparty/ce-compat/ce_time.cpp
changeset 0 1918ee327afb
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 //
       
     2 // strftime.c
       
     3 //
       
     4 // Date to string conversion
       
     5 //
       
     6 // Copyright (C) 2002 Michael Ringgaard. All rights reserved.
       
     7 //
       
     8 // Redistribution and use in source and binary forms, with or without
       
     9 // modification, are permitted provided that the following conditions
       
    10 // are met:
       
    11 //
       
    12 // 1. Redistributions of source code must retain the above copyright
       
    13 //    notice, this list of conditions and the following disclaimer.
       
    14 // 2. Redistributions in binary form must reproduce the above copyright
       
    15 //    notice, this list of conditions and the following disclaimer in the
       
    16 //    documentation and/or other materials provided with the distribution.
       
    17 // 3. Neither the name of the project nor the names of its contributors
       
    18 //    may be used to endorse or promote products derived from this software
       
    19 //    without specific prior written permission.
       
    20 //
       
    21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
       
    22 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
       
    23 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
       
    24 // ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
       
    25 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
       
    26 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
       
    27 // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
       
    28 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
       
    29 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
       
    30 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
       
    31 // SUCH DAMAGE.
       
    32 //
       
    33 
       
    34 /////////////////////////////////////////////////////////////////////////////////////////////
       
    35 //                                                                                         //
       
    36 //                                         time()                                          //
       
    37 //                                                                                         //
       
    38 /////////////////////////////////////////////////////////////////////////////////////////////
       
    39 
       
    40 
       
    41 #include <windows.h>
       
    42 #include <time.h>
       
    43 #include "ce_time.h"
       
    44 
       
    45 time_t
       
    46 time(time_t* timer)
       
    47 {
       
    48 	SYSTEMTIME systime;
       
    49 	struct tm tmtime;
       
    50 	time_t tt;
       
    51 
       
    52 	GetLocalTime(&systime);
       
    53 
       
    54 	tmtime.tm_year = systime.wYear-1900;
       
    55 	tmtime.tm_mon = systime.wMonth-1;
       
    56 	tmtime.tm_mday = systime.wDay;
       
    57 	tmtime.tm_wday = systime.wDayOfWeek;
       
    58 	tmtime.tm_hour = systime.wHour;
       
    59 	tmtime.tm_min = systime.wMinute;
       
    60 	tmtime.tm_sec = systime.wSecond;
       
    61 
       
    62 	tt = mktime(&tmtime);
       
    63 
       
    64 	if(timer)
       
    65 		*timer = tt;
       
    66 
       
    67 	return tt;
       
    68 }
       
    69 
       
    70 
       
    71 /////////////////////////////////////////////////////////////////////////////////////////////
       
    72 //                                                                                         //
       
    73 //                                        mktime()                                         //
       
    74 //                                                                                         //
       
    75 /////////////////////////////////////////////////////////////////////////////////////////////
       
    76 
       
    77 static int month_to_day[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
       
    78 
       
    79 time_t mktime(struct tm *t)
       
    80 {
       
    81         short  month, year;
       
    82         time_t result;
       
    83 
       
    84         month = t->tm_mon;
       
    85         year = t->tm_year + month / 12 + 1900;
       
    86         month %= 12;
       
    87         if (month < 0)
       
    88         {
       
    89                 year -= 1;
       
    90                 month += 12;
       
    91         }
       
    92         result = (year - 1970) * 365 + (year - 1969) / 4 + month_to_day[month];
       
    93         result = (year - 1970) * 365 + month_to_day[month];
       
    94         if (month <= 1)
       
    95                 year -= 1;
       
    96         result += (year - 1968) / 4;
       
    97         result -= (year - 1900) / 100;
       
    98         result += (year - 1600) / 400;
       
    99         result += t->tm_mday;
       
   100         result -= 1;
       
   101         result *= 24;
       
   102         result += t->tm_hour;
       
   103         result *= 60;
       
   104         result += t->tm_min;
       
   105         result *= 60;
       
   106         result += t->tm_sec;
       
   107         return(result);
       
   108 }
       
   109 
       
   110 
       
   111 /////////////////////////////////////////////////////////////////////////////////////////////
       
   112 //                                                                                         //
       
   113 //                             strftime() - taken from OpenBSD                             //
       
   114 //                                                                                         //
       
   115 /////////////////////////////////////////////////////////////////////////////////////////////
       
   116 
       
   117 #define IN_NONE	0
       
   118 #define IN_SOME	1
       
   119 #define IN_THIS	2
       
   120 #define IN_ALL	3
       
   121 #define CHAR_BIT      8
       
   122 
       
   123 #define TYPE_BIT(type)	(sizeof (type) * CHAR_BIT)
       
   124 #define TYPE_SIGNED(type) (((type) -1) < 0)
       
   125 
       
   126 #define INT_STRLEN_MAXIMUM(type) \
       
   127     ((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 1000 + 1 + TYPE_SIGNED(type))
       
   128 
       
   129 #define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
       
   130 
       
   131 #define MONSPERYEAR	12
       
   132 #define DAYSPERWEEK	7
       
   133 #define TM_YEAR_BASE	1900
       
   134 #define HOURSPERDAY	24
       
   135 #define DAYSPERNYEAR	365
       
   136 #define DAYSPERLYEAR	366
       
   137 
       
   138 static char		wildabbr[] = "WILDABBR";
       
   139 
       
   140 static char *			tzname[2] = {
       
   141 	wildabbr,
       
   142 	wildabbr
       
   143 };
       
   144 
       
   145 
       
   146 #define Locale	(&C_time_locale)
       
   147 
       
   148 struct lc_time_T {
       
   149 	const char *	mon[MONSPERYEAR];
       
   150 	const char *	month[MONSPERYEAR];
       
   151 	const char *	wday[DAYSPERWEEK];
       
   152 	const char *	weekday[DAYSPERWEEK];
       
   153 	const char *	X_fmt;
       
   154 	const char *	x_fmt;
       
   155 	const char *	c_fmt;
       
   156 	const char *	am;
       
   157 	const char *	pm;
       
   158 	const char *	date_fmt;
       
   159 };
       
   160 
       
   161 static const struct lc_time_T	C_time_locale = {
       
   162 	{
       
   163 		"Jan", "Feb", "Mar", "Apr", "May", "Jun",
       
   164 		"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
       
   165 	}, {
       
   166 		"January", "February", "March", "April", "May", "June",
       
   167 		"July", "August", "September", "October", "November", "December"
       
   168 	}, {
       
   169 		"Sun", "Mon", "Tue", "Wed",
       
   170 		"Thu", "Fri", "Sat"
       
   171 	}, {
       
   172 		"Sunday", "Monday", "Tuesday", "Wednesday",
       
   173 		"Thursday", "Friday", "Saturday"
       
   174 	},
       
   175 
       
   176 	/* X_fmt */
       
   177 	"%H:%M:%S",
       
   178 
       
   179 	/*
       
   180 	** x_fmt
       
   181 	** C99 requires this format.
       
   182 	** Using just numbers (as here) makes Quakers happier;
       
   183 	** it's also compatible with SVR4.
       
   184 	*/
       
   185 	"%m/%d/%y",
       
   186 
       
   187 	/*
       
   188 	** c_fmt
       
   189 	** C99 requires this format.
       
   190 	** Previously this code used "%D %X", but we now conform to C99.
       
   191 	** Note that
       
   192 	**      "%a %b %d %H:%M:%S %Y"
       
   193 	** is used by Solaris 2.3.
       
   194 	*/
       
   195 	"%a %b %e %T %Y",
       
   196 
       
   197 	/* am */
       
   198 	"AM",
       
   199 
       
   200 	/* pm */
       
   201 	"PM",
       
   202 
       
   203 	/* date_fmt */
       
   204 	"%a %b %e %H:%M:%S %Z %Y"
       
   205 };
       
   206 
       
   207 
       
   208 static char *
       
   209 _add(const char * str, char * pt, const char * const ptlim)
       
   210 {
       
   211 	while (pt < ptlim && (*pt = *str++) != '\0')
       
   212 		++pt;
       
   213 	return pt;
       
   214 }
       
   215 
       
   216 
       
   217 static char *
       
   218 _conv(const int n, const char * const format, char * const pt, const char * const ptlim)
       
   219 {
       
   220 	char	buf[INT_STRLEN_MAXIMUM(int) + 1];
       
   221 
       
   222 	(void) _snprintf(buf, sizeof buf, format, n);
       
   223 	return _add(buf, pt, ptlim);
       
   224 }
       
   225 
       
   226 
       
   227 static char *
       
   228 _fmt(const char * format, const struct tm * const t, char * pt, const char * const ptlim, int * warnp)
       
   229 {
       
   230 	for ( ; *format; ++format) {
       
   231 		if (*format == '%') {
       
   232 label:
       
   233 			switch (*++format) {
       
   234 			case '\0':
       
   235 				--format;
       
   236 				break;
       
   237 			case 'A':
       
   238 				pt = _add((t->tm_wday < 0 ||
       
   239 					t->tm_wday >= DAYSPERWEEK) ?
       
   240 					"?" : Locale->weekday[t->tm_wday],
       
   241 					pt, ptlim);
       
   242 				continue;
       
   243 			case 'a':
       
   244 				pt = _add((t->tm_wday < 0 ||
       
   245 					t->tm_wday >= DAYSPERWEEK) ?
       
   246 					"?" : Locale->wday[t->tm_wday],
       
   247 					pt, ptlim);
       
   248 				continue;
       
   249 			case 'B':
       
   250 				pt = _add((t->tm_mon < 0 ||
       
   251 					t->tm_mon >= MONSPERYEAR) ?
       
   252 					"?" : Locale->month[t->tm_mon],
       
   253 					pt, ptlim);
       
   254 				continue;
       
   255 			case 'b':
       
   256 			case 'h':
       
   257 				pt = _add((t->tm_mon < 0 ||
       
   258 					t->tm_mon >= MONSPERYEAR) ?
       
   259 					"?" : Locale->mon[t->tm_mon],
       
   260 					pt, ptlim);
       
   261 				continue;
       
   262 			case 'C':
       
   263 				/*
       
   264 				** %C used to do a...
       
   265 				**	_fmt("%a %b %e %X %Y", t);
       
   266 				** ...whereas now POSIX 1003.2 calls for
       
   267 				** something completely different.
       
   268 				** (ado, 1993-05-24)
       
   269 				*/
       
   270 				pt = _conv((t->tm_year + TM_YEAR_BASE) / 100,
       
   271 					"%02d", pt, ptlim);
       
   272 				continue;
       
   273 			case 'c':
       
   274 				{
       
   275 				int warn2 = IN_SOME;
       
   276 
       
   277 				pt = _fmt(Locale->c_fmt, t, pt, ptlim, warnp);
       
   278 				if (warn2 == IN_ALL)
       
   279 					warn2 = IN_THIS;
       
   280 				if (warn2 > *warnp)
       
   281 					*warnp = warn2;
       
   282 				}
       
   283 				continue;
       
   284 			case 'D':
       
   285 				pt = _fmt("%m/%d/%y", t, pt, ptlim, warnp);
       
   286 				continue;
       
   287 			case 'd':
       
   288 				pt = _conv(t->tm_mday, "%02d", pt, ptlim);
       
   289 				continue;
       
   290 			case 'E':
       
   291 			case 'O':
       
   292 				/*
       
   293 				** C99 locale modifiers.
       
   294 				** The sequences
       
   295 				**	%Ec %EC %Ex %EX %Ey %EY
       
   296 				**	%Od %oe %OH %OI %Om %OM
       
   297 				**	%OS %Ou %OU %OV %Ow %OW %Oy
       
   298 				** are supposed to provide alternate
       
   299 				** representations.
       
   300 				*/
       
   301 				goto label;
       
   302 			case 'e':
       
   303 				pt = _conv(t->tm_mday, "%2d", pt, ptlim);
       
   304 				continue;
       
   305 			case 'F':
       
   306 				pt = _fmt("%Y-%m-%d", t, pt, ptlim, warnp);
       
   307 				continue;
       
   308 			case 'H':
       
   309 				pt = _conv(t->tm_hour, "%02d", pt, ptlim);
       
   310 				continue;
       
   311 			case 'I':
       
   312 				pt = _conv((t->tm_hour % 12) ?
       
   313 					(t->tm_hour % 12) : 12,
       
   314 					"%02d", pt, ptlim);
       
   315 				continue;
       
   316 			case 'j':
       
   317 				pt = _conv(t->tm_yday + 1, "%03d", pt, ptlim);
       
   318 				continue;
       
   319 			case 'k':
       
   320 				/*
       
   321 				** This used to be...
       
   322 				**	_conv(t->tm_hour % 12 ?
       
   323 				**		t->tm_hour % 12 : 12, 2, ' ');
       
   324 				** ...and has been changed to the below to
       
   325 				** match SunOS 4.1.1 and Arnold Robbins'
       
   326 				** strftime version 3.0.  That is, "%k" and
       
   327 				** "%l" have been swapped.
       
   328 				** (ado, 1993-05-24)
       
   329 				*/
       
   330 				pt = _conv(t->tm_hour, "%2d", pt, ptlim);
       
   331 				continue;
       
   332 #ifdef KITCHEN_SINK
       
   333 			case 'K':
       
   334 				/*
       
   335 				** After all this time, still unclaimed!
       
   336 				*/
       
   337 				pt = _add("kitchen sink", pt, ptlim);
       
   338 				continue;
       
   339 #endif /* defined KITCHEN_SINK */
       
   340 			case 'l':
       
   341 				/*
       
   342 				** This used to be...
       
   343 				**	_conv(t->tm_hour, 2, ' ');
       
   344 				** ...and has been changed to the below to
       
   345 				** match SunOS 4.1.1 and Arnold Robbin's
       
   346 				** strftime version 3.0.  That is, "%k" and
       
   347 				** "%l" have been swapped.
       
   348 				** (ado, 1993-05-24)
       
   349 				*/
       
   350 				pt = _conv((t->tm_hour % 12) ?
       
   351 					(t->tm_hour % 12) : 12,
       
   352 					"%2d", pt, ptlim);
       
   353 				continue;
       
   354 			case 'M':
       
   355 				pt = _conv(t->tm_min, "%02d", pt, ptlim);
       
   356 				continue;
       
   357 			case 'm':
       
   358 				pt = _conv(t->tm_mon + 1, "%02d", pt, ptlim);
       
   359 				continue;
       
   360 			case 'n':
       
   361 				pt = _add("\n", pt, ptlim);
       
   362 				continue;
       
   363 			case 'p':
       
   364 				pt = _add((t->tm_hour >= (HOURSPERDAY / 2)) ?
       
   365 					Locale->pm :
       
   366 					Locale->am,
       
   367 					pt, ptlim);
       
   368 				continue;
       
   369 			case 'R':
       
   370 				pt = _fmt("%H:%M", t, pt, ptlim, warnp);
       
   371 				continue;
       
   372 			case 'r':
       
   373 				pt = _fmt("%I:%M:%S %p", t, pt, ptlim, warnp);
       
   374 				continue;
       
   375 			case 'S':
       
   376 				pt = _conv(t->tm_sec, "%02d", pt, ptlim);
       
   377 				continue;
       
   378 			case 's':
       
   379 				{
       
   380 					struct tm	tm;
       
   381 					char		buf[INT_STRLEN_MAXIMUM(
       
   382 								time_t) + 1];
       
   383 					time_t		mkt;
       
   384 
       
   385 					tm = *t;
       
   386 					mkt = mktime(&tm);
       
   387 					if (TYPE_SIGNED(time_t))
       
   388 						(void) _snprintf(buf, sizeof buf,
       
   389 						    "%ld", (long) mkt);
       
   390 					else	(void) _snprintf(buf, sizeof buf,
       
   391 						    "%lu", (unsigned long) mkt);
       
   392 					pt = _add(buf, pt, ptlim);
       
   393 				}
       
   394 				continue;
       
   395 			case 'T':
       
   396 				pt = _fmt("%H:%M:%S", t, pt, ptlim, warnp);
       
   397 				continue;
       
   398 			case 't':
       
   399 				pt = _add("\t", pt, ptlim);
       
   400 				continue;
       
   401 			case 'U':
       
   402 				pt = _conv((t->tm_yday + DAYSPERWEEK -
       
   403 					t->tm_wday) / DAYSPERWEEK,
       
   404 					"%02d", pt, ptlim);
       
   405 				continue;
       
   406 			case 'u':
       
   407 				/*
       
   408 				** From Arnold Robbins' strftime version 3.0:
       
   409 				** "ISO 8601: Weekday as a decimal number
       
   410 				** [1 (Monday) - 7]"
       
   411 				** (ado, 1993-05-24)
       
   412 				*/
       
   413 				pt = _conv((t->tm_wday == 0) ?
       
   414 					DAYSPERWEEK : t->tm_wday,
       
   415 					"%d", pt, ptlim);
       
   416 				continue;
       
   417 			case 'V':	/* ISO 8601 week number */
       
   418 			case 'G':	/* ISO 8601 year (four digits) */
       
   419 			case 'g':	/* ISO 8601 year (two digits) */
       
   420 				{
       
   421 					int	year;
       
   422 					int	yday;
       
   423 					int	wday;
       
   424 					int	w;
       
   425 
       
   426 					year = t->tm_year + TM_YEAR_BASE;
       
   427 					yday = t->tm_yday;
       
   428 					wday = t->tm_wday;
       
   429 					for ( ; ; ) {
       
   430 						int	len;
       
   431 						int	bot;
       
   432 						int	top;
       
   433 
       
   434 						len = isleap(year) ?
       
   435 							DAYSPERLYEAR :
       
   436 							DAYSPERNYEAR;
       
   437 						/*
       
   438 						** What yday (-3 ... 3) does
       
   439 						** the ISO year begin on?
       
   440 						*/
       
   441 						bot = ((yday + 11 - wday) %
       
   442 							DAYSPERWEEK) - 3;
       
   443 						/*
       
   444 						** What yday does the NEXT
       
   445 						** ISO year begin on?
       
   446 						*/
       
   447 						top = bot -
       
   448 							(len % DAYSPERWEEK);
       
   449 						if (top < -3)
       
   450 							top += DAYSPERWEEK;
       
   451 						top += len;
       
   452 						if (yday >= top) {
       
   453 							++year;
       
   454 							w = 1;
       
   455 							break;
       
   456 						}
       
   457 						if (yday >= bot) {
       
   458 							w = 1 + ((yday - bot) /
       
   459 								DAYSPERWEEK);
       
   460 							break;
       
   461 						}
       
   462 						--year;
       
   463 						yday += isleap(year) ?
       
   464 							DAYSPERLYEAR :
       
   465 							DAYSPERNYEAR;
       
   466 					}
       
   467 					if (*format == 'V')
       
   468 						pt = _conv(w, "%02d",
       
   469 							pt, ptlim);
       
   470 					else if (*format == 'g') {
       
   471 						*warnp = IN_ALL;
       
   472 						pt = _conv(year % 100, "%02d",
       
   473 							pt, ptlim);
       
   474 					} else	pt = _conv(year, "%04d",
       
   475 							pt, ptlim);
       
   476 				}
       
   477 				continue;
       
   478 			case 'v':
       
   479 				pt = _fmt("%e-%b-%Y", t, pt, ptlim, warnp);
       
   480 				continue;
       
   481 			case 'W':
       
   482 				pt = _conv((t->tm_yday + DAYSPERWEEK -
       
   483 					(t->tm_wday ?
       
   484 					(t->tm_wday - 1) :
       
   485 					(DAYSPERWEEK - 1))) / DAYSPERWEEK,
       
   486 					"%02d", pt, ptlim);
       
   487 				continue;
       
   488 			case 'w':
       
   489 				pt = _conv(t->tm_wday, "%d", pt, ptlim);
       
   490 				continue;
       
   491 			case 'X':
       
   492 				pt = _fmt(Locale->X_fmt, t, pt, ptlim, warnp);
       
   493 				continue;
       
   494 			case 'x':
       
   495 				{
       
   496 				int	warn2 = IN_SOME;
       
   497 
       
   498 				pt = _fmt(Locale->x_fmt, t, pt, ptlim, &warn2);
       
   499 				if (warn2 == IN_ALL)
       
   500 					warn2 = IN_THIS;
       
   501 				if (warn2 > *warnp)
       
   502 					*warnp = warn2;
       
   503 				}
       
   504 				continue;
       
   505 			case 'y':
       
   506 				*warnp = IN_ALL;
       
   507 				pt = _conv((t->tm_year + TM_YEAR_BASE) % 100,
       
   508 					"%02d", pt, ptlim);
       
   509 				continue;
       
   510 			case 'Y':
       
   511 				pt = _conv(t->tm_year + TM_YEAR_BASE, "%04d",
       
   512 					pt, ptlim);
       
   513 				continue;
       
   514 			case 'Z':
       
   515 				if (t->tm_isdst >= 0)
       
   516 					pt = _add(tzname[t->tm_isdst != 0],
       
   517 						pt, ptlim);
       
   518 				/*
       
   519 				** C99 says that %Z must be replaced by the
       
   520 				** empty string if the time zone is not
       
   521 				** determinable.
       
   522 				*/
       
   523 				continue;
       
   524 			case 'z':
       
   525 				{
       
   526 				int		diff;
       
   527 				char const *	sign;
       
   528 
       
   529 				if (t->tm_isdst < 0)
       
   530 					continue;
       
   531 				continue;
       
   532 				if (diff < 0) {
       
   533 					sign = "-";
       
   534 					diff = -diff;
       
   535 				} else	sign = "+";
       
   536 				pt = _add(sign, pt, ptlim);
       
   537 				diff /= 60;
       
   538 				pt = _conv((diff/60)*100 + diff%60,
       
   539 					"%04d", pt, ptlim);
       
   540 				}
       
   541 				continue;
       
   542 			case '+':
       
   543 				pt = _fmt(Locale->date_fmt, t, pt, ptlim,
       
   544 					warnp);
       
   545 				continue;
       
   546 			case '%':
       
   547 			default:
       
   548 				break;
       
   549 			}
       
   550 		}
       
   551 		if (pt == ptlim)
       
   552 			break;
       
   553 		*pt++ = *format;
       
   554 	}
       
   555 	return pt;
       
   556 }
       
   557 
       
   558 
       
   559 size_t
       
   560 strftime(char * const s, const size_t maxsize, const char * const format, const struct tm * const t)
       
   561 {
       
   562 	char *	p;
       
   563 	int	warn;
       
   564 
       
   565 	//tzset();
       
   566 
       
   567 	warn = IN_NONE;
       
   568 	p = _fmt(((format == NULL) ? "%c" : format), t, s, s + maxsize, &warn);
       
   569 
       
   570 	if (p == s + maxsize) {
       
   571 		if (maxsize > 0)
       
   572 			s[maxsize - 1] = '\0';
       
   573 		return 0;
       
   574 	}
       
   575 	*p = '\0';
       
   576 	return p - s;
       
   577 }
       
   578 
       
   579 
       
   580 
       
   581 /////////////////////////////////////////////////////////////////////////////////////////////
       
   582 //                                                                                         //
       
   583 //                                      gmtime()                                           //
       
   584 //                                                                                         //
       
   585 /////////////////////////////////////////////////////////////////////////////////////////////
       
   586 
       
   587 
       
   588 
       
   589 static struct tm mytm;
       
   590 
       
   591 static int DMonth[13] = { 0,31,59,90,120,151,181,212,243,273,304,334,365 };
       
   592 static int monthCodes[12] = { 6, 2, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4 };
       
   593 
       
   594 
       
   595 static int
       
   596 calcDayOfWeek(const struct tm* nTM)
       
   597 {
       
   598 	int day;
       
   599 
       
   600 	day = (nTM->tm_year%100);
       
   601 	day += day/4;
       
   602 	day += monthCodes[nTM->tm_mon];
       
   603 	day += nTM->tm_mday;
       
   604 	while(day>=7)
       
   605 		day -= 7;
       
   606 
       
   607 	return day;
       
   608 }
       
   609 
       
   610 
       
   611 static struct tm *
       
   612 gmtime(const time_t *timer)
       
   613 {
       
   614 	unsigned long x = *timer;
       
   615 	int imin, ihrs, iday, iyrs;
       
   616 	int sec, min, hrs, day, mon, yrs;
       
   617 	int lday, qday, jday, mday;
       
   618 
       
   619 
       
   620 	imin = x / 60;							// whole minutes since 1/1/70
       
   621 	sec = x - (60 * imin);					// leftover seconds
       
   622 	ihrs = imin / 60;						// whole hours since 1/1/70
       
   623 	min = imin - 60 * ihrs;					// leftover minutes
       
   624 	iday = ihrs / 24;						// whole days since 1/1/70
       
   625 	hrs = ihrs - 24 * iday;					// leftover hours
       
   626 	iday = iday + 365 + 366; 				// whole days since 1/1/68
       
   627 	lday = iday / (( 4* 365) + 1);			// quadyr = 4 yr period = 1461 days
       
   628 	qday = iday % (( 4 * 365) + 1);			// days since current quadyr began
       
   629 	if(qday >= (31 + 29))					// if past feb 29 then
       
   630 		lday = lday + 1;					// add this quadyr’s leap day to the
       
   631 											// # of quadyrs (leap days) since 68
       
   632 	iyrs = (iday - lday) / 365;				// whole years since 1968
       
   633 	jday = iday - (iyrs * 365) - lday;		// days since 1 /1 of current year.
       
   634 	if(qday <= 365 && qday >= 60)			// if past 2/29 and a leap year then
       
   635 		jday = jday + 1;					// add a leap day to the # of whole
       
   636 											// days since 1/1 of current year
       
   637 	yrs = iyrs + 1968;						// compute year
       
   638 	mon = 13;								// estimate month ( +1)
       
   639 	mday = 366;								// max days since 1/1 is 365
       
   640 	while(jday < mday)						// mday = # of days passed from 1/1
       
   641 	{										// until first day of current month
       
   642 		mon = mon - 1;						// mon = month (estimated)
       
   643 		mday = DMonth[mon];					// # elapsed days at first of ”mon”
       
   644 		if((mon > 2) && (yrs % 4) == 0)		// if past 2/29 and leap year then
       
   645 			mday = mday + 1;				// add leap day
       
   646 											// compute month by decrementing
       
   647 	}										// month until found
       
   648 
       
   649 	day = jday - mday + 1;					// compute day of month
       
   650 
       
   651 	mytm.tm_sec = sec;
       
   652 	mytm.tm_min = min;
       
   653 	mytm.tm_hour = hrs;
       
   654 	mytm.tm_mday = day;
       
   655 	mytm.tm_mon = mon;
       
   656 	mytm.tm_year = yrs - 1900;
       
   657 
       
   658 	mytm.tm_wday = calcDayOfWeek(&mytm);
       
   659 	mytm.tm_yday = jday;
       
   660 	mytm.tm_isdst = 0;
       
   661 
       
   662 	return &mytm;
       
   663 }
       
   664 
       
   665 
       
   666 /////////////////////////////////////////////////////////////////////////////////////////////
       
   667 //                                                                                         //
       
   668 //                            localtime() - simply using gmtime()                          //
       
   669 //                                                                                         //
       
   670 /////////////////////////////////////////////////////////////////////////////////////////////
       
   671 
       
   672 
       
   673 struct tm *
       
   674 localtime(const time_t *timer)
       
   675 {
       
   676 	return gmtime(timer);
       
   677 }