Added -clobber switch to mhstore(1) [Bug #11160].
[mmh] / docs / historical / mh-6.8.5 / zotnet / tws / dtime.c
1 /* dtime.c - routines to do ``ARPA-style'' time structures */
2 #ifndef lint
3 static char ident[] = "@(#)$Id: dtime.c,v 1.15 1992/12/15 00:20:22 jromine Exp $";
4 #endif  /* lint */
5
6 /* LINTLIBRARY */
7
8
9 #include "tws.h"
10 #ifndef INETONLY
11 #include "../h/strings.h"
12 #else   /* INETONLY */
13 #include "strings.h"
14 #endif  /* INETONLY */
15 #include <stdio.h>
16 #include <sys/types.h>
17 #if     !defined(SYS5) && !defined(ZONEINFO)
18 #include <sys/timeb.h>
19 #endif  /* !defined(SYS5) && !defined(ZONEINFO) */
20 #ifdef  _AIX
21 #include <sys/time.h>
22 #include <time.h>
23 #else
24 #ifdef  BSD42
25 #include <sys/time.h>
26 #else   /* BSD42 */
27 #include <time.h>
28 #endif  /* BSD42 */
29 #endif
30
31 #ifdef  SYS5
32 extern int  daylight;
33 extern long timezone;
34 extern char *tzname[];
35 #endif  /* SYS5 */
36
37 /* \f */
38
39 #ifndef abs
40 #define abs(a)  (a >= 0 ? a : -a)
41 #endif
42
43 #define dysize(y)       \
44         (((y) % 4) ? 365 : (((y) % 100) ? 366 : (((y) % 400) ? 365 : 366)))
45
46 /* \f */
47
48 char *tw_moty[] = {
49     "Jan", "Feb", "Mar", "Apr", "May", "Jun",
50     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL
51 };
52
53 char *tw_dotw[] = {
54     "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL
55 };
56
57 char *tw_ldotw[] = {
58     "Sunday", "Monday", "Tuesday", "Wednesday",
59     "Thursday", "Friday", "Saturday", NULL
60 };
61
62 /* \f */
63
64 static struct zone {
65     char   *std,
66            *dst;
67     int     shift;
68 }                   zones[] = {
69                         "GMT", "BST", 0,
70                         "EST", "EDT", -5,
71                         "CST", "CDT", -6,
72                         "MST", "MDT", -7,
73                         "PST", "PDT", -8,
74 #ifdef  notdef  /* RFC1123 specifies do not use military TZs */
75                         "A", NULL, -1,
76                         "B", NULL, -2,
77                         "C", NULL, -3,
78                         "D", NULL, -4,
79                         "E", NULL, -5,
80                         "F", NULL, -6,
81                         "G", NULL, -7,
82                         "H", NULL, -8,
83                         "I", NULL, -9,
84                         "K", NULL, -10,
85                         "L", NULL, -11,
86                         "M", NULL, -12,
87                         "N", NULL, 1,
88 #ifndef HUJI
89                         "O", NULL, 2,
90 #else   /* HUJI */
91                         "JST", "JDT", 2,
92 #endif  /* HUJI */
93                         "P", NULL, 3,
94                         "Q", NULL, 4,
95                         "R", NULL, 5,
96                         "S", NULL, 6,
97                         "T", NULL, 7,
98                         "U", NULL, 8,
99                         "V", NULL, 9,
100                         "W", NULL, 10,
101                         "X", NULL, 11,
102                         "Y", NULL, 12,
103 #endif  /* notdef */
104
105                         NULL
106 };
107
108 #define CENTURY 1900
109
110 long    time ();
111 struct tm *localtime ();
112
113 /* \f */
114
115 char *dtimenow () {
116     long    clock;
117
118     (void) time (&clock);
119     return dtime (&clock);
120 }
121
122
123 char   *dctime (tw)
124 register struct tws *tw;
125 {
126     static char buffer[25];
127
128     if (!tw)
129         return NULL;
130
131     (void) sprintf (buffer, "%.3s %.3s %02d %02d:%02d:%02d %.4d\n",
132             tw_dotw[tw -> tw_wday], tw_moty[tw -> tw_mon], tw -> tw_mday,
133             tw -> tw_hour, tw -> tw_min, tw -> tw_sec,
134             tw -> tw_year >= 100 ? tw -> tw_year : CENTURY + tw -> tw_year);
135
136     return buffer;
137 }
138
139 /* \f */
140
141 struct tws *dtwstime () {
142     long    clock;
143
144     (void) time (&clock);
145     return dlocaltime (&clock);
146 }
147
148
149 struct tws *dlocaltime (clock)
150 register long   *clock;
151 {
152     register struct tm *tm;
153 #if     !defined(SYS5) && !defined(ZONEINFO)
154     struct timeb    tb;
155 #endif  /* !defined(SYS5) && !defined(ZONEINFO) */
156     static struct tws   tw;
157
158     if (!clock)
159         return NULL;
160     tw.tw_flags = TW_NULL;
161
162     tm = localtime (clock);
163     tw.tw_sec = tm -> tm_sec;
164     tw.tw_min = tm -> tm_min;
165     tw.tw_hour = tm -> tm_hour;
166     tw.tw_mday = tm -> tm_mday;
167     tw.tw_mon = tm -> tm_mon;
168     tw.tw_year = tm -> tm_year + CENTURY;
169     tw.tw_wday = tm -> tm_wday;
170     tw.tw_yday = tm -> tm_yday;
171     if (tm -> tm_isdst)
172         tw.tw_flags |= TW_DST;
173 #if     defined(SYS5)
174     tzset ();
175     tw.tw_zone = -(timezone / 60);
176 #else   /* defined(SYS5) */
177 #if     defined(ZONEINFO)
178     tw.tw_zone = tm->tm_gmtoff / 60;
179     if (tm -> tm_isdst)                 /* if DST is in effect */
180         tw.tw_zone -= 60;               /* reset to normal offset */
181 #else   /* defined(ZONEINFO) */
182     ftime (&tb);
183     tw.tw_zone = -tb.timezone;
184 #endif  /* defined(ZONEINFO) */
185 #endif  /* defined(SYS5) */
186     tw.tw_flags &= ~TW_SDAY, tw.tw_flags |= TW_SEXP;
187     tw.tw_flags &= ~TW_SZONE, tw.tw_flags |= TW_SZEXP;
188     tw.tw_clock = *clock;
189
190     return (&tw);
191 }
192
193
194 struct tws *dgmtime (clock)
195 register long   *clock;
196 {
197     register struct tm *tm;
198     static struct tws   tw;
199
200     if (!clock)
201         return NULL;
202     tw.tw_flags = TW_NULL;
203
204     tm = gmtime (clock);
205     tw.tw_sec = tm -> tm_sec;
206     tw.tw_min = tm -> tm_min;
207     tw.tw_hour = tm -> tm_hour;
208     tw.tw_mday = tm -> tm_mday;
209     tw.tw_mon = tm -> tm_mon;
210     tw.tw_year = tm -> tm_year + CENTURY;
211     tw.tw_wday = tm -> tm_wday;
212     tw.tw_yday = tm -> tm_yday;
213     if (tm -> tm_isdst)
214         tw.tw_flags |= TW_DST;
215     tw.tw_zone = 0;
216     tw.tw_flags &= ~TW_SDAY, tw.tw_flags |= TW_SEXP;
217     tw.tw_flags &= ~TW_SZONE, tw.tw_flags |= TW_SZEXP;
218     tw.tw_clock = *clock;
219
220     return (&tw);
221 }
222
223 /* \f */
224
225 char   *dasctime (tw, flags)
226 register struct tws *tw;
227 int     flags;
228 {
229     char buffer[80];
230     static char result[80];
231
232     if (!tw)
233         return NULL;
234
235     /* Display timezone if known */
236     if ((tw->tw_flags & TW_SZONE) == TW_SZNIL)
237             result[0] = '\0';
238     else
239             (void) sprintf(result, " %s",
240                 dtimezone(tw -> tw_zone, tw->tw_flags | flags));
241     (void) sprintf(buffer, "%02d %s %0*d %02d:%02d:%02d%s",
242             tw->tw_mday, tw_moty[tw->tw_mon],
243             tw -> tw_year < 100 ? 2 : 4, tw -> tw_year,
244             tw->tw_hour, tw->tw_min, tw->tw_sec, result);
245
246     if ((tw -> tw_flags & TW_SDAY) == TW_SEXP)
247         (void) sprintf (result, "%s, %s", tw_dotw[tw -> tw_wday], buffer);
248     else
249         if ((tw -> tw_flags & TW_SDAY) == TW_SNIL)
250             (void) strcpy (result, buffer);
251         else
252             (void) sprintf (result, "%s (%s)", buffer, tw_dotw[tw -> tw_wday]);
253
254     return result;
255 }
256
257 /* \f */
258
259 char   *dtimezone (offset, flags)
260 register int     offset,
261                  flags;
262 {
263     register int    hours,
264                     mins;
265     register struct zone *z;
266     static char buffer[10];
267
268     if (offset < 0) {
269         mins = -((-offset) % 60);
270         hours = -((-offset) / 60);
271     }
272     else {
273         mins = offset % 60;
274         hours = offset / 60;
275     }
276
277     if (!(flags & TW_ZONE) && mins == 0)
278 #if     defined(SYS5) && defined(TZNAME)
279     {
280         tzset();
281         return ((flags & TW_DST) ? tzname[1] : tzname[0]);
282     }
283 #else
284         for (z = zones; z -> std; z++)
285             if (z -> shift == hours)
286                 return (z -> dst && (flags & TW_DST) ? z -> dst : z -> std);
287 #endif
288
289 #if     defined(DSTXXX)
290     if (flags & TW_DST)
291         hours += 1;
292 #endif  /* defined(DSTXXX) */
293     (void) sprintf (buffer, "%s%02d%02d",
294             offset < 0 ? "-" : "+", abs (hours), abs (mins));
295     return buffer;
296 }
297
298 /* \f */
299
300 void twscopy (tb, tw)
301 register struct tws *tb,
302                     *tw;
303 {
304 #ifdef  notdef
305     tb -> tw_sec = tw -> tw_sec;
306     tb -> tw_min = tw -> tw_min;
307     tb -> tw_hour = tw -> tw_hour;
308     tb -> tw_mday = tw -> tw_mday;
309     tb -> tw_mon = tw -> tw_mon;
310     tb -> tw_year = tw -> tw_year;
311     tb -> tw_wday = tw -> tw_wday;
312     tb -> tw_yday = tw -> tw_yday;
313     tb -> tw_zone = tw -> tw_zone;
314     tb -> tw_clock = tw -> tw_clock;
315     tb -> tw_flags = tw -> tw_flags;
316 #else   /* not notdef */
317     *tb = *tw;
318 #endif  /* not notdef */
319 }
320
321
322 int     twsort (tw1, tw2)
323 register struct tws *tw1,
324                     *tw2;
325 {
326     register long   c1,
327                     c2;
328
329     if (tw1 -> tw_clock == 0L)
330         (void) twclock (tw1);
331     if (tw2 -> tw_clock == 0L)
332         (void) twclock (tw2);
333
334     return ((c1 = tw1 -> tw_clock) > (c2 = tw2 -> tw_clock) ? 1
335             : c1 == c2 ? 0 : -1);
336 }
337
338 /* \f */
339
340 /* This routine is based on the gtime() routine written by Steven Shafer
341    (sas) at CMU.  It was forwarded to MTR by Jay Lepreau at Utah-CS.
342  */
343
344 static int  dmsize[] = {
345     31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
346 };
347
348
349 long    twclock (tw)
350 register struct tws *tw;
351 {
352     register int    i,
353                     sec,
354                     min,
355                     hour,
356                     mday,
357                     mon,
358                     year;
359     register long   result;
360
361     if (tw -> tw_clock != 0L)
362         return tw -> tw_clock;
363
364     if ((sec = tw -> tw_sec) < 0 || sec > 59
365             || (min = tw -> tw_min) < 0 || min > 59
366             || (hour = tw -> tw_hour) < 0 || hour > 23
367             || (mday = tw -> tw_mday) < 1 || mday > 31
368             || (mon = tw -> tw_mon + 1) < 1 || mon > 12)
369         return (tw -> tw_clock = -1L);
370     year = tw -> tw_year;
371
372     result = 0L;
373     if (year < 100)
374         year += CENTURY;
375     for (i = 1970; i < year; i++)
376         result += dysize (i);
377     if (dysize (year) == 366 && mon >= 3)
378         result++;
379     while (--mon)
380         result += dmsize[mon - 1];
381     result += mday - 1;
382     result = 24 * result + hour;
383     result = 60 * result + min;
384     result = 60 * result + sec;
385     result -= 60 * tw -> tw_zone;
386     if (tw -> tw_flags & TW_DST)
387         result -= 60 * 60;
388
389     return (tw -> tw_clock = result);
390 }
391
392 /* \f */
393
394 /*
395  *    Simple calculation of day of the week.  Algorithm used is Zeller's
396  *    congruence.  Currently, we assume if tw -> tw_year < 100
397  *    then the century is CENTURY.
398  */
399
400 set_dotw (tw)
401 register struct tws *tw;
402 {
403     register int    month,
404                     day,
405                     year,
406                     century;
407
408     month = tw -> tw_mon - 1;
409     day = tw -> tw_mday;
410     year = tw -> tw_year % 100;
411     century = tw -> tw_year >= 100 ? tw -> tw_year / 100 : (CENTURY / 100);
412
413     if (month <= 0) {
414         month += 12;
415         if (--year < 0) {
416             year += 100;
417             century--;
418         }
419     }
420
421     tw -> tw_wday =
422         ((26 * month - 2) / 10 + day + year + year / 4
423             - 3 * century / 4 + 1) % 7;
424
425     tw -> tw_flags &= ~TW_SDAY, tw -> tw_flags |= TW_SIMP;
426 }