Annotation of OpenXM_contrib/gnuplot/time.c, Revision 1.1.1.3
1.1 maekawa 1: #ifndef lint
1.1.1.3 ! ohara 2: static char *RCSid = "$Id: time.c,v 1.5.2.2 2002/01/31 21:28:05 lhecking Exp $";
1.1 maekawa 3: #endif
4:
5: /* GNUPLOT - time.c */
6:
7: /*[
8: * Copyright 1986 - 1993, 1998 Thomas Williams, Colin Kelley
9: *
10: * Permission to use, copy, and distribute this software and its
11: * documentation for any purpose with or without fee is hereby granted,
12: * provided that the above copyright notice appear in all copies and
13: * that both that copyright notice and this permission notice appear
14: * in supporting documentation.
15: *
16: * Permission to modify the software is granted, but not the right to
17: * distribute the complete modified source code. Modifications are to
18: * be distributed as patches to the released version. Permission to
19: * distribute binaries produced by compiling modified sources is granted,
20: * provided you
21: * 1. distribute the corresponding source modifications from the
22: * released version in the form of a patch file along with the binaries,
23: * 2. add special version identification to distinguish your version
24: * in addition to the base release version number,
25: * 3. provide your name and address as the primary contact for the
26: * support of your modified version, and
27: * 4. retain our contact information in regard to use of the base
28: * software.
29: * Permission to distribute the released version of the source code along
30: * with corresponding source modifications in the form of a patch file is
31: * granted with same provisions 2 through 4 for binary distributions.
32: *
33: * This software is provided "as is" without express or implied warranty
34: * to the extent permitted by applicable law.
35: ]*/
36:
37:
38: /* some systems may not implement time very well ; in particular,
39: * things might break as the year 2000 approaches.
40: * This module either adds a routine gstrptime() to read a formatted time,
41: * augmenting the standard suite of time routines provided by ansi,
42: * or it completely replaces the whole lot with a new set of routines,
43: * which count time relative to the year 2000. Default is to use the
44: * new routines. define USE_SYSTEM_TIME to use the system routines, at your
45: * own risk. One problem in particular is that not all systems allow
46: * the time with integer value 0 to be represented symbolically, which
47: * prevents use of relative times.
48: */
49:
50:
51: #include "plot.h"
52:
53: /* build as a standalone test */
54:
55: #ifdef TEST_TIME
56:
57: # ifdef HAVE_SYS_TIMEB_H
58: # include <sys/timeb.h>
59: #else
60: /* declare struct timeb */
61: extern int ftime(struct timeb *);
62: #endif
63:
64: # define int_error(x,y) fprintf(stderr, "Error: " x "\n")
65: # define int_warn(x,y) fprintf(stderr, "Warn: " x "\n")
66:
67: /* need (only) these from plot.h */
68: # define ZERO_YEAR 2000
69: /* 1st jan, 2000 is a Saturday (cal 1 2000 on unix) */
70: # define JAN_FIRST_WDAY 6
71:
72: /* zero gnuplot (2000) - zero system (1970) */
73: # define SEC_OFFS_SYS 946684800.0
74:
75: /* avg, incl. leap year */
76: # define YEAR_SEC 31557600.0
77:
78: /* YEAR_SEC / 12 */
79: # define MON_SEC 2629800.0
80:
81: # define WEEK_SEC 604800.0
82: # define DAY_SEC 86400.0
83:
84: /*forward decls */
85: extern char *abbrev_month_names[];
86: extern char *full_month_names[];
87: extern char *abbrev_day_names[];
88: extern char *full_day_names[];
89:
90: #else /* TEST_TIME */
91:
92: # include "setshow.h" /* for month names etc */
93:
94: #endif /* TEST_TIME */
95:
96: static char *read_int __PROTO((char *s, int nr, int *d));
97: static int gdysize __PROTO((int yr));
98:
99:
100: static char *
101: read_int(s, nr, d)
102: char *s;
103: int nr, *d;
104: {
105: int result = 0;
106:
107: while (--nr >= 0 && *s >= '0' && *s <= '9')
108: result = result * 10 + (*s++ - '0');
109:
110: *d = result;
111: return (s);
112: }
113:
114:
115:
116: #ifndef USE_SYSTEM_TIME
117:
118: /* a new set of routines to completely replace the ansi ones
119: * Use at your own risk
120: */
121:
122:
123: static int mndday[12] =
124: {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
125:
126: static int xstrftime __PROTO((char *buf, int bufsz, char *fmt, struct tm * tm));
127:
128: /* days in year */
129: static int gdysize(yr)
130: int yr;
131: {
132:
133: if (!(yr % 4)) {
134: if ((!(yr % 100)) && yr % 400)
135: return (365);
136: return (366);
137: }
138: return (365);
139: }
140:
141:
142: /* new strptime() and gmtime() to allow time to be read as 24 hour,
143: * and spaces in the format string. time is converted to seconds from
144: * year 2000.... */
145:
146: char *
147: gstrptime(s, fmt, tm)
148: char *s;
149: char *fmt;
150: struct tm *tm;
151: {
152: int yday, date;
153:
154: date = yday = 0;
155: tm->tm_mday = 1;
156: tm->tm_mon = tm->tm_hour = tm->tm_min = tm->tm_sec = 0;
157: /* make relative times work (user-defined tic step) */
158: tm->tm_year = ZERO_YEAR;
159:
160: /* we do not yet calculate wday or yday, so make them illegal
161: * [but yday will be read by %j]
162: */
163:
164: tm->tm_yday = tm->tm_wday = -1;
165:
166: while (*fmt) {
167: if (*fmt != '%') {
168: if (*fmt == ' ') {
169: /* space in format means zero or more spaces in input */
170: while (*s == ' ')
171: ++s;
172: ++fmt;
173: continue;
174: } else if (*fmt == *s) {
175: ++s;
176: ++fmt;
177: continue;
178: } else
179: break; /* literal match has failed */
180: }
181: /* we are processing a percent escape */
182:
183: switch (*++fmt) {
184: case 'b': /* abbreviated month name */
185: {
186: int m;
187: for (m = 0; m < 12; ++m)
188: if (strnicmp(s, abbrev_month_names[m], strlen(abbrev_month_names[m])) == 0) {
189: s += strlen(abbrev_month_names[m]);
190: goto found_abbrev_mon;
191: }
192: /* get here => not found */
193: int_warn("Bad abbreviated month name", NO_CARET);
194: m = 0;
195: found_abbrev_mon:
196: tm->tm_mon = m;
197: break;
198: }
199:
200: case 'B': /* full month name */
201: {
202: int m;
203: for (m = 0; m < 12; ++m)
204: if (strnicmp(s, full_month_names[m], strlen(full_month_names[m])) == 0) {
205: s += strlen(full_month_names[m]);
206: goto found_full_mon;
207: }
208: /* get here => not found */
209: int_warn("Bad full month name", NO_CARET);
210: m = 0;
211: found_full_mon:
212: tm->tm_mon = m;
213: break;
214: }
215:
216: case 'd': /* read a day of month */
217: s = read_int(s, 2, &tm->tm_mday);
218: date++;
219: break;
220:
221: case 'm': /* month number */
222: s = read_int(s, 2, &tm->tm_mon);
223: date++;
224: --tm->tm_mon;
225: break;
226:
227: case 'y': /* year number */
228: s = read_int(s, 2, &tm->tm_year);
1.1.1.2 maekawa 229: /* In line with the current UNIX98 specification by
230: * The Open Group and major Unix vendors,
231: * two-digit years 69-99 refer to the 20th century, and
232: * values in the range 00-68 refer to the 21st century.
233: */
234: if (tm->tm_year <= 68)
235: tm->tm_year += 100;
1.1 maekawa 236: date++;
237: tm->tm_year += 1900;
238: break;
239:
240: case 'Y':
241: s = read_int(s, 4, &tm->tm_year);
242: date++;
243: break;
244:
245: case 'j':
246: s = read_int(s, 3, &tm->tm_yday);
247: tm->tm_yday--;
248: date++;
249: yday++;
250: break;
251:
252: case 'H':
253: s = read_int(s, 2, &tm->tm_hour);
254: break;
255:
256: case 'M':
257: s = read_int(s, 2, &tm->tm_min);
258: break;
259:
260: case 'S':
261: s = read_int(s, 2, &tm->tm_sec);
262: break;
263:
1.1.1.3 ! ohara 264: /* read EPOCH data
! 265: * EPOCH is the std. unixtimeformat seconds since 01.01.1970 UTC
! 266: * actualy i would need a read_long (or what time_t is else)
! 267: * aktualy this is not my idea i got if from
! 268: * AlunDa Penguin Jones (21.11.97)
! 269: * but changed %t to %s because of strftime
! 270: * and fixed the localtime() into gmtime()
! 271: * maybe we should use ggmtime() ? but who choose double ????
! 272: * Walter Harms <WHarms@bfs.de> 26 Mar 2000
! 273: */
! 274:
! 275: case 's':
! 276: {
! 277: /* time_t when; */
! 278: int when;
! 279: struct tm *tmwhen;
! 280: s = read_int(s, 10, &when);
! 281: tmwhen = gmtime((time_t*)&when);
! 282: tmwhen->tm_year += 1900;
! 283: *tm = *tmwhen;
! 284: break;
! 285: }
! 286:
1.1 maekawa 287: default:
288: int_warn("Bad time format in string", NO_CARET);
289: }
290: fmt++;
291: }
292:
1.1.1.3 ! ohara 293: FPRINTF((stderr, "read date-time : %02d/%02d/%d:%02d:%02d:%02d\n", tm->tm_mday, tm->tm_mon + 1, tm->tm_year, tm->tm_hour, tm->tm_min, tm->tm_sec));
1.1 maekawa 294:
295: /* now check the date/time entered, normalising if necessary
296: * read_int cannot read a -ve number, but can read %m=0 then decrement
297: * it to -1
298: */
299:
300: #define S (tm->tm_sec)
301: #define M (tm->tm_min)
302: #define H (tm->tm_hour)
303:
304: if (S >= 60) {
305: M += S / 60;
306: S %= 60;
307: }
308: if (M >= 60) {
309: H += M / 60;
310: M %= 60;
311: }
312: if (H >= 24) {
313: if (yday)
314: tm->tm_yday += H / 24;
315: tm->tm_mday += H / 24;
316: H %= 24;
317: }
318: #undef S
319: #undef M
320: #undef H
321:
1.1.1.3 ! ohara 322: FPRINTF((stderr, "normalised time : %02d/%02d/%d:%02d:%02d:%02d\n", tm->tm_mday, tm->tm_mon + 1, tm->tm_year, tm->tm_hour, tm->tm_min, tm->tm_sec));
1.1 maekawa 323:
324: if (date) {
325: if (yday) {
326:
327: if (tm->tm_yday < 0)
328: int_error("Illegal day of year", NO_CARET);
329:
330: /* we just set month to jan, day to yday, and let the
331: * normalising code do the work.
332: */
333:
334: tm->tm_mon = 0;
335: /* yday is 0->365, day is 1->31 */
336: tm->tm_mday = tm->tm_yday + 1;
337: }
338: if (tm->tm_mon < 0) {
339: int_error("illegal month", NO_CARET);
340: return (NULL);
341: }
342: if (tm->tm_mday < 1) {
343: int_error("illegal day of month", NO_CARET);
344: return (NULL);
345: }
346: if (tm->tm_mon > 11) {
347: tm->tm_year += tm->tm_mon / 12;
348: tm->tm_mon %= 12;
349: } {
350: int days_in_month;
351: while (tm->tm_mday > (days_in_month = (mndday[tm->tm_mon] + (tm->tm_mon == 1 && (gdysize(tm->tm_year) > 365))))) {
352: if (++tm->tm_mon == 12) {
353: ++tm->tm_year;
354: tm->tm_mon = 0;
355: }
356: tm->tm_mday -= days_in_month;
357: }
358: }
359: }
360: return (s);
361: }
362:
363: int gstrftime(s, bsz, fmt, l_clock)
364: char *s;
365: int bsz;
366: char *fmt;
367: double l_clock;
368: {
369: struct tm tm;
370:
371: ggmtime(&tm, l_clock);
372: #if 0
373: if ((tm.tm_zone = (char *) malloc(strlen(xtm->tm_zone) + 1)))
374: strcpy(tm.tm_zone, xtm->tm_zone);
375: /* printf("zone: %s - %s\n",tm.tm_zone,xtm->tm_zone); */
376: #endif
377:
378: return (xstrftime(s, bsz, fmt, &tm));
379: }
380:
381:
382: /* some shorthands : check that there is space in the output string
383: * Odd-looking defn is dangling-else-safe
384: */
385: #define CHECK_SPACE(n) if ( (l+(n)) <= bsz) ; else return 0
386:
387: /* copy a fixed string, checking that there's room */
388: #define COPY_STRING(z) CHECK_SPACE(strlen(z)) ; strcpy(s, z)
389:
390: /* format a string, using default spec if none given
391: * w and z are width and zero-flag
392: * dw and dz are the defaults for these
393: * In fact, CHECK_SPACE(w) is not a sufficient test, since
394: * sprintf("%2d", 365) outputs three characters
395: */
396:
397: #define FORMAT_STRING(dz, dw, x) \
398: if (w==0) { w=(dw); if (!z) z=(dz); } \
399: CHECK_SPACE(w); \
400: sprintf(s, z ? "%0*d" : "%*d", w, (x) )
401:
402: static int xstrftime(str, bsz, fmt, tm)
403: char *str; /* output buffer */
404: int bsz; /* space available */
405: char *fmt;
406: struct tm *tm;
407: {
408: int l = 0; /* chars written so far */
409:
410: char *s = str;
411:
412: memset(s, '\0', bsz);
413:
414: while (*fmt != '\0') {
415: if (*fmt != '%') {
416: if (l >= bsz)
417: return (0);
418: *s++ = *fmt++;
419: l++;
420: } else {
421:
422: /* set up format modifiers */
423: int w = 0;
424: int z = 0;
425: if (*++fmt == '0') {
426: z = 1;
427: ++fmt;
428: }
429: while (*fmt >= '0' && *fmt <= '9') {
430: w = w * 10 + (*fmt - '0');
431: ++fmt;
432: }
433:
434: switch (*fmt++) {
435: case '%':
436: CHECK_SPACE(1);
437: *s = '%';
438: break;
439:
440: case 'a':
441: COPY_STRING(abbrev_day_names[tm->tm_wday]);
442: break;
443:
444: case 'A':
445: COPY_STRING(full_day_names[tm->tm_wday]);
446: break;
447:
448: case 'b':
449: case 'h':
450: COPY_STRING(abbrev_month_names[tm->tm_mon]);
451: break;
452:
453: case 'B':
454: COPY_STRING(full_month_names[tm->tm_mon]);
455: break;
456:
457:
458: #if 0
459: /* %x not currently supported, so neither is c */
460: case 'c':
461: if (!xstrftime(s, bsz - l, "%x %X", tm))
462: return (0);
463: break;
464: #endif
465:
466: case 'd':
467: FORMAT_STRING(1, 2, tm->tm_mday); /* %02d */
468: break;
469:
470: case 'D':
471: if (!xstrftime(s, bsz - l, "%m/%d/%y", tm))
472: return (0);
473: break;
474:
475: case 'H':
476: FORMAT_STRING(1, 2, tm->tm_hour); /* %02d */
477: break;
478:
479: case 'I':
480: FORMAT_STRING(1, 2, tm->tm_hour % 12); /* %02d */
481: break;
482:
483: case 'j':
484: FORMAT_STRING(1, 3, tm->tm_yday + 1); /* %03d */
485: break;
486:
487: /* not in linux strftime man page. Not really needed now */
488: case 'k':
489: FORMAT_STRING(0, 2, tm->tm_hour); /* %2d */
490: break;
491:
492: case 'l':
493: FORMAT_STRING(0, 2, tm->tm_hour % 12); /* %2d */
494: break;
495:
496: case 'm':
497: FORMAT_STRING(1, 2, tm->tm_mon + 1); /* %02d */
498: break;
499:
500: case 'M':
501: FORMAT_STRING(1, 2, tm->tm_min); /* %02d */
502: break;
503:
504: case 'p':
505: CHECK_SPACE(2);
506: strcpy(s, (tm->tm_hour < 12) ? "am" : "pm");
507: break;
508:
509: case 'r':
510: if (!xstrftime(s, bsz - l, "%I:%M:%S %p", tm))
511: return (0);
512: break;
513:
514: case 'R':
515: if (!xstrftime(s, bsz - l, "%H:%M", tm))
516: return (0);
517: break;
518:
519: case 'S':
520: FORMAT_STRING(1, 2, tm->tm_sec); /* %02d */
521: break;
522:
523: case 'T':
524: if (!xstrftime(s, bsz - l, "%H:%M:%S", tm))
525: return (0);
526: break;
527:
528: case 'W': /* mon 1 day of week */
529: {
530: int week;
531: if (tm->tm_yday <= tm->tm_wday) {
532: week = 1;
533:
534: if ((tm->tm_mday - tm->tm_yday) > 4) {
535: week = 52;
536: }
537: if (tm->tm_yday == tm->tm_wday && tm->tm_wday == 0)
538: week = 52;
539:
540: } else {
541:
542: /* sun prev week */
543: int bw = tm->tm_yday - tm->tm_wday;
544:
545: if (tm->tm_wday > 0)
546: bw += 7; /* sun end of week */
547:
548: week = (int) bw / 7;
549:
550: if ((bw % 7) > 2) /* jan 1 is before friday */
551: week++;
552: }
553: FORMAT_STRING(1, 2, week); /* %02d */
554: break;
555: }
556:
557: case 'U': /* sun 1 day of week */
558: {
559: int week, bw;
560:
561: if (tm->tm_yday <= tm->tm_wday) {
562: week = 1;
563: if ((tm->tm_mday - tm->tm_yday) > 4) {
564: week = 52;
565: }
566: } else {
567: /* sat prev week */
568: bw = tm->tm_yday - tm->tm_wday - 1;
569: if (tm->tm_wday >= 0)
570: bw += 7; /* sat end of week */
571: week = (int) bw / 7;
572: if ((bw % 7) > 1) { /* jan 1 is before friday */
573: week++;
574: }
575: }
576: FORMAT_STRING(1, 2, week); /* %02d */
577: break;
578: }
579:
580: case 'w': /* day of week, sun=0 */
581: FORMAT_STRING(1, 2, tm->tm_wday); /* %02d */
582: break;
583:
584: case 'y':
585: FORMAT_STRING(1, 2, tm->tm_year % 100); /* %02d */
586: break;
587:
588: case 'Y':
589: FORMAT_STRING(1, 4, tm->tm_year); /* %04d */
590: break;
591:
592: #if 0
593: case 'Z':
594: COPY_STRING(tm->tm_zone);
595: break;
596: #endif
597: } /* switch */
598:
599: while (*s != '\0') {
600: s++;
601: l++;
602: }
603: }
604: }
605: return (l);
606: }
607:
608:
609:
610: /* time_t */
611: double gtimegm(tm)
612: struct tm *tm;
613: {
614: register int i;
615: /* returns sec from year ZERO_YEAR, defined in plot.h */
616: double dsec;
617:
618: dsec = 0;
619: if (tm->tm_year < ZERO_YEAR) {
620: for (i = tm->tm_year; i < ZERO_YEAR; i++) {
621: dsec -= (double) gdysize(i);
622: }
623: } else {
624: for (i = ZERO_YEAR; i < tm->tm_year; i++) {
625: dsec += (double) gdysize(i);
626: }
627: }
628: if (tm->tm_mday > 0) {
629: for (i = 0; i < tm->tm_mon; i++) {
630: dsec += (double) mndday[i] + (i == 1 && (gdysize(tm->tm_year) > 365));
631: }
632: dsec += (double) tm->tm_mday - 1;
633: } else {
634: dsec += (double) tm->tm_yday;
635: }
636: dsec *= (double) 24;
637:
638: dsec += tm->tm_hour;
639: dsec *= 60.0;
640: dsec += tm->tm_min;
641: dsec *= 60.0;
642: dsec += tm->tm_sec;
643:
1.1.1.3 ! ohara 644: FPRINTF((stderr, "broken-down time : %02d/%02d/%d:%02d:%02d:%02d = %g seconds\n", tm->tm_mday, tm->tm_mon + 1, tm->tm_year, tm->tm_hour, tm->tm_min, tm->tm_sec, dsec));
1.1 maekawa 645:
646: return (dsec);
647: }
648:
649: int ggmtime(tm, l_clock)
650: struct tm *tm;
651: /* time_t l_clock; */
652: double l_clock;
653: {
654: /* l_clock is relative to ZERO_YEAR, jan 1, 00:00:00,defined in plot.h */
655: int i, days;
656:
657: /* dodgy way of doing wday - i hope it works ! */
658:
659: int wday = JAN_FIRST_WDAY; /* eg 6 for 2000 */
660:
661: FPRINTF((stderr, "%g seconds = ", l_clock));
662:
663: tm->tm_year = ZERO_YEAR;
664: tm->tm_mday = tm->tm_yday = tm->tm_mon = tm->tm_hour = tm->tm_min = tm->tm_sec = 0;
665: if (l_clock < 0) {
666: while (l_clock < 0) {
667: int days_in_year = gdysize(--tm->tm_year);
668: l_clock += days_in_year * DAY_SEC; /* 24*3600 */
669: /* adding 371 is noop in modulo 7 arithmetic, but keeps wday +ve */
670: wday += 371 - days_in_year;
671: }
672: } else {
673: for (;;) {
674: int days_in_year = gdysize(tm->tm_year);
675: if (l_clock < days_in_year * DAY_SEC)
676: break;
677: l_clock -= days_in_year * DAY_SEC;
678: tm->tm_year++;
679: /* only interested in result modulo 7, but %7 is expensive */
680: wday += (days_in_year - 364);
681: }
682: }
683: tm->tm_yday = (int) (l_clock / DAY_SEC);
684: l_clock -= tm->tm_yday * DAY_SEC;
685: tm->tm_hour = (int) l_clock / 3600;
686: l_clock -= tm->tm_hour * 3600;
687: tm->tm_min = (int) l_clock / 60;
688: l_clock -= tm->tm_min * 60;
689: tm->tm_sec = (int) l_clock;
690:
691: days = tm->tm_yday;
692:
693: /* wday%7 should be day of week of first day of year */
694: tm->tm_wday = (wday + days) % 7;
695:
696: while (days >= (i = mndday[tm->tm_mon] + (tm->tm_mon == 1 && (gdysize(tm->tm_year) > 365)))) {
697: days -= i;
698: tm->tm_mon++;
699: }
700: tm->tm_mday = days + 1;
701:
1.1.1.3 ! ohara 702: FPRINTF((stderr, "broken-down time : %02d/%02d/%d:%02d:%02d:%02d\n", tm->tm_mday, tm->tm_mon + 1, tm->tm_year, tm->tm_hour, tm->tm_min, tm->tm_sec));
1.1 maekawa 703:
704: return (0);
705: }
706:
707:
708:
709:
710: #else /* USE_SYSTEM_TIME */
711:
712: /* define gnu time routines in terms of system time routines */
713:
714: int gstrftime(buf, bufsz, fmt, l_clock)
715: char *buf;
716: int bufsz;
717: char *fmt;
718: double l_clock;
719: {
720: time_t t = (time_t) l_clock;
721: return strftime(buf, bufsz, fmt, gmtime(&t));
722: }
723:
724: double gtimegm(tm)
725: struct tm *tm;
726: {
727: return (double) mktime(tm);
728: }
729:
730: int ggmtime(tm, l_clock)
731: struct tm *tm;
732: double l_clock;
733: {
734: time_t t = (time_t) l_clock;
735: struct tm *m = gmtime(&t);
736: *tm = *m; /* can any non-ansi compilers not do this ? */
737: }
738:
739: #define NOTHING
740: #define LETTER(L, width, field, extra) \
741: case L: s=read_int(s,width,&tm->field); extra; continue
742:
743: /* supplemental routine gstrptime() to read a formatted time */
744:
745: char *
746: gstrptime(s, fmt, tm)
747: char *s;
748: char *fmt;
749: struct tm *tm;
750: {
751: FPRINTF((stderr, "gstrptime(\"%s\", \"%s\")\n", s, fmt));
752:
753: /* linux does not appear to like years before 1902
754: * NT complains if its before 1970
755: * initialise fields to midnight, 1st Jan, 1970 (for relative times)
756: */
757: tm->tm_sec = tm->tm_min = tm->tm_hour = 0;
758: tm->tm_mday = 1;
759: tm->tm_mon = 0;
760: tm->tm_year = 70;
761: /* oops - it goes wrong without this */
762: tm->tm_isdst = 0;
763:
764: for (; *fmt && *s; ++fmt) {
765: if (*fmt != '%') {
766: if (*s != *fmt)
767: return s;
768: ++s;
769: continue;
770: }
771: assert(*fmt == '%');
772:
773: switch (*++fmt) {
774: case 0:
775: /* uh oh - % is last character in format */
776: return s;
777: case '%':
778: /* literal % */
779: if (*s++ != '%')
780: return s - 1;
781: continue;
782:
783: LETTER('d', 2, tm_mday, NOTHING);
784: LETTER('m', 2, tm_mon, NOTHING);
785: LETTER('y', 2, tm_year, NOTHING);
786: LETTER('Y', 4, tm_year, tm->tm_year -= 1900);
787: LETTER('H', 2, tm_hour, NOTHING);
788: LETTER('M', 2, tm_min, NOTHING);
789: LETTER('S', 2, tm_sec, NOTHING);
790:
791: default:
792: int_error("incorrect time format character", NO_CARET);
793: }
794: }
795:
796: FPRINTF((stderr, "Before mktime : %d/%d/%d:%d:%d:%d\n", tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_hour, tm->tm_min, tm->tm_sec));
797: /* mktime range-checks the time */
798:
799: if (mktime(tm) == -1) {
800: FPRINTF((stderr, "mktime() was not happy\n"));
801: int_error("Invalid date/time [mktime() did not like it]", NO_CARET);
802: }
803: FPRINTF((stderr, "After mktime : %d/%d/%d:%d:%d:%d\n", tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_hour, tm->tm_min, tm->tm_sec));
804:
805: return s;
806: }
807:
808:
809: #endif /* USE_SYSTEM_TIME */
810:
811:
812: #ifdef TEST_TIME
813:
814: char *abbrev_month_names[] =
815: {"jan", "feb", "mar", "apr", "may", "jun", "jul",
816: "aug", "sep", "oct", "nov", "dec"};
817: char *full_month_names[] =
818: {"January", "February", "March", "April", "May",
819: "June", "July", "August", "September", "October", "November", "December"};
820:
821: char *abbrev_day_names[] =
822: {"sun", "mon", "tue", "wed", "thu", "fri", "sat"};
823: char *full_day_names[] =
824: {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
825:
826:
827:
828: /* either print current time using supplied format, or read
829: * supplied time using supplied format
830: */
831:
832:
833: int main(argc,argv)
834: int argc;
835: char *argv[];
836: {
837: char output[80];
838:
839: if (argc < 2) {
840: fputs("usage : test 'format' ['time']\n", stderr);
841: exit(EXIT_FAILURE);
842: }
843: if (argc == 2) {
844: struct timeb now;
845: struct tm *tm;
846: ftime(&now);
847: tm = gmtime(&now.time);
848: xstrftime(output, 80, argv[1], tm);
849: puts(output);
850: } else {
851: struct tm tm;
852: gstrptime(argv[2], argv[1], &tm);
853: puts(asctime(&tm));
854: }
855: exit(EXIT_SUCCESS);
856: }
857:
858: #endif /* TEST_TIME */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>