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
64 #include <X11/Xos_r.h>
69 #include <sys/param.h>
78 typedef enum {dstoff, dston, nochange} DSTchange;
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
88 char *months2[] = {"",
89 (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL,
90 (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL,
91 (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL
101 int monthsecs[12] = {
102 31*daysec, 28*daysec, 31*daysec,
103 30*daysec, 31*daysec, 30*daysec,
104 31*daysec, 31*daysec, 30*daysec,
105 31*daysec, 30*daysec, 31*daysec
108 char *days[8] = {(char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL};
110 char *days2[8] = {(char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL};
112 char *days3[8] = {(char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL};
114 char *days4[8] = {(char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL};
116 char *numbers[32] = {"",
117 " 1 ", " 2 ", " 3 ", " 4 ", " 5 ", " 6 ", " 7 ",
118 " 8 ", " 9 ", "10", "11", "12", "13", "14",
119 "15", "16", "17", "18", "19", "20", "21",
120 "22", "23", "24", "25", "26", "27", "28",
125 "12", " 1", " 2", " 3", " 4", " 5", " 6", " 7", " 8", " 9", "10", "11",
126 "12", " 1", " 2", " 3", " 4", " 5", " 6", " 7", " 8", " 9", "10", "11"
130 * Given a weekmask and the first day of the week, calculate
131 * the number of times outstanding in the week.
134 ntimes_this_week(u_int weekmask, int firstday)
136 int i, ntimes, weekdaymask = 1 << firstday;
141 for (i=firstday, ntimes=0; i < 7; i++, weekdaymask <<= 1) {
142 if (weekdaymask & weekmask)
148 /* Return beginning of time */
155 /* Return end of time */
162 /* Given a weekmask, find the last appointment in the week */
164 lastapptofweek(u_int mask)
171 for (n = -1; mask != 0; n++, mask = mask >> 1);
176 /* Remove after v3 release */
180 boolean_t magic=B_FALSE;
182 _Xltimeparams localtime_buf;
184 tm = _XLocaltime(&t, localtime_buf);
186 if (tm->tm_hour == 3 && tm->tm_min == 41)
190 /* for 12 hour clock, if 24 subtract 12 */
194 boolean_t am = B_TRUE;
198 else if (*hr >= 12) {
210 int r =((t >= bot) &&(t <= eot));
215 dst_changed(Tick old, Tick new)
219 _Xltimeparams localtime_buf;
221 oldtm = *_XLocaltime(&old, localtime_buf);
222 newtm = *_XLocaltime(&new, localtime_buf);
224 if(oldtm.tm_isdst == newtm.tm_isdst) return(nochange);
225 switch(oldtm.tm_isdst) {
236 seconds(int n, Unit unit)
238 return(n *(int)unit);
242 seconds_dble(double n, Unit unit)
244 return((double)(n * (int)unit));
251 _Xltimeparams localtime_buf;
253 tm = _XLocaltime(&t, localtime_buf);
254 return(tm->tm_year + 1900);
262 _Xltimeparams localtime_buf;
264 tm = _XLocaltime(&t, localtime_buf);
265 return(tm->tm_mon+1);
272 _Xltimeparams localtime_buf;
274 tm = _XLocaltime(&t, localtime_buf);
282 _Xltimeparams localtime_buf;
284 tm = _XLocaltime(&t, localtime_buf);
292 (y % 4 == 0 && y % 100 !=0 || y % 400 == 0);
300 _Xltimeparams localtime_buf;
302 tm = *_XLocaltime(&t, localtime_buf);
304 return(((mon==1) && leapyr(tm.tm_year+1900))? 29 : monthdays[mon]);
312 _Xltimeparams localtime_buf;
314 tm = *_XLocaltime(&t, localtime_buf);
316 return(((mon==1) && leapyr(tm.tm_year+1900))? 29*daysec : monthsecs[mon]);
323 _Xltimeparams localtime_buf;
325 tm = _XLocaltime(&t, localtime_buf);
333 _Xltimeparams localtime_buf;
335 tm = _XLocaltime(&t, localtime_buf);
336 return((12 + tm->tm_mday - tm->tm_wday)/7);
340 * If the result falls beyond the system limit, -1 is returned by mktime().
343 next_nmonth(Tick t, int n)
347 _Xltimeparams localtime_buf;
352 tm = *_XLocaltime(&t, localtime_buf);
360 if ((tm.tm_mon = tm.tm_mon + n) > 11) {
372 return(next_nmonth(t, 1));
376 weekofmonth(Tick t, int *wk)
378 struct tm tm, tm1, tm2;
380 _Xltimeparams localtime_buf;
382 tm = *_XLocaltime(&t, localtime_buf);
387 firstday = mktime(&tm);
388 tm = *_XLocaltime(&firstday, localtime_buf);
390 /* need to get it again since data in tm is changed */
391 tm1 = *_XLocaltime(&t, localtime_buf);
394 if (tm1.tm_wday < tm.tm_wday)
400 t += seconds(7, daysec);
401 tm2 = *_XLocaltime(&t, localtime_buf);
403 return((tm1.tm_mon == tm2.tm_mon) ? B_FALSE : B_TRUE);
411 _Xltimeparams localtime_buf;
413 tm = *_XLocaltime(&t, localtime_buf);
417 extern int /* find dow(0-6) that 1st dom falls on */
421 _Xltimeparams localtime_buf;
423 tm = *_XLocaltime(&t, localtime_buf);
427 tm = *_XLocaltime(&t, localtime_buf);
432 ldom(Tick t /* find dow(0-6) that last dom falls on */ )
435 _Xltimeparams localtime_buf;
437 tm = *_XLocaltime(&t, localtime_buf);
438 tm.tm_mday = monthlength(t);
441 tm = *_XLocaltime(&t, localtime_buf);
445 /* returns tick of last day of month */
449 return(upperbound(next_ndays(tick, monthlength(tick) - dom(tick))));
452 /* returns tick of first day of month */
456 return(lowerbound(last_ndays(tick, dom(tick)-1)));
459 /* returns tick of first day of week */
465 if ((d = dow(tick)) == 0)
470 return(lowerbound(last_ndays(tick, d)));
473 /* returns tick of first day of week */
479 if ((d = dow(tick)) == 0)
485 return(upperbound(next_ndays(tick, d)));
487 /* returns number of weeks in month */
491 return (wom(last_dom(tick)));
495 adjust_dst(Tick start, Tick next)
498 change = dst_changed(start, next);
513 next_nhours(Tick t, int n)
517 _Xltimeparams localtime_buf;
519 tm = *_XLocaltime(&t, localtime_buf);
524 next = next + seconds(n, hrsec);
525 next = adjust_dst(t, next);
530 last_ndays(Tick t, int n)
534 _Xltimeparams localtime_buf;
536 tm = *_XLocaltime(&t, localtime_buf);
542 last = last - seconds(n, daysec);
543 last = adjust_dst(t, last);
548 next_ndays(Tick t, int n)
552 _Xltimeparams localtime_buf;
554 tm = *_XLocaltime(&t, localtime_buf);
562 next = timelocal(&tm);
564 next = next + seconds(n, daysec);
565 next = adjust_dst(t, next);
574 next = t +(int)daysec;
575 next = adjust_dst(t, next);
584 prev = t - (int)daysec;
585 prev = adjust_dst(t, prev);
594 next = t + seconds(7, daysec);
595 next = adjust_dst(t, next);
604 prev = t - seconds(7, daysec);
605 prev = adjust_dst(t, prev);
614 next = t + seconds(14, daysec);
615 next = adjust_dst(t, next);
624 prev = t - seconds(14, daysec);
625 prev = adjust_dst(t, prev);
629 /* WORK OUT A BETTER WAY TO DO THIS!! */
631 prevmonth_exactday(Tick t)
636 _Xltimeparams localtime_buf;
638 tm = *_XLocaltime(&t, localtime_buf);
639 sdelta = tm.tm_hour * hrsec + tm.tm_min * minsec + tm.tm_sec;
641 if((tm.tm_mday < 31 && tm.tm_mon != 0) || /* at least 30 days everywhere, except Feb.*/
642 (tm.tm_mday==31 && tm.tm_mon==6) || /* two 31s -- Jul./Aug. */
643 (tm.tm_mday==31 && tm.tm_mon==11) || /* two 31s -- Dec./Jan. */
644 (tm.tm_mon == 0 &&(tm.tm_mday < 29 ||(tm.tm_mday==29 && leapyr(tm.tm_year+1900))))) {
645 prev = t-monthseconds(previousmonth(t));
646 prev = adjust_dst(t, prev);
648 else { /* brute force */
649 prev = previousmonth(previousmonth(t)); /* hop over the month */
650 tm = *_XLocaltime(&prev, localtime_buf);
654 prev =(mktime(&tm)) + sdelta;
656 prev =(timelocal(&tm)) + sdelta;
663 /* WORK OUT A BETTER WAY TO DO THIS!! */
665 nextmonth_exactday(Tick t)
670 _Xltimeparams localtime_buf;
672 tm = *_XLocaltime(&t, localtime_buf);
673 sdelta = tm.tm_hour * hrsec + tm.tm_min * minsec + tm.tm_sec;
675 if((tm.tm_mday < 31 && tm.tm_mon != 0) || /* at least 30 days everywhere, except Feb.*/
676 (tm.tm_mday==31 && tm.tm_mon==6) || /* two 31s -- Jul./Aug. */
677 (tm.tm_mday==31 && tm.tm_mon==11) || /* two 31s -- Dec./Jan. */
678 (tm.tm_mon == 0 &&(tm.tm_mday < 29 ||(tm.tm_mday==29 && leapyr(tm.tm_year+1900))))) {
679 next = t+monthseconds(t);
680 next = adjust_dst(t, next);
682 else { /* brute force */
683 next = next_nmonth(t, 2); /* hop over the month */
684 tm = *_XLocaltime(&next, localtime_buf);
688 next = mktime(&tm) + sdelta;
690 next =(timelocal(&tm)) + sdelta;
697 nextnyear(Tick t, int n)
700 _Xltimeparams localtime_buf;
702 tm = *_XLocaltime(&t, localtime_buf);
707 return(timelocal(&tm));
714 return(nextnyear(t, 1));
718 prevnday_exacttime(Tick t, int n)
722 prev = t - seconds(n, daysec);
723 prev = adjust_dst(t, prev);
728 prevnyear(Tick t, int n)
731 _Xltimeparams localtime_buf;
733 tm = *_XLocaltime(&t, localtime_buf);
738 return(timelocal(&tm));
745 return(prevnyear(t, 1));
749 previousmonth(Tick t)
752 _Xltimeparams localtime_buf;
754 tm = *_XLocaltime(&t, localtime_buf);
771 return(timelocal(&tm));
776 prev_nmonth(Tick t, int n)
780 _Xltimeparams localtime_buf;
785 tm = *_XLocaltime(&t, localtime_buf);
793 if ((tm.tm_mon = tm.tm_mon - n) < 0) {
801 return(timelocal(&tm));
809 _Xltimeparams localtime_buf;
811 tm = *_XLocaltime(&t, localtime_buf);
818 return(timelocal(&tm));
826 _Xltimeparams localtime_buf;
828 tm = *_XLocaltime(&t, localtime_buf);
836 return(timelocal(&tm));
844 _Xltimeparams localtime_buf;
846 tm = *_XLocaltime(&t, localtime_buf);
854 return(timelocal(&tm));
862 _Xltimeparams localtime_buf;
864 tm = *_XLocaltime(&t, localtime_buf);
872 return(timelocal(&tm));
876 lower_bound(int i, Tick t)
879 _Xltimeparams localtime_buf;
881 tm = *_XLocaltime(&t, localtime_buf);
889 return (timelocal(&tm));
896 _Xltimeparams localtime_buf;
898 tm = *_XLocaltime(&t, localtime_buf);
904 return(mktime(&tm)-1);
906 return(timelocal(&tm)-1);
913 return((y-1)/4 -(y-1)/100 +(y-1)/400);
917 xytoclock(int x, int y, Tick t)
919 int dd, mn, yr, ly, leaps;
922 struct tm timestruct;
924 _Xltimeparams localtime_buf;
926 memset(×truct, NULL, sizeof(struct tm));
928 tm = *_XLocaltime(&t, localtime_buf);
930 yr = tm.tm_year + 1900;
935 (yr+leaps+3055L*(mn+2)/100-84-(mn>2)*(2-ly))%7;
937 timestruct.tm_mon = tm.tm_mon;
938 timestruct.tm_mday = dd;
939 timestruct.tm_year = tm.tm_year;
940 timestruct.tm_sec = 0;
941 timestruct.tm_isdst = -1;
943 tick = mktime(×truct);
954 set_timezone(char *tzname)
956 static char tzenv[MAXPATHLEN];
959 /* I don't like using 'system', but this does the right
960 * thing according to tha man pages
962 if (tzname==NULL) system("unset TZ\n");
964 if (tzname==NULL) tzsetwall();
968 sprintf(tzenv, "TZ=%s", tzname);
982 extern long timezone;
986 _Xltimeparams localtime_buf;
989 tm = *_XLocaltime(&t, localtime_buf);
997 * cm now supports to up end of 1999. This is due to the limitation
998 * of cm_getdate() which can only handle up to end of 1999.
999 * When cm_getdate() is improved to handle up to the system limit,
1000 * definitions of eot and EOT need to be changed as well as some
1001 * of the routines in this file and the caller of these routines.
1008 _Xltimeparams localtime_buf;
1009 _Xgtimeparams gmtime_buf;
1011 /* Fix for QAR 31607 */
1013 if (getenv("TZ") == NULL){
1015 tzptr = malloc(strlen(tzname[0]) + strlen(tzname[1]) + 10);
1016 sprintf (tzptr,"TZ=%s%d%s", tzname[0], timezone/3600, tzname[1]);
1022 tm = *_XLocaltime(&t, localtime_buf);
1023 gm = *_XGmtime(&t, gmtime_buf);
1025 bot = mktime(&gm) - mktime(&tm);
1032 tm.tm_year =137; /* Dec. 31, 2037 */
1038 seconds_to_hours(int n)
1040 return(n/(int)hrsec);
1044 hours_to_seconds(int n)
1046 return(n *(int)hrsec);
1050 seconds_to_minutes(int n)
1056 minutes_to_seconds(int n)
1058 return(n *(int)minsec);
1063 days_to_seconds(int n)
1065 return(n *(int)daysec);
1068 seconds_to_days(int n)
1070 return(n/(int)daysec);
1075 weeks_to_seconds(int n)
1077 return(n *(int)wksec);
1081 seconds_to_weeks(int)
1083 return(n/(int)wksec);
1088 monthdayyear(int m, int d, int y)
1093 struct tm timestruct;
1095 memset(×truct, NULL, sizeof(struct tm));
1096 timestruct.tm_mon = m - 1;
1097 timestruct.tm_mday = d;
1098 timestruct.tm_year = y - 1900;
1099 timestruct.tm_sec = 0;
1100 timestruct.tm_isdst = -1;
1102 t = mktime(×truct);
1104 sprintf(buf, "%d/%d/%d", m, d, y);
1105 t = cm_getdate(buf, NULL);
1107 printf("monthdayyear, m= %d, d = %d, y = %d, t1 = %d, t = %d\n", m, d, y, t1, t);