comparison zotnet/tws/phoon/dtime.c @ 0:bce86c4163a3

Initial revision
author kono
date Mon, 18 Apr 2005 23:46:02 +0900
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:bce86c4163a3
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 }