|
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 } |