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