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 libraries 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 #if defined(__linux__)
64 #include <X11/Xos_r.h>
65 #if defined(__linux__)
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);
261 _Xltimeparams localtime_buf;
263 tm = _XLocaltime(&t, localtime_buf);
264 return(tm->tm_mon+1);
271 _Xltimeparams localtime_buf;
273 tm = _XLocaltime(&t, localtime_buf);
281 _Xltimeparams localtime_buf;
283 tm = _XLocaltime(&t, localtime_buf);
291 (y % 4 == 0 && y % 100 !=0 || y % 400 == 0);
299 _Xltimeparams localtime_buf;
301 tm = *_XLocaltime(&t, localtime_buf);
303 return(((mon==1) && leapyr(tm.tm_year+1900))? 29 : monthdays[mon]);
311 _Xltimeparams localtime_buf;
313 tm = *_XLocaltime(&t, localtime_buf);
315 return(((mon==1) && leapyr(tm.tm_year+1900))? 29*daysec : monthsecs[mon]);
322 _Xltimeparams localtime_buf;
324 tm = _XLocaltime(&t, localtime_buf);
332 _Xltimeparams localtime_buf;
334 tm = _XLocaltime(&t, localtime_buf);
335 return((12 + tm->tm_mday - tm->tm_wday)/7);
339 * If the result falls beyond the system limit, -1 is returned by mktime().
342 next_nmonth(Tick t, int n)
346 _Xltimeparams localtime_buf;
351 tm = *_XLocaltime(&t, localtime_buf);
359 if ((tm.tm_mon = tm.tm_mon + n) > 11) {
371 return(next_nmonth(t, 1));
375 weekofmonth(Tick t, int *wk)
377 struct tm tm, tm1, tm2;
379 _Xltimeparams localtime_buf;
381 tm = *_XLocaltime(&t, localtime_buf);
386 firstday = mktime(&tm);
387 tm = *_XLocaltime(&firstday, localtime_buf);
389 /* need to get it again since data in tm is changed */
390 tm1 = *_XLocaltime(&t, localtime_buf);
393 if (tm1.tm_wday < tm.tm_wday)
399 t += seconds(7, daysec);
400 tm2 = *_XLocaltime(&t, localtime_buf);
402 return((tm1.tm_mon == tm2.tm_mon) ? B_FALSE : B_TRUE);
410 _Xltimeparams localtime_buf;
412 tm = *_XLocaltime(&t, localtime_buf);
416 int /* find dow(0-6) that 1st dom falls on */
420 _Xltimeparams localtime_buf;
422 tm = *_XLocaltime(&t, localtime_buf);
426 tm = *_XLocaltime(&t, localtime_buf);
431 ldom(Tick t /* find dow(0-6) that last dom falls on */ )
434 _Xltimeparams localtime_buf;
436 tm = *_XLocaltime(&t, localtime_buf);
437 tm.tm_mday = monthlength(t);
440 tm = *_XLocaltime(&t, localtime_buf);
444 /* returns tick of last day of month */
448 return(upperbound(next_ndays(tick, monthlength(tick) - dom(tick))));
451 /* returns tick of first day of month */
455 return(lowerbound(last_ndays(tick, dom(tick)-1)));
458 /* returns tick of first day of week */
464 if ((d = dow(tick)) == 0)
469 return(lowerbound(last_ndays(tick, d)));
472 /* returns tick of first day of week */
478 if ((d = dow(tick)) == 0)
484 return(upperbound(next_ndays(tick, d)));
486 /* returns number of weeks in month */
490 return (wom(last_dom(tick)));
494 adjust_dst(Tick start, Tick next)
497 change = dst_changed(start, next);
512 next_nhours(Tick t, int n)
516 _Xltimeparams localtime_buf;
518 tm = *_XLocaltime(&t, localtime_buf);
523 next = next + seconds(n, hrsec);
524 next = adjust_dst(t, next);
529 last_ndays(Tick t, int n)
533 _Xltimeparams localtime_buf;
535 tm = *_XLocaltime(&t, localtime_buf);
541 last = last - seconds(n, daysec);
542 last = adjust_dst(t, last);
547 next_ndays(Tick t, int n)
551 _Xltimeparams localtime_buf;
553 tm = *_XLocaltime(&t, localtime_buf);
561 next = timelocal(&tm);
563 next = next + seconds(n, daysec);
564 next = adjust_dst(t, next);
573 next = t +(int)daysec;
574 next = adjust_dst(t, next);
583 prev = t - (int)daysec;
584 prev = adjust_dst(t, prev);
593 next = t + seconds(7, daysec);
594 next = adjust_dst(t, next);
603 prev = t - seconds(7, daysec);
604 prev = adjust_dst(t, prev);
613 next = t + seconds(14, daysec);
614 next = adjust_dst(t, next);
623 prev = t - seconds(14, daysec);
624 prev = adjust_dst(t, prev);
628 /* WORK OUT A BETTER WAY TO DO THIS!! */
630 prevmonth_exactday(Tick t)
635 _Xltimeparams localtime_buf;
637 tm = *_XLocaltime(&t, localtime_buf);
638 sdelta = tm.tm_hour * hrsec + tm.tm_min * minsec + tm.tm_sec;
640 if((tm.tm_mday < 31 && tm.tm_mon != 0) || /* at least 30 days everywhere, except Feb.*/
641 (tm.tm_mday==31 && tm.tm_mon==6) || /* two 31s -- Jul./Aug. */
642 (tm.tm_mday==31 && tm.tm_mon==11) || /* two 31s -- Dec./Jan. */
643 (tm.tm_mon == 0 &&(tm.tm_mday < 29 ||(tm.tm_mday==29 && leapyr(tm.tm_year+1900))))) {
644 prev = t-monthseconds(previousmonth(t));
645 prev = adjust_dst(t, prev);
647 else { /* brute force */
648 prev = previousmonth(previousmonth(t)); /* hop over the month */
649 tm = *_XLocaltime(&prev, localtime_buf);
653 prev =(mktime(&tm)) + sdelta;
655 prev =(timelocal(&tm)) + sdelta;
662 /* WORK OUT A BETTER WAY TO DO THIS!! */
664 nextmonth_exactday(Tick t)
669 _Xltimeparams localtime_buf;
671 tm = *_XLocaltime(&t, localtime_buf);
672 sdelta = tm.tm_hour * hrsec + tm.tm_min * minsec + tm.tm_sec;
674 if((tm.tm_mday < 31 && tm.tm_mon != 0) || /* at least 30 days everywhere, except Feb.*/
675 (tm.tm_mday==31 && tm.tm_mon==6) || /* two 31s -- Jul./Aug. */
676 (tm.tm_mday==31 && tm.tm_mon==11) || /* two 31s -- Dec./Jan. */
677 (tm.tm_mon == 0 &&(tm.tm_mday < 29 ||(tm.tm_mday==29 && leapyr(tm.tm_year+1900))))) {
678 next = t+monthseconds(t);
679 next = adjust_dst(t, next);
681 else { /* brute force */
682 next = next_nmonth(t, 2); /* hop over the month */
683 tm = *_XLocaltime(&next, localtime_buf);
687 next = mktime(&tm) + sdelta;
689 next =(timelocal(&tm)) + sdelta;
696 nextnyear(Tick t, int n)
699 _Xltimeparams localtime_buf;
701 tm = *_XLocaltime(&t, localtime_buf);
706 return(timelocal(&tm));
713 return(nextnyear(t, 1));
717 prevnday_exacttime(Tick t, int n)
721 prev = t - seconds(n, daysec);
722 prev = adjust_dst(t, prev);
727 prevnyear(Tick t, int n)
730 _Xltimeparams localtime_buf;
732 tm = *_XLocaltime(&t, localtime_buf);
737 return(timelocal(&tm));
744 return(prevnyear(t, 1));
748 previousmonth(Tick t)
751 _Xltimeparams localtime_buf;
753 tm = *_XLocaltime(&t, localtime_buf);
770 return(timelocal(&tm));
775 prev_nmonth(Tick t, int n)
779 _Xltimeparams localtime_buf;
784 tm = *_XLocaltime(&t, localtime_buf);
792 if ((tm.tm_mon = tm.tm_mon - n) < 0) {
800 return(timelocal(&tm));
808 _Xltimeparams localtime_buf;
810 tm = *_XLocaltime(&t, localtime_buf);
817 return(timelocal(&tm));
825 _Xltimeparams localtime_buf;
827 tm = *_XLocaltime(&t, localtime_buf);
835 return(timelocal(&tm));
843 _Xltimeparams localtime_buf;
845 tm = *_XLocaltime(&t, localtime_buf);
853 return(timelocal(&tm));
861 _Xltimeparams localtime_buf;
863 tm = *_XLocaltime(&t, localtime_buf);
871 return(timelocal(&tm));
875 lower_bound(int i, Tick t)
878 _Xltimeparams localtime_buf;
880 tm = *_XLocaltime(&t, localtime_buf);
888 return (timelocal(&tm));
895 _Xltimeparams localtime_buf;
897 tm = *_XLocaltime(&t, localtime_buf);
903 return(mktime(&tm)-1);
905 return(timelocal(&tm)-1);
912 return((y-1)/4 -(y-1)/100 +(y-1)/400);
916 xytoclock(int x, int y, Tick t)
918 int dd, mn, yr, ly, leaps;
921 struct tm timestruct;
923 _Xltimeparams localtime_buf;
925 memset(×truct, 0, sizeof(struct tm));
927 tm = *_XLocaltime(&t, localtime_buf);
929 yr = tm.tm_year + 1900;
934 (yr+leaps+3055L*(mn+2)/100-84-(mn>2)*(2-ly))%7;
936 timestruct.tm_mon = tm.tm_mon;
937 timestruct.tm_mday = dd;
938 timestruct.tm_year = tm.tm_year;
939 timestruct.tm_sec = 0;
940 timestruct.tm_isdst = -1;
942 tick = mktime(×truct);
953 set_timezone(char *tzname)
955 static char tzenv[MAXPATHLEN];
958 /* I don't like using 'system', but this does the right
959 * thing according to tha man pages
961 if (tzname==NULL) system("unset TZ\n");
963 if (tzname==NULL) tzsetwall();
967 sprintf(tzenv, "TZ=%s", tzname);
981 extern long timezone;
985 _Xltimeparams localtime_buf;
988 tm = *_XLocaltime(&t, localtime_buf);
996 * cm now supports to up end of 1999. This is due to the limitation
997 * of cm_getdate() which can only handle up to end of 1999.
998 * When cm_getdate() is improved to handle up to the system limit,
999 * definitions of eot and EOT need to be changed as well as some
1000 * of the routines in this file and the caller of these routines.
1007 _Xltimeparams localtime_buf;
1008 _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%ld%s", tzname[0], timezone/3600, tzname[1]);
1023 tm = *_XLocaltime(&t, localtime_buf);
1024 gm = *_XGmtime(&t, gmtime_buf);
1026 bot = mktime(&gm) - mktime(&tm);
1033 tm.tm_year =137; /* Dec. 31, 2037 */
1039 seconds_to_hours(int n)
1041 return(n/(int)hrsec);
1045 hours_to_seconds(int n)
1047 return(n *(int)hrsec);
1051 seconds_to_minutes(int n)
1057 minutes_to_seconds(int n)
1059 return(n *(int)minsec);
1064 days_to_seconds(int n)
1066 return(n *(int)daysec);
1069 int seconds_to_days(int n)
1071 return(n/(int)daysec);
1076 weeks_to_seconds(int n)
1078 return(n *(int)wksec);
1082 seconds_to_weeks(int)
1084 return(n/(int)wksec);
1089 monthdayyear(int m, int d, int y)
1094 struct tm timestruct;
1096 memset(×truct, 0, sizeof(struct tm));
1097 timestruct.tm_mon = m - 1;
1098 timestruct.tm_mday = d;
1099 timestruct.tm_year = y - 1900;
1100 timestruct.tm_sec = 0;
1101 timestruct.tm_isdst = -1;
1103 t = mktime(×truct);
1105 sprintf(buf, "%d/%d/%d", m, d, y);
1106 t = cm_getdate(buf, NULL);
1108 printf("monthdayyear, m= %d, d = %d, y = %d, t1 = %d, t = %d\n", m, d, y, t1, t);