1 /*******************************************************************************
5 ** $XConsortium: timeops.c /main/6 1996/11/21 19:44:23 drk $
7 ** RESTRICTED CONFIDENTIAL INFORMATION:
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
17 ** Copyright 1993 Sun Microsystems, Inc. All rights reserved.
19 *******************************************************************************/
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. *
29 static char sccsid[] = "@(#)timeops.c 1.13 95/05/02 Copyr 1991 Sun Microsystems, Inc.";
32 #include <EUSCompat.h>
37 #define XOS_USE_NO_LOCKING
38 #define X_INCLUDE_TIME_H
39 #include <X11/Xos_r.h>
41 #include <sys/param.h>
50 typedef enum {dstoff, dston, nochange} DSTchange;
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
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
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
80 char *days[8] = {(char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL};
82 char *days2[8] = {(char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL};
84 char *days3[8] = {(char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL};
86 char *days4[8] = {(char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL};
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",
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"
102 * Given a weekmask and the first day of the week, calculate
103 * the number of times outstanding in the week.
106 ntimes_this_week(u_int weekmask, int firstday)
108 int i, ntimes, weekdaymask = 1 << firstday;
113 for (i=firstday, ntimes=0; i < 7; i++, weekdaymask <<= 1) {
114 if (weekdaymask & weekmask)
120 /* Return beginning of time */
127 /* Return end of time */
134 /* Given a weekmask, find the last appointment in the week */
136 lastapptofweek(u_int mask)
143 for (n = -1; mask != 0; n++, mask = mask >> 1);
148 /* Remove after v3 release */
152 boolean_t magic=B_FALSE;
154 _Xltimeparams localtime_buf;
156 tm = _XLocaltime(&t, localtime_buf);
158 if (tm->tm_hour == 3 && tm->tm_min == 41)
162 /* for 12 hour clock, if 24 subtract 12 */
166 boolean_t am = B_TRUE;
170 else if (*hr >= 12) {
182 int r =((t >= bot) &&(t <= eot));
187 dst_changed(Tick old, Tick new)
191 _Xltimeparams localtime_buf;
193 oldtm = *_XLocaltime(&old, localtime_buf);
194 newtm = *_XLocaltime(&new, localtime_buf);
196 if(oldtm.tm_isdst == newtm.tm_isdst) return(nochange);
197 switch(oldtm.tm_isdst) {
208 seconds(int n, Unit unit)
210 return(n *(int)unit);
214 seconds_dble(double n, Unit unit)
216 return((double)(n * (int)unit));
223 _Xltimeparams localtime_buf;
225 tm = _XLocaltime(&t, localtime_buf);
226 return(tm->tm_year + 1900);
234 _Xltimeparams localtime_buf;
236 tm = _XLocaltime(&t, localtime_buf);
237 return(tm->tm_mon+1);
244 _Xltimeparams localtime_buf;
246 tm = _XLocaltime(&t, localtime_buf);
254 _Xltimeparams localtime_buf;
256 tm = _XLocaltime(&t, localtime_buf);
264 (y % 4 == 0 && y % 100 !=0 || y % 400 == 0);
272 _Xltimeparams localtime_buf;
274 tm = *_XLocaltime(&t, localtime_buf);
276 return(((mon==1) && leapyr(tm.tm_year+1900))? 29 : monthdays[mon]);
284 _Xltimeparams localtime_buf;
286 tm = *_XLocaltime(&t, localtime_buf);
288 return(((mon==1) && leapyr(tm.tm_year+1900))? 29*daysec : monthsecs[mon]);
295 _Xltimeparams localtime_buf;
297 tm = _XLocaltime(&t, localtime_buf);
305 _Xltimeparams localtime_buf;
307 tm = _XLocaltime(&t, localtime_buf);
308 return((12 + tm->tm_mday - tm->tm_wday)/7);
312 * If the result falls beyond the system limit, -1 is returned by mktime().
315 next_nmonth(Tick t, int n)
319 _Xltimeparams localtime_buf;
324 tm = *_XLocaltime(&t, localtime_buf);
332 if ((tm.tm_mon = tm.tm_mon + n) > 11) {
344 return(next_nmonth(t, 1));
348 weekofmonth(Tick t, int *wk)
350 struct tm tm, tm1, tm2;
352 _Xltimeparams localtime_buf;
354 tm = *_XLocaltime(&t, localtime_buf);
359 firstday = mktime(&tm);
360 tm = *_XLocaltime(&firstday, localtime_buf);
362 /* need to get it again since data in tm is changed */
363 tm1 = *_XLocaltime(&t, localtime_buf);
366 if (tm1.tm_wday < tm.tm_wday)
372 t += seconds(7, daysec);
373 tm2 = *_XLocaltime(&t, localtime_buf);
375 return((tm1.tm_mon == tm2.tm_mon) ? B_FALSE : B_TRUE);
383 _Xltimeparams localtime_buf;
385 tm = *_XLocaltime(&t, localtime_buf);
389 extern int /* find dow(0-6) that 1st dom falls on */
393 _Xltimeparams localtime_buf;
395 tm = *_XLocaltime(&t, localtime_buf);
399 tm = *_XLocaltime(&t, localtime_buf);
404 ldom(Tick t /* find dow(0-6) that last dom falls on */ )
407 _Xltimeparams localtime_buf;
409 tm = *_XLocaltime(&t, localtime_buf);
410 tm.tm_mday = monthlength(t);
413 tm = *_XLocaltime(&t, localtime_buf);
417 /* returns tick of last day of month */
421 return(upperbound(next_ndays(tick, monthlength(tick) - dom(tick))));
424 /* returns tick of first day of month */
428 return(lowerbound(last_ndays(tick, dom(tick)-1)));
431 /* returns tick of first day of week */
437 if ((d = dow(tick)) == 0)
442 return(lowerbound(last_ndays(tick, d)));
445 /* returns tick of first day of week */
451 if ((d = dow(tick)) == 0)
457 return(upperbound(next_ndays(tick, d)));
459 /* returns number of weeks in month */
463 return (wom(last_dom(tick)));
467 adjust_dst(Tick start, Tick next)
470 change = dst_changed(start, next);
485 next_nhours(Tick t, int n)
489 _Xltimeparams localtime_buf;
491 tm = *_XLocaltime(&t, localtime_buf);
496 next = next + seconds(n, hrsec);
497 next = adjust_dst(t, next);
502 last_ndays(Tick t, int n)
506 _Xltimeparams localtime_buf;
508 tm = *_XLocaltime(&t, localtime_buf);
514 last = last - seconds(n, daysec);
515 last = adjust_dst(t, last);
520 next_ndays(Tick t, int n)
524 _Xltimeparams localtime_buf;
526 tm = *_XLocaltime(&t, localtime_buf);
534 next = timelocal(&tm);
536 next = next + seconds(n, daysec);
537 next = adjust_dst(t, next);
546 next = t +(int)daysec;
547 next = adjust_dst(t, next);
556 prev = t - (int)daysec;
557 prev = adjust_dst(t, prev);
566 next = t + seconds(7, daysec);
567 next = adjust_dst(t, next);
576 prev = t - seconds(7, daysec);
577 prev = adjust_dst(t, prev);
586 next = t + seconds(14, daysec);
587 next = adjust_dst(t, next);
596 prev = t - seconds(14, daysec);
597 prev = adjust_dst(t, prev);
601 /* WORK OUT A BETTER WAY TO DO THIS!! */
603 prevmonth_exactday(Tick t)
608 _Xltimeparams localtime_buf;
610 tm = *_XLocaltime(&t, localtime_buf);
611 sdelta = tm.tm_hour * hrsec + tm.tm_min * minsec + tm.tm_sec;
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);
620 else { /* brute force */
621 prev = previousmonth(previousmonth(t)); /* hop over the month */
622 tm = *_XLocaltime(&prev, localtime_buf);
626 prev =(mktime(&tm)) + sdelta;
628 prev =(timelocal(&tm)) + sdelta;
635 /* WORK OUT A BETTER WAY TO DO THIS!! */
637 nextmonth_exactday(Tick t)
642 _Xltimeparams localtime_buf;
644 tm = *_XLocaltime(&t, localtime_buf);
645 sdelta = tm.tm_hour * hrsec + tm.tm_min * minsec + tm.tm_sec;
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);
654 else { /* brute force */
655 next = next_nmonth(t, 2); /* hop over the month */
656 tm = *_XLocaltime(&next, localtime_buf);
660 next = mktime(&tm) + sdelta;
662 next =(timelocal(&tm)) + sdelta;
669 nextnyear(Tick t, int n)
672 _Xltimeparams localtime_buf;
674 tm = *_XLocaltime(&t, localtime_buf);
679 return(timelocal(&tm));
686 return(nextnyear(t, 1));
690 prevnday_exacttime(Tick t, int n)
694 prev = t - seconds(n, daysec);
695 prev = adjust_dst(t, prev);
700 prevnyear(Tick t, int n)
703 _Xltimeparams localtime_buf;
705 tm = *_XLocaltime(&t, localtime_buf);
710 return(timelocal(&tm));
717 return(prevnyear(t, 1));
721 previousmonth(Tick t)
724 _Xltimeparams localtime_buf;
726 tm = *_XLocaltime(&t, localtime_buf);
743 return(timelocal(&tm));
748 prev_nmonth(Tick t, int n)
752 _Xltimeparams localtime_buf;
757 tm = *_XLocaltime(&t, localtime_buf);
765 if ((tm.tm_mon = tm.tm_mon - n) < 0) {
773 return(timelocal(&tm));
781 _Xltimeparams localtime_buf;
783 tm = *_XLocaltime(&t, localtime_buf);
790 return(timelocal(&tm));
798 _Xltimeparams localtime_buf;
800 tm = *_XLocaltime(&t, localtime_buf);
808 return(timelocal(&tm));
816 _Xltimeparams localtime_buf;
818 tm = *_XLocaltime(&t, localtime_buf);
826 return(timelocal(&tm));
834 _Xltimeparams localtime_buf;
836 tm = *_XLocaltime(&t, localtime_buf);
844 return(timelocal(&tm));
848 lower_bound(int i, Tick t)
851 _Xltimeparams localtime_buf;
853 tm = *_XLocaltime(&t, localtime_buf);
861 return (timelocal(&tm));
868 _Xltimeparams localtime_buf;
870 tm = *_XLocaltime(&t, localtime_buf);
876 return(mktime(&tm)-1);
878 return(timelocal(&tm)-1);
885 return((y-1)/4 -(y-1)/100 +(y-1)/400);
889 xytoclock(int x, int y, Tick t)
891 int dd, mn, yr, ly, leaps;
894 struct tm timestruct;
896 _Xltimeparams localtime_buf;
898 memset(×truct, NULL, sizeof(struct tm));
900 tm = *_XLocaltime(&t, localtime_buf);
902 yr = tm.tm_year + 1900;
907 (yr+leaps+3055L*(mn+2)/100-84-(mn>2)*(2-ly))%7;
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;
915 tick = mktime(×truct);
926 set_timezone(char *tzname)
928 static char tzenv[MAXPATHLEN];
931 /* I don't like using 'system', but this does the right
932 * thing according to tha man pages
934 if (tzname==NULL) system("unset TZ\n");
936 if (tzname==NULL) tzsetwall();
940 sprintf(tzenv, "TZ=%s", tzname);
954 extern long timezone;
958 _Xltimeparams localtime_buf;
961 tm = *_XLocaltime(&t, localtime_buf);
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.
980 _Xltimeparams localtime_buf;
981 _Xgtimeparams gmtime_buf;
983 /* Fix for QAR 31607 */
985 if (getenv("TZ") == NULL){
987 tzptr = malloc(strlen(tzname[0]) + strlen(tzname[1]) + 10);
988 sprintf (tzptr,"TZ=%s%d%s", tzname[0], timezone/3600, tzname[1]);
994 tm = *_XLocaltime(&t, localtime_buf);
995 gm = *_XGmtime(&t, gmtime_buf);
997 bot = mktime(&gm) - mktime(&tm);
1004 tm.tm_year =137; /* Dec. 31, 2037 */
1010 seconds_to_hours(int n)
1012 return(n/(int)hrsec);
1016 hours_to_seconds(int n)
1018 return(n *(int)hrsec);
1022 seconds_to_minutes(int n)
1028 minutes_to_seconds(int n)
1030 return(n *(int)minsec);
1035 days_to_seconds(int n)
1037 return(n *(int)daysec);
1040 seconds_to_days(int n)
1042 return(n/(int)daysec);
1047 weeks_to_seconds(int n)
1049 return(n *(int)wksec);
1053 seconds_to_weeks(int)
1055 return(n/(int)wksec);
1060 monthdayyear(int m, int d, int y)
1065 struct tm timestruct;
1067 memset(×truct, 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;
1074 t = mktime(×truct);
1076 sprintf(buf, "%d/%d/%d", m, d, y);
1077 t = cm_getdate(buf, NULL);
1079 printf("monthdayyear, m= %d, d = %d, y = %d, t1 = %d, t = %d\n", m, d, y, t1, t);