Initial import of the CDE 2.1.30 sources from the Open Group.
[oweals/cde.git] / cde / programs / dtcm / libDtCmP / timeops.c
1 /*******************************************************************************
2 **
3 **  timeops.c
4 **
5 **  $XConsortium: timeops.c /main/6 1996/11/21 19:44:23 drk $
6 **
7 **  RESTRICTED CONFIDENTIAL INFORMATION:
8 **
9 **  The information in this document is subject to special
10 **  restrictions in a confidential disclosure agreement between
11 **  HP, IBM, Sun, USL, SCO and Univel.  Do not distribute this
12 **  document outside HP, IBM, Sun, USL, SCO, or Univel without
13 **  Sun's specific written approval.  This document and all copies
14 **  and derivative works thereof must be returned or destroyed at
15 **  Sun's request.
16 **
17 **  Copyright 1993 Sun Microsystems, Inc.  All rights reserved.
18 **
19 *******************************************************************************/
20
21 /*                                                                      *
22  * (c) Copyright 1993, 1994 Hewlett-Packard Company                     *
23  * (c) Copyright 1993, 1994 International Business Machines Corp.       *
24  * (c) Copyright 1993, 1994 Sun Microsystems, Inc.                      *
25  * (c) Copyright 1993, 1994 Novell, Inc.                                *
26  */
27
28 #ifndef lint
29 static char sccsid[] = "@(#)timeops.c 1.13 95/05/02 Copyr 1991 Sun Microsystems, Inc.";
30 #endif
31
32 #include <EUSCompat.h>
33 #include <stdio.h>
34 #include <unistd.h>
35 #include <stdlib.h>
36
37 #define XOS_USE_NO_LOCKING
38 #define X_INCLUDE_TIME_H
39 #include <X11/Xos_r.h>
40
41 #include <sys/param.h>
42 #include <sys/time.h>
43 #include <csa.h>
44 #include "util.h"
45 #include "timeops.h"
46 #include "getdate.h"
47
48 extern int debug;
49
50 typedef enum {dstoff, dston, nochange} DSTchange;
51
52 Tick bot, eot;
53
54 char *months[] = {"",
55            (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL,
56            (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL,
57            (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL
58 };
59
60 char *months2[] = {"",
61            (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL,
62            (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL,
63            (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL
64 };
65
66 int monthdays[12] = {
67         31,     28,     31,
68         30,     31,     30,
69         31,     31,     30,
70         31,     30,     31
71 };
72
73 int monthsecs[12] = {
74         31*daysec,      28*daysec,      31*daysec,
75         30*daysec,      31*daysec,      30*daysec,
76         31*daysec,      31*daysec,      30*daysec,
77         31*daysec,      30*daysec,      31*daysec
78 };
79
80 char *days[8] = {(char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL};
81
82 char *days2[8] = {(char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL};
83
84 char *days3[8] = {(char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL};
85
86 char *days4[8] = {(char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL};
87
88 char *numbers[32] = {"",
89         " 1 ", " 2 ", " 3 ", " 4 ", " 5 ", " 6 ", " 7 ",
90         " 8 ", " 9 ", "10", "11", "12", "13", "14",
91         "15", "16", "17", "18", "19", "20", "21",
92         "22", "23", "24", "25", "26", "27", "28",
93         "29", "30", "31"
94 };
95
96 char *hours[24] = {
97         "12", " 1", " 2", " 3", " 4", " 5", " 6", " 7", " 8", " 9", "10", "11",
98         "12", " 1", " 2", " 3", " 4", " 5", " 6", " 7", " 8", " 9", "10", "11"
99 };
100
101 /*
102  * Given a weekmask and the first day of the week, calculate
103  * the number of times outstanding in the week.
104  */
105 extern int
106 ntimes_this_week(u_int weekmask, int firstday)
107 {
108         int i, ntimes, weekdaymask = 1 << firstday;
109
110         if (weekmask == 0)
111                 return 0;
112
113         for (i=firstday, ntimes=0; i < 7; i++, weekdaymask <<= 1) {
114                 if (weekdaymask & weekmask)
115                         ntimes++;
116         }
117         return ntimes;
118 }
119
120 /* Return beginning of time */
121 extern Tick
122 get_bot()
123 {
124         return bot;
125 }
126
127 /* Return end of time */
128 extern Tick
129 get_eot()
130 {
131         return eot;
132 }
133
134 /* Given a weekmask, find the last appointment in the week */
135 extern int
136 lastapptofweek(u_int mask)
137 {
138         int n;
139
140         if (mask == 0)
141                 return -1;
142
143         for (n = -1; mask != 0; n++, mask = mask >> 1);
144
145         return n;
146 }
147
148 /*      Remove after v3 release */
149 extern boolean_t
150 magic_time(Tick t)
151 {
152         boolean_t magic=B_FALSE;
153         struct tm *tm;
154         _Xltimeparams localtime_buf;
155
156         tm = _XLocaltime(&t, localtime_buf);
157
158         if (tm->tm_hour == 3 && tm->tm_min == 41)
159                  magic=B_TRUE;
160         return(magic);
161 }
162 /* for 12 hour clock, if 24 subtract 12 */
163 extern boolean_t
164 adjust_hour(int *hr)
165 {
166         boolean_t am = B_TRUE;
167
168         if (*hr == 0)
169                 *hr = 12;
170         else if (*hr >= 12) {
171                 if (*hr > 12)
172                         *hr -= 12;
173                 am = B_FALSE;
174         }
175         return am;
176 }
177
178
179 extern int
180 timeok( Tick t)
181 {
182         int r =((t >= bot) &&(t <= eot));
183         return(r);
184 }
185
186 static DSTchange
187 dst_changed(Tick old, Tick new)
188 {       
189         struct tm oldtm;
190         struct tm newtm;
191         _Xltimeparams localtime_buf;
192
193         oldtm   = *_XLocaltime(&old, localtime_buf);
194         newtm   = *_XLocaltime(&new, localtime_buf);
195         
196         if(oldtm.tm_isdst ==  newtm.tm_isdst) return(nochange);
197         switch(oldtm.tm_isdst) {
198                 case 1:
199                         return(dstoff);
200                 case 0:
201                         return(dston);
202                 default:
203                         return(nochange);
204         }
205 }
206         
207 extern int
208 seconds(int n, Unit unit)
209 {
210         return(n *(int)unit);
211 }
212
213 extern double
214 seconds_dble(double n, Unit unit)
215 {
216         return((double)(n * (int)unit));
217 }
218
219 extern int
220 year(Tick t)
221 {
222         struct tm *tm;
223         _Xltimeparams localtime_buf;
224
225         tm = _XLocaltime(&t, localtime_buf);
226         return(tm->tm_year + 1900);
227 }
228
229 extern int
230 month(t)
231         Tick t;
232 {
233         struct tm *tm;
234         _Xltimeparams localtime_buf;
235
236         tm = _XLocaltime(&t, localtime_buf);
237         return(tm->tm_mon+1);
238 }
239
240 extern int
241 hour(Tick t)
242 {
243         struct tm *tm;
244         _Xltimeparams localtime_buf;
245
246         tm = _XLocaltime(&t, localtime_buf);
247         return(tm->tm_hour);
248 }
249
250 extern int
251 minute(Tick t)
252 {
253         struct tm *tm;
254         _Xltimeparams localtime_buf;
255
256         tm = _XLocaltime(&t, localtime_buf);
257         return(tm->tm_min);
258 }
259
260 extern int
261 leapyr(int y)
262 {
263         return
264          (y % 4 == 0 && y % 100 !=0 || y % 400 == 0);
265 }
266
267 extern int
268 monthlength(Tick t)
269 {
270         int mon;
271         struct tm tm;
272         _Xltimeparams localtime_buf;
273
274         tm = *_XLocaltime(&t, localtime_buf);
275         mon = tm.tm_mon;
276         return(((mon==1) && leapyr(tm.tm_year+1900))? 29 : monthdays[mon]);
277 }
278
279 extern int
280 monthseconds(Tick t)
281 {
282         int mon;
283         struct tm tm;
284         _Xltimeparams localtime_buf;
285         
286         tm = *_XLocaltime(&t, localtime_buf);
287         mon = tm.tm_mon;
288         return(((mon==1) && leapyr(tm.tm_year+1900))? 29*daysec : monthsecs[mon]);
289 }
290
291 extern int
292 dom(Tick t)
293 {
294         struct tm *tm;
295         _Xltimeparams localtime_buf;
296
297         tm = _XLocaltime(&t, localtime_buf);
298         return(tm->tm_mday);
299 }
300
301 extern int
302 wom(Tick t)
303 {
304         struct tm *tm;
305         _Xltimeparams localtime_buf;
306
307         tm = _XLocaltime(&t, localtime_buf);
308         return((12 + tm->tm_mday - tm->tm_wday)/7);
309 }
310
311 /*
312  * If the result falls beyond the system limit, -1 is returned by mktime().
313  */
314 Tick
315 next_nmonth(Tick t, int n)
316 {
317         struct tm tm;
318         int     n12;
319         _Xltimeparams localtime_buf;
320
321         n12 = n/12;
322         n = n%12;
323
324         tm = *_XLocaltime(&t, localtime_buf);
325         tm.tm_hour=0;
326         tm.tm_min=0;
327         tm.tm_sec=0;
328         tm.tm_mday=1;
329         if (n12 > 0)
330                 tm.tm_year += n12;
331
332         if ((tm.tm_mon = tm.tm_mon + n) > 11) {
333                 tm.tm_mon -= 12;
334                 tm.tm_year++;
335         }
336
337         tm.tm_isdst = -1;
338         return(mktime(&tm));
339 }
340
341 extern Tick
342 nextmonth(Tick t)
343 {
344         return(next_nmonth(t, 1));
345 }
346
347 extern boolean_t
348 weekofmonth(Tick t, int *wk)
349 {
350         struct tm tm, tm1, tm2;
351         Tick    firstday;
352         _Xltimeparams localtime_buf;
353
354         tm = *_XLocaltime(&t, localtime_buf);
355         tm.tm_hour = 0;
356         tm.tm_min = 0;
357         tm.tm_sec = 0;
358         tm.tm_mday = 1;
359         firstday = mktime(&tm);
360         tm = *_XLocaltime(&firstday, localtime_buf);
361
362         /* need to get it again since data in tm is changed */
363         tm1 = *_XLocaltime(&t, localtime_buf);
364
365         *wk = wom(t);
366         if (tm1.tm_wday < tm.tm_wday)
367                 (*wk)--;
368
369         if (*wk < 4)
370                 return B_FALSE;
371         else {
372                 t += seconds(7, daysec);
373                 tm2 = *_XLocaltime(&t, localtime_buf);
374
375                 return((tm1.tm_mon == tm2.tm_mon) ? B_FALSE : B_TRUE);
376         }
377 }
378
379 extern int
380 dow(Tick t)
381 {
382         struct tm tm;
383         _Xltimeparams localtime_buf;
384
385         tm = *_XLocaltime(&t, localtime_buf);
386         return(tm.tm_wday);
387 }
388
389 extern int /* find dow(0-6) that 1st dom falls on */
390 fdom(Tick t)
391 {
392         struct tm tm;
393         _Xltimeparams localtime_buf;
394
395         tm              = *_XLocaltime(&t, localtime_buf);
396         tm.tm_mday      = 1;
397         tm.tm_isdst     = -1;
398         t               = mktime(&tm);
399         tm              = *_XLocaltime(&t, localtime_buf);
400         return(tm.tm_wday);
401 }
402
403 extern int
404 ldom(Tick t /* find dow(0-6) that last dom falls on */ )
405 {
406         struct tm tm;
407         _Xltimeparams localtime_buf;
408
409         tm              = *_XLocaltime(&t, localtime_buf);
410         tm.tm_mday      = monthlength(t);
411         tm.tm_isdst     = -1;
412         t               = mktime(&tm);
413         tm              = *_XLocaltime(&t, localtime_buf);
414         return(tm.tm_wday);
415 }
416
417 /* returns tick of last day of month */
418 extern Tick
419 last_dom(Tick tick)
420 {
421         return(upperbound(next_ndays(tick, monthlength(tick) - dom(tick))));
422 }
423
424 /* returns tick of first day of month */
425 extern Tick
426 first_dom(Tick tick)
427 {
428         return(lowerbound(last_ndays(tick, dom(tick)-1)));
429 }
430
431 /* returns tick of first day of week */
432 extern Tick
433 first_dow(Tick tick)
434 {
435         int d;
436
437         if ((d = dow(tick)) == 0)
438                 d = 6;
439         else 
440                 d--;
441
442         return(lowerbound(last_ndays(tick, d)));
443 }
444
445 /* returns tick of first day of week */
446 extern Tick
447 last_dow(Tick tick)
448 {
449         int d;
450
451         if ((d = dow(tick)) == 0)
452                 d = 6;
453         else 
454                 d--;
455         d = 6 - d;
456
457         return(upperbound(next_ndays(tick, d)));
458 }
459 /* returns number of weeks in month */
460 extern int
461 numwks(Tick tick)
462 {
463         return (wom(last_dom(tick)));
464 }
465
466 extern int
467 adjust_dst(Tick start, Tick next) 
468 {
469         DSTchange change;
470         change = dst_changed(start, next);
471         switch(change) {
472                 case nochange:
473                 break;
474                 case dstoff:
475                         next+=(int) hrsec;
476                 break;
477                 case dston:
478                         next-=(int) hrsec;
479                 break;
480         }
481         return(next);
482 }
483
484 extern Tick
485 next_nhours(Tick t, int n)
486 {
487         Tick next;
488         struct tm tm;
489         _Xltimeparams localtime_buf;
490
491         tm              = *_XLocaltime(&t, localtime_buf);
492         tm.tm_sec       = 0;
493         tm.tm_min       = 0;
494  
495         next            = mktime(&tm);
496         next            = next + seconds(n, hrsec);
497         next            = adjust_dst(t, next);
498         return(next);
499 }
500
501 extern Tick
502 last_ndays(Tick t, int n)
503 {
504         Tick last;
505         struct tm tm;
506         _Xltimeparams localtime_buf;
507
508         tm              = *_XLocaltime(&t, localtime_buf);
509         tm.tm_sec       = 0;
510         tm.tm_min       = 0;
511         tm.tm_hour      = 0;
512
513         last            = mktime(&tm);
514         last            = last - seconds(n, daysec);
515         last            = adjust_dst(t, last);
516         return(last);
517 }
518
519 extern Tick
520 next_ndays(Tick t, int n)
521 {
522         Tick next;
523         struct tm tm;
524         _Xltimeparams localtime_buf;
525
526         tm              = *_XLocaltime(&t, localtime_buf);
527         tm.tm_sec       = 0;
528         tm.tm_min       = 0;
529         tm.tm_hour      = 0;
530
531 #ifdef SVR4
532         next            = mktime(&tm);
533 #else
534         next            = timelocal(&tm);
535 #endif /* SVR4 */
536         next            = next + seconds(n, daysec);
537         next            = adjust_dst(t, next);
538         return(next);
539 }
540
541 extern Tick
542 nextday(Tick t)
543 {
544         Tick next;
545
546         next    = t +(int)daysec;
547         next    = adjust_dst(t, next);
548         return(next);
549 }
550
551 extern Tick
552 prevday(Tick t)
553 {
554         Tick prev;
555
556         prev    = t - (int)daysec;
557         prev    = adjust_dst(t, prev);
558         return(prev);
559 }
560
561 extern Tick
562 nextweek(Tick t)
563 {
564         Tick next;
565
566         next    = t + seconds(7, daysec);
567         next    = adjust_dst(t, next);
568         return(next);
569 }
570
571 extern Tick
572 prevweek(Tick t)
573 {
574         Tick prev;
575
576         prev    = t - seconds(7, daysec);
577         prev    = adjust_dst(t, prev);
578         return(prev);
579 }
580
581 extern Tick
582 next2weeks(Tick t)
583 {
584         Tick next;
585
586         next    = t + seconds(14, daysec);
587         next    = adjust_dst(t, next);
588         return(next);
589 }
590
591 extern Tick
592 prev2weeks(Tick t)
593 {
594         Tick prev;
595
596         prev    = t - seconds(14, daysec);
597         prev    = adjust_dst(t, prev);
598         return(prev);
599 }
600
601 /*              WORK OUT A BETTER WAY TO DO THIS!!      */
602 extern Tick
603 prevmonth_exactday(Tick t)
604 {
605         Tick prev; int day;
606         struct tm tm;
607         int sdelta;
608         _Xltimeparams localtime_buf;
609
610         tm = *_XLocaltime(&t, localtime_buf);
611         sdelta = tm.tm_hour * hrsec + tm.tm_min * minsec + tm.tm_sec; 
612         day = tm.tm_mday;
613         if((tm.tm_mday < 31 && tm.tm_mon != 0) ||       /* at least 30 days everywhere, except Feb.*/
614            (tm.tm_mday==31 && tm.tm_mon==6)    ||       /* two 31s -- Jul./Aug.         */
615            (tm.tm_mday==31 && tm.tm_mon==11)   ||       /* two 31s -- Dec./Jan.         */
616            (tm.tm_mon == 0 &&(tm.tm_mday < 29  ||(tm.tm_mday==29 && leapyr(tm.tm_year+1900))))) {       
617                 prev = t-monthseconds(previousmonth(t));
618                 prev = adjust_dst(t, prev);
619         }
620         else {  /* brute force */
621                 prev = previousmonth(previousmonth(t));         /* hop over the month */
622                 tm = *_XLocaltime(&prev, localtime_buf);
623                 tm.tm_mday = day;
624 #ifdef SVR4
625                 tm.tm_isdst = -1;
626                 prev =(mktime(&tm)) + sdelta;
627 #else
628                 prev =(timelocal(&tm)) + sdelta;
629 #endif /* SVR4 */
630
631         }
632         return(prev);
633 }
634
635 /*              WORK OUT A BETTER WAY TO DO THIS!!      */
636 extern Tick
637 nextmonth_exactday(Tick t)
638 {
639         Tick next; int day;
640         struct tm tm;
641         int sdelta;
642         _Xltimeparams localtime_buf;
643
644         tm = *_XLocaltime(&t, localtime_buf);
645         sdelta = tm.tm_hour * hrsec + tm.tm_min * minsec + tm.tm_sec; 
646         day = tm.tm_mday;
647         if((tm.tm_mday < 31 && tm.tm_mon != 0) ||       /* at least 30 days everywhere, except Feb.*/
648            (tm.tm_mday==31 && tm.tm_mon==6)    ||       /* two 31s -- Jul./Aug.         */
649            (tm.tm_mday==31 && tm.tm_mon==11)   ||       /* two 31s -- Dec./Jan.         */
650            (tm.tm_mon == 0 &&(tm.tm_mday < 29  ||(tm.tm_mday==29 && leapyr(tm.tm_year+1900))))) {       
651                 next = t+monthseconds(t);
652                 next = adjust_dst(t, next);
653         }
654         else {  /* brute force */
655                 next = next_nmonth(t, 2);               /* hop over the month */
656                 tm = *_XLocaltime(&next, localtime_buf);
657                 tm.tm_mday = day;
658 #ifdef SVR4
659                 tm.tm_isdst = -1;
660                 next = mktime(&tm) + sdelta;
661 #else
662                 next =(timelocal(&tm)) + sdelta;
663 #endif /* SVR4 */
664         }
665         return(next);
666 }
667
668 extern Tick
669 nextnyear(Tick t, int n)
670 {
671         struct tm tm;
672         _Xltimeparams localtime_buf;
673
674         tm      = *_XLocaltime(&t, localtime_buf);
675         tm.tm_year += n;
676 #ifdef SVR4
677         return(mktime(&tm));
678 #else
679         return(timelocal(&tm));
680 #endif /* SVR4 */
681 }
682
683 extern Tick
684 nextyear(Tick t)
685 {
686         return(nextnyear(t, 1));
687 }
688
689 extern Tick
690 prevnday_exacttime(Tick t, int n)
691 {
692         Tick prev;
693
694         prev    = t - seconds(n, daysec);
695         prev    = adjust_dst(t, prev);
696         return(prev);
697 }
698
699 extern Tick
700 prevnyear(Tick t, int n)
701 {
702         struct tm tm;
703         _Xltimeparams localtime_buf;
704
705         tm = *_XLocaltime(&t, localtime_buf);
706         tm.tm_year -= n;
707 #ifdef SVR4
708         return(mktime(&tm));
709 #else
710         return(timelocal(&tm));
711 #endif /* SVR4 */
712 }
713
714 extern Tick
715 prevyear(Tick t)
716 {
717         return(prevnyear(t, 1));
718 }
719
720 extern Tick
721 previousmonth(Tick t)
722 {
723         struct tm tm;
724         _Xltimeparams localtime_buf;
725
726         tm = *_XLocaltime(&t, localtime_buf);
727         tm.tm_hour=0;
728         tm.tm_min=0;
729         tm.tm_sec=0;
730         if(tm.tm_mon==0) {
731                 tm.tm_mon=11;
732                 tm.tm_mday=1;
733                 tm.tm_year--;
734         }
735         else {
736                 tm.tm_mday=1;
737                 tm.tm_mon--;
738         }
739 #ifdef SVR4
740         tm.tm_isdst = -1;
741         return(mktime(&tm));
742 #else
743         return(timelocal(&tm));
744 #endif /* SVR4 */
745 }
746
747 extern Tick
748 prev_nmonth(Tick t, int n)
749 {
750         struct tm tm;
751         int     n12;
752         _Xltimeparams localtime_buf;
753
754         n12 = n/12;
755         n = n%12;
756
757         tm = *_XLocaltime(&t, localtime_buf);
758         tm.tm_hour=0;
759         tm.tm_min=0;
760         tm.tm_sec=0;
761         tm.tm_mday=1;
762         if (n12 > 0)
763                 tm.tm_year -= n12;
764
765         if ((tm.tm_mon = tm.tm_mon - n) < 0) {
766                 tm.tm_mon += 12;
767                 tm.tm_year--;
768         }
769 #ifdef SVR4
770         tm.tm_isdst = -1;
771         return(mktime(&tm));
772 #else
773         return(timelocal(&tm));
774 #endif /* SVR4 */
775 }
776
777 extern Tick
778 jan1(Tick t)
779 {
780         struct tm tm;
781         _Xltimeparams localtime_buf;
782
783         tm              = *_XLocaltime(&t, localtime_buf);
784         tm.tm_mon       = 0;
785         tm.tm_mday      = 1;
786 #ifdef SVR4
787         tm.tm_isdst = -1;
788         return(mktime(&tm));
789 #else
790         return(timelocal(&tm));
791 #endif /* SVR4 */
792 }
793
794 extern Tick
795 nextjan1(Tick t)
796 {
797         struct tm tm;
798         _Xltimeparams localtime_buf;
799
800         tm              = *_XLocaltime(&t, localtime_buf);
801         tm.tm_mon       = 0;
802         tm.tm_mday      = 1;
803         tm.tm_year++;    
804 #ifdef SVR4
805         tm.tm_isdst = -1;
806         return(mktime(&tm));
807 #else
808         return(timelocal(&tm));
809 #endif /* SVR4 */
810 }
811
812 extern Tick
813 lastjan1(Tick t)
814 {
815         struct tm tm;
816         _Xltimeparams localtime_buf;
817
818         tm              = *_XLocaltime(&t, localtime_buf);
819         tm.tm_mon       = 0;
820         tm.tm_mday      = 1;
821         tm.tm_year--;    
822 #ifdef SVR4
823         tm.tm_isdst = -1;
824         return(mktime(&tm));
825 #else
826         return(timelocal(&tm));
827 #endif /* SVR4 */
828 }
829
830 extern Tick
831 lowerbound(Tick t)
832 {
833         struct tm tm;
834         _Xltimeparams localtime_buf;
835
836         tm              =  *_XLocaltime(&t, localtime_buf);
837         tm.tm_sec       =  0;
838         tm.tm_min       =  0;
839         tm.tm_hour      =  0;
840         tm.tm_isdst     = -1;
841 #ifdef SVR4
842         return(mktime(&tm));
843 #else
844         return(timelocal(&tm));
845 #endif /* SVR4 */
846 }
847 extern Tick
848 lower_bound(int i, Tick t)
849 {
850         struct tm tm;
851         _Xltimeparams localtime_buf;
852
853         tm              =  *_XLocaltime(&t, localtime_buf);
854         tm.tm_sec       =  0;
855         tm.tm_min       =  0;
856         tm.tm_hour      =  i;
857         tm.tm_isdst     = -1;
858 #ifdef SVR4
859         return(mktime(&tm));
860 #else
861         return (timelocal(&tm));
862 #endif /* SVR4 */
863 }
864 extern Tick
865 upperbound(Tick t)
866 {
867         struct tm tm;
868         _Xltimeparams localtime_buf;
869
870         tm              =  *_XLocaltime(&t, localtime_buf);
871         tm.tm_sec       =  59;
872         tm.tm_min       =  59;
873         tm.tm_hour      =  23;
874         tm.tm_isdst     = -1;
875 #ifdef SVR4
876         return(mktime(&tm)-1);
877 #else
878         return(timelocal(&tm)-1);
879 #endif /* SVR4 */
880 }
881
882 static int
883 leapsB4(int y)
884 {
885         return((y-1)/4 -(y-1)/100 +(y-1)/400);
886 }
887
888 extern Tick
889 xytoclock(int x, int y, Tick t)
890 {
891         int dd, mn, yr, ly, leaps;
892         char buf[10];
893         struct tm tm;
894         struct tm timestruct;
895         Tick tick;
896         _Xltimeparams localtime_buf;
897
898         memset(&timestruct, NULL, sizeof(struct tm));
899
900         tm      = *_XLocaltime(&t, localtime_buf);
901         mn      = tm.tm_mon + 1;
902         yr      = tm.tm_year + 1900;
903         leaps   = leapsB4(yr);
904         ly      = leapyr(yr);
905
906         dd = 7*(y-1) + x - 
907          (yr+leaps+3055L*(mn+2)/100-84-(mn>2)*(2-ly))%7;
908
909         timestruct.tm_mon = tm.tm_mon;
910         timestruct.tm_mday = dd;
911         timestruct.tm_year = tm.tm_year;
912         timestruct.tm_sec = 0;
913         timestruct.tm_isdst = -1;
914
915         tick = mktime(&timestruct);
916         return(tick);
917 }
918
919 extern Tick
920 now()
921 {
922         return(time(0));
923 }
924
925 extern void
926 set_timezone(char *tzname)
927 {
928         static char tzenv[MAXPATHLEN];
929
930 #ifdef SVR4
931         /* I don't like using 'system', but this does the right
932          * thing according to tha man pages
933          */
934         if (tzname==NULL) system("unset TZ\n");
935 #else
936         if (tzname==NULL) tzsetwall();
937 #endif /* SVR4 */
938
939         else {
940                 sprintf(tzenv, "TZ=%s", tzname);
941                 putenv(tzenv);
942                 tzset();
943         }
944 }
945  
946 extern long
947 gmt_off()
948 {
949         struct tm tm;
950         Tick t;
951         static Tick gmt;
952  
953 #ifdef SVR4
954         extern long timezone;
955
956         gmt             = timezone;
957 #else
958         _Xltimeparams localtime_buf;
959
960         t       = now();
961         tm      = *_XLocaltime(&t, localtime_buf);
962         gmt = tm.tm_gmtoff;
963 #endif /* SVR4 */
964         return(gmt);
965 }
966
967
968 /* [ytso 1/26/93]
969  * cm now supports to up end of 1999.  This is due to the limitation
970  * of cm_getdate() which can only handle up to end of 1999.
971  * When cm_getdate() is improved to handle up to the system limit,
972  * definitions of eot and EOT need to be changed as well as some
973  * of the routines in this file and the caller of these routines.
974  */
975 extern void
976 init_time()
977 {
978         struct tm tm, gm;
979         Tick    t;
980         _Xltimeparams localtime_buf;
981         _Xgtimeparams gmtime_buf;
982
983         /* Fix for QAR 31607 */
984         tzset();
985         if (getenv("TZ") == NULL){
986                 char *tzptr;
987                 tzptr = malloc(strlen(tzname[0]) + strlen(tzname[1]) + 10);
988                 sprintf (tzptr,"TZ=%s%d%s", tzname[0], timezone/3600, tzname[1]);
989                 putenv(tzptr);
990                 tzset();
991         }
992
993         t               = now();
994         tm              = *_XLocaltime(&t, localtime_buf);
995         gm              = *_XGmtime(&t, gmtime_buf);
996
997         bot             = mktime(&gm) - mktime(&tm);
998
999         tm.tm_sec       =59;
1000         tm.tm_min       =59;
1001         tm.tm_hour      =23;
1002         tm.tm_mday      =31;
1003         tm.tm_mon       =11;
1004         tm.tm_year      =137;                   /* Dec. 31, 2037 */
1005         tm.tm_isdst = -1;
1006         eot             =mktime(&tm);
1007 }
1008
1009 extern int
1010 seconds_to_hours(int n)
1011 {
1012         return(n/(int)hrsec);
1013 }
1014
1015 extern int
1016 hours_to_seconds(int n)
1017 {
1018         return(n *(int)hrsec);
1019 }
1020
1021 extern int
1022 seconds_to_minutes(int n)
1023 {
1024         return(n/60);
1025 }
1026
1027 extern int
1028 minutes_to_seconds(int n)
1029 {
1030         return(n *(int)minsec);
1031 }
1032
1033
1034 extern int
1035 days_to_seconds(int n)
1036 {
1037         return(n *(int)daysec);
1038 }
1039
1040 seconds_to_days(int n)
1041 {
1042         return(n/(int)daysec);
1043 }
1044
1045 /*
1046 extern int
1047 weeks_to_seconds(int n)
1048 {
1049         return(n *(int)wksec);
1050 }
1051
1052 extern int
1053 seconds_to_weeks(int)
1054 {
1055         return(n/(int)wksec);
1056 }
1057 */
1058
1059 extern Tick
1060 monthdayyear(int m, int d, int y)
1061 {
1062         int t, t1;
1063         char buf[10];
1064
1065         struct tm timestruct;
1066
1067         memset(&timestruct, NULL, sizeof(struct tm));
1068         timestruct.tm_mon = m - 1;
1069         timestruct.tm_mday = d;
1070         timestruct.tm_year = y - 1900;
1071         timestruct.tm_sec = 0;
1072         timestruct.tm_isdst = -1;
1073
1074         t = mktime(&timestruct);
1075 /*
1076         sprintf(buf, "%d/%d/%d", m, d, y);
1077         t = cm_getdate(buf, NULL);
1078
1079 printf("monthdayyear, m= %d, d = %d, y = %d, t1 = %d, t = %d\n", m, d, y, t1, t);
1080         
1081 */
1082         return(t);
1083 }