Mercurial > hg > Applications > mh
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 } |