2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
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)
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
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
23 /*******************************************************************************
27 ** $XConsortium: timeops.c /main/6 1996/11/21 19:44:23 drk $
29 ** RESTRICTED CONFIDENTIAL INFORMATION:
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
39 ** Copyright 1993 Sun Microsystems, Inc. All rights reserved.
41 *******************************************************************************/
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. *
51 static char sccsid[] = "@(#)timeops.c 1.13 95/05/02 Copyr 1991 Sun Microsystems, Inc.";
54 #include <EUSCompat.h>
59 #define XOS_USE_NO_LOCKING
60 #define X_INCLUDE_TIME_H
61 #include <X11/Xos_r.h>
63 #include <sys/param.h>
72 typedef enum {dstoff, dston, nochange} DSTchange;
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
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
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
102 char *days[8] = {(char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL};
104 char *days2[8] = {(char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL};
106 char *days3[8] = {(char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL};
108 char *days4[8] = {(char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL};
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",
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"
124 * Given a weekmask and the first day of the week, calculate
125 * the number of times outstanding in the week.
128 ntimes_this_week(u_int weekmask, int firstday)
130 int i, ntimes, weekdaymask = 1 << firstday;
135 for (i=firstday, ntimes=0; i < 7; i++, weekdaymask <<= 1) {
136 if (weekdaymask & weekmask)
142 /* Return beginning of time */
149 /* Return end of time */
156 /* Given a weekmask, find the last appointment in the week */
158 lastapptofweek(u_int mask)
165 for (n = -1; mask != 0; n++, mask = mask >> 1);
170 /* Remove after v3 release */
174 boolean_t magic=B_FALSE;
176 _Xltimeparams localtime_buf;
178 tm = _XLocaltime(&t, localtime_buf);
180 if (tm->tm_hour == 3 && tm->tm_min == 41)
184 /* for 12 hour clock, if 24 subtract 12 */
188 boolean_t am = B_TRUE;
192 else if (*hr >= 12) {
204 int r =((t >= bot) &&(t <= eot));
209 dst_changed(Tick old, Tick new)
213 _Xltimeparams localtime_buf;
215 oldtm = *_XLocaltime(&old, localtime_buf);
216 newtm = *_XLocaltime(&new, localtime_buf);
218 if(oldtm.tm_isdst == newtm.tm_isdst) return(nochange);
219 switch(oldtm.tm_isdst) {
230 seconds(int n, Unit unit)
232 return(n *(int)unit);
236 seconds_dble(double n, Unit unit)
238 return((double)(n * (int)unit));
245 _Xltimeparams localtime_buf;
247 tm = _XLocaltime(&t, localtime_buf);
248 return(tm->tm_year + 1900);
256 _Xltimeparams localtime_buf;
258 tm = _XLocaltime(&t, localtime_buf);
259 return(tm->tm_mon+1);
266 _Xltimeparams localtime_buf;
268 tm = _XLocaltime(&t, localtime_buf);
276 _Xltimeparams localtime_buf;
278 tm = _XLocaltime(&t, localtime_buf);
286 (y % 4 == 0 && y % 100 !=0 || y % 400 == 0);
294 _Xltimeparams localtime_buf;
296 tm = *_XLocaltime(&t, localtime_buf);
298 return(((mon==1) && leapyr(tm.tm_year+1900))? 29 : monthdays[mon]);
306 _Xltimeparams localtime_buf;
308 tm = *_XLocaltime(&t, localtime_buf);
310 return(((mon==1) && leapyr(tm.tm_year+1900))? 29*daysec : monthsecs[mon]);
317 _Xltimeparams localtime_buf;
319 tm = _XLocaltime(&t, localtime_buf);
327 _Xltimeparams localtime_buf;
329 tm = _XLocaltime(&t, localtime_buf);
330 return((12 + tm->tm_mday - tm->tm_wday)/7);
334 * If the result falls beyond the system limit, -1 is returned by mktime().
337 next_nmonth(Tick t, int n)
341 _Xltimeparams localtime_buf;
346 tm = *_XLocaltime(&t, localtime_buf);
354 if ((tm.tm_mon = tm.tm_mon + n) > 11) {
366 return(next_nmonth(t, 1));
370 weekofmonth(Tick t, int *wk)
372 struct tm tm, tm1, tm2;
374 _Xltimeparams localtime_buf;
376 tm = *_XLocaltime(&t, localtime_buf);
381 firstday = mktime(&tm);
382 tm = *_XLocaltime(&firstday, localtime_buf);
384 /* need to get it again since data in tm is changed */
385 tm1 = *_XLocaltime(&t, localtime_buf);
388 if (tm1.tm_wday < tm.tm_wday)
394 t += seconds(7, daysec);
395 tm2 = *_XLocaltime(&t, localtime_buf);
397 return((tm1.tm_mon == tm2.tm_mon) ? B_FALSE : B_TRUE);
405 _Xltimeparams localtime_buf;
407 tm = *_XLocaltime(&t, localtime_buf);
411 extern int /* find dow(0-6) that 1st dom falls on */
415 _Xltimeparams localtime_buf;
417 tm = *_XLocaltime(&t, localtime_buf);
421 tm = *_XLocaltime(&t, localtime_buf);
426 ldom(Tick t /* find dow(0-6) that last dom falls on */ )
429 _Xltimeparams localtime_buf;
431 tm = *_XLocaltime(&t, localtime_buf);
432 tm.tm_mday = monthlength(t);
435 tm = *_XLocaltime(&t, localtime_buf);
439 /* returns tick of last day of month */
443 return(upperbound(next_ndays(tick, monthlength(tick) - dom(tick))));
446 /* returns tick of first day of month */
450 return(lowerbound(last_ndays(tick, dom(tick)-1)));
453 /* returns tick of first day of week */
459 if ((d = dow(tick)) == 0)
464 return(lowerbound(last_ndays(tick, d)));
467 /* returns tick of first day of week */
473 if ((d = dow(tick)) == 0)
479 return(upperbound(next_ndays(tick, d)));
481 /* returns number of weeks in month */
485 return (wom(last_dom(tick)));
489 adjust_dst(Tick start, Tick next)
492 change = dst_changed(start, next);
507 next_nhours(Tick t, int n)
511 _Xltimeparams localtime_buf;
513 tm = *_XLocaltime(&t, localtime_buf);
518 next = next + seconds(n, hrsec);
519 next = adjust_dst(t, next);
524 last_ndays(Tick t, int n)
528 _Xltimeparams localtime_buf;
530 tm = *_XLocaltime(&t, localtime_buf);
536 last = last - seconds(n, daysec);
537 last = adjust_dst(t, last);
542 next_ndays(Tick t, int n)
546 _Xltimeparams localtime_buf;
548 tm = *_XLocaltime(&t, localtime_buf);
556 next = timelocal(&tm);
558 next = next + seconds(n, daysec);
559 next = adjust_dst(t, next);
568 next = t +(int)daysec;
569 next = adjust_dst(t, next);
578 prev = t - (int)daysec;
579 prev = adjust_dst(t, prev);
588 next = t + seconds(7, daysec);
589 next = adjust_dst(t, next);
598 prev = t - seconds(7, daysec);
599 prev = adjust_dst(t, prev);
608 next = t + seconds(14, daysec);
609 next = adjust_dst(t, next);
618 prev = t - seconds(14, daysec);
619 prev = adjust_dst(t, prev);
623 /* WORK OUT A BETTER WAY TO DO THIS!! */
625 prevmonth_exactday(Tick t)
630 _Xltimeparams localtime_buf;
632 tm = *_XLocaltime(&t, localtime_buf);
633 sdelta = tm.tm_hour * hrsec + tm.tm_min * minsec + tm.tm_sec;
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);
642 else { /* brute force */
643 prev = previousmonth(previousmonth(t)); /* hop over the month */
644 tm = *_XLocaltime(&prev, localtime_buf);
648 prev =(mktime(&tm)) + sdelta;
650 prev =(timelocal(&tm)) + sdelta;
657 /* WORK OUT A BETTER WAY TO DO THIS!! */
659 nextmonth_exactday(Tick t)
664 _Xltimeparams localtime_buf;
666 tm = *_XLocaltime(&t, localtime_buf);
667 sdelta = tm.tm_hour * hrsec + tm.tm_min * minsec + tm.tm_sec;
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);
676 else { /* brute force */
677 next = next_nmonth(t, 2); /* hop over the month */
678 tm = *_XLocaltime(&next, localtime_buf);
682 next = mktime(&tm) + sdelta;
684 next =(timelocal(&tm)) + sdelta;
691 nextnyear(Tick t, int n)
694 _Xltimeparams localtime_buf;
696 tm = *_XLocaltime(&t, localtime_buf);
701 return(timelocal(&tm));
708 return(nextnyear(t, 1));
712 prevnday_exacttime(Tick t, int n)
716 prev = t - seconds(n, daysec);
717 prev = adjust_dst(t, prev);
722 prevnyear(Tick t, int n)
725 _Xltimeparams localtime_buf;
727 tm = *_XLocaltime(&t, localtime_buf);
732 return(timelocal(&tm));
739 return(prevnyear(t, 1));
743 previousmonth(Tick t)
746 _Xltimeparams localtime_buf;
748 tm = *_XLocaltime(&t, localtime_buf);
765 return(timelocal(&tm));
770 prev_nmonth(Tick t, int n)
774 _Xltimeparams localtime_buf;
779 tm = *_XLocaltime(&t, localtime_buf);
787 if ((tm.tm_mon = tm.tm_mon - n) < 0) {
795 return(timelocal(&tm));
803 _Xltimeparams localtime_buf;
805 tm = *_XLocaltime(&t, localtime_buf);
812 return(timelocal(&tm));
820 _Xltimeparams localtime_buf;
822 tm = *_XLocaltime(&t, localtime_buf);
830 return(timelocal(&tm));
838 _Xltimeparams localtime_buf;
840 tm = *_XLocaltime(&t, localtime_buf);
848 return(timelocal(&tm));
856 _Xltimeparams localtime_buf;
858 tm = *_XLocaltime(&t, localtime_buf);
866 return(timelocal(&tm));
870 lower_bound(int i, Tick t)
873 _Xltimeparams localtime_buf;
875 tm = *_XLocaltime(&t, localtime_buf);
883 return (timelocal(&tm));
890 _Xltimeparams localtime_buf;
892 tm = *_XLocaltime(&t, localtime_buf);
898 return(mktime(&tm)-1);
900 return(timelocal(&tm)-1);
907 return((y-1)/4 -(y-1)/100 +(y-1)/400);
911 xytoclock(int x, int y, Tick t)
913 int dd, mn, yr, ly, leaps;
916 struct tm timestruct;
918 _Xltimeparams localtime_buf;
920 memset(×truct, NULL, sizeof(struct tm));
922 tm = *_XLocaltime(&t, localtime_buf);
924 yr = tm.tm_year + 1900;
929 (yr+leaps+3055L*(mn+2)/100-84-(mn>2)*(2-ly))%7;
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;
937 tick = mktime(×truct);
948 set_timezone(char *tzname)
950 static char tzenv[MAXPATHLEN];
953 /* I don't like using 'system', but this does the right
954 * thing according to tha man pages
956 if (tzname==NULL) system("unset TZ\n");
958 if (tzname==NULL) tzsetwall();
962 sprintf(tzenv, "TZ=%s", tzname);
976 extern long timezone;
980 _Xltimeparams localtime_buf;
983 tm = *_XLocaltime(&t, localtime_buf);
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.
1002 _Xltimeparams localtime_buf;
1003 _Xgtimeparams gmtime_buf;
1005 /* Fix for QAR 31607 */
1007 if (getenv("TZ") == NULL){
1009 tzptr = malloc(strlen(tzname[0]) + strlen(tzname[1]) + 10);
1010 sprintf (tzptr,"TZ=%s%d%s", tzname[0], timezone/3600, tzname[1]);
1016 tm = *_XLocaltime(&t, localtime_buf);
1017 gm = *_XGmtime(&t, gmtime_buf);
1019 bot = mktime(&gm) - mktime(&tm);
1026 tm.tm_year =137; /* Dec. 31, 2037 */
1032 seconds_to_hours(int n)
1034 return(n/(int)hrsec);
1038 hours_to_seconds(int n)
1040 return(n *(int)hrsec);
1044 seconds_to_minutes(int n)
1050 minutes_to_seconds(int n)
1052 return(n *(int)minsec);
1057 days_to_seconds(int n)
1059 return(n *(int)daysec);
1062 seconds_to_days(int n)
1064 return(n/(int)daysec);
1069 weeks_to_seconds(int n)
1071 return(n *(int)wksec);
1075 seconds_to_weeks(int)
1077 return(n/(int)wksec);
1082 monthdayyear(int m, int d, int y)
1087 struct tm timestruct;
1089 memset(×truct, 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;
1096 t = mktime(×truct);
1098 sprintf(buf, "%d/%d/%d", m, d, y);
1099 t = cm_getdate(buf, NULL);
1101 printf("monthdayyear, m= %d, d = %d, y = %d, t1 = %d, t = %d\n", m, d, y, t1, t);