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