|
|
1.1 root 1: #
2: /*
3: * MAKETIME derive 32-bit time value from TM structure.
4: *
5: * Usage:
6: * long t,maketime();
7: * struct tm *tp; Pointer to TM structure from <time.h>
8: * NOTE: this must be extended version!!!
9: * t = maketime(tp);
10: *
11: * Returns:
12: * 0 if failure; parameter out of range or nonsensical.
13: * else long time-value.
14: * Notes:
15: * This code is quasi-public; it may be used freely in like software.
16: * It is not to be sold, nor used in licensed software without
17: * permission of the author.
18: * For everyone's benefit, please report bugs and improvements!
19: * Copyright 1981 by Ken Harrenstien, SRI International.
20: * (ARPANET: KLH @ SRI)
21: */
22: #ifndef lint
23: static char rcsid[]= "$Id: maketime.c,v 1.6 87/12/18 17:05:58 narten Exp $";
24: #endif
25: /* $Log: maketime.c,v $
26: * Revision 1.6 87/12/18 17:05:58 narten
27: * include rcsparam.h
28: *
29: * Revision 1.5 87/12/18 11:35:51 narten
30: * maketime.c: fixed USG code - you have tgo call "tzset" in order to have
31: * "timezone" set. ("localtime" calls it, but it's probably better not to
32: * count on "localtime" having been called.)
33: *
34: * Revision 1.4 87/10/18 10:26:57 narten
35: * Updating version numbers. Changes relative to 1.0 are actually
36: * relative to 1.2
37: *
38: * Revision 1.3 87/09/24 13:58:45 narten
39: * Sources now pass through lint (if you ignore printf/sprintf/fprintf
40: * warnings)
41: *
42: * Revision 1.2 87/03/27 14:21:48 jenkins
43: * Port to suns
44: *
45: * Revision 1.1 84/01/23 14:50:04 kcs
46: * Initial revision
47: *
48: * Revision 1.2 83/12/05 10:12:56 wft
49: * added cond. compilation for USG Unix; long timezone;
50: *
51: * Revision 1.1 82/05/06 11:38:00 wft
52: * Initial revision
53: *
54: */
55:
56:
57: #include "rcsbase.h"
58: #include "time.h"
59:
60: int daytb[] = { /* # days in year thus far, indexed by month (0-12!!) */
61: 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
62: };
63:
64: struct tm *localtime();
65: long time();
66:
67: long maketime(atm)
68: struct tm *atm;
69: { register struct tm *tp;
70: register int i;
71: int year, yday, mon, day, hour, min, sec, zone, dst, leap;
72: long tres, curtim;
73:
74: VOID time(&curtim);
75: tp = localtime(&curtim); /* Get breakdowns of current time */
76: year = tp->tm_year; /* Use to set up defaults */
77: mon = tp->tm_mon;
78: day = tp->tm_mday;
79:
80:
81: #ifdef DEBUG
82: printf("first YMD: %d %d %d, T=%ld\n",year,mon,day,tres);
83: #endif DEBUG
84: tp = atm;
85:
86: /* First must find date, using specified year, month, day.
87: * If one of these is unspecified, it defaults either to the
88: * current date (if no more global spec was given) or to the
89: * zero-value for that spec (i.e. a more global spec was seen).
90: * Start with year... note 32 bits can only handle 135 years.
91: */
92: if(tp->tm_year != TMNULL)
93: { if((year = tp->tm_year) >= 1900) /* Allow full yr # */
94: year -= 1900; /* by making kosher */
95: mon = 0; /* Since year was given, default */
96: day = 1; /* for remaining specs is zero */
97: }
98: if(year < 70 || 70+134 < year ) /* Check range */
99: return(0); /* ERR: year out of range */
100: leap = year&03 ? 0 : 1; /* See if leap year */
101: year -= 70; /* UNIX time starts at 1970 */
102:
103: /*
104: * Find day of year.
105: * YDAY is used only if it exists and either the month or day-of-month
106: * is missing.
107: */
108: if (tp->tm_yday != TMNULL
109: && (tp->tm_mon == TMNULL || tp->tm_mday == TMNULL))
110: yday = tp->tm_yday;
111: else
112: { if(tp->tm_mon != TMNULL)
113: { mon = tp->tm_mon; /* Month was specified */
114: day = 1; /* so set remaining default */
115: }
116: if(mon < 0 || 11 < mon) return(0); /* ERR: bad month */
117: if(tp->tm_mday != TMNULL) day = tp->tm_mday;
118: if(day < 1
119: || (((daytb[mon+1]-daytb[mon]) < day)
120: && (day!=29 || mon!=1 || !leap) ))
121: return(0); /* ERR: bad day */
122: yday = daytb[mon] /* Add # of days in months so far */
123: + ((leap /* Leap year, and past Feb? If */
124: && mon>1)? 1:0) /* so, add leap day for this year */
125: + day-1; /* And finally add # days this mon */
126:
127: if (tp->tm_yday != TMNULL /* Confirm that YDAY correct */
128: && tp->tm_yday != yday) return(0); /* ERR: conflict */
129: }
130: if(yday < 0 || (leap?366:365) <= yday)
131: return(0); /* ERR: bad YDAY or maketime bug */
132:
133: tres = year*365 /* Get # days of years so far */
134: + ((year+1)>>2) /* plus # of leap days since 1970 */
135: + yday; /* and finally add # days this year */
136:
137: if((i = tp->tm_wday) != TMNULL) /* Check WDAY if present */
138: if(i < 0 || 6 < i /* Ensure within range */
139: || i != (tres+4)%7) /* Matches? Jan 1,1970 was Thu = 4 */
140: return(0); /* ERR: bad WDAY */
141:
142: #ifdef DEBUG
143: printf("YMD: %d %d %d, T=%ld\n",year,mon,day,tres);
144: #endif DEBUG
145: /*
146: * Now determine time. If not given, default to zeros
147: * (since time is always the least global spec)
148: */
149: tres *= 86400L; /* Get # seconds (24*60*60) */
150: hour = min = sec = 0;
151: if(tp->tm_hour != TMNULL) hour = tp->tm_hour;
152: if(tp->tm_min != TMNULL) min = tp->tm_min;
153: if(tp->tm_sec != TMNULL) sec = tp->tm_sec;
154: if( min < 0 || 60 <= min
155: || sec < 0 || 60 <= sec) return(0); /* ERR: MS out of range */
156: if(hour < 0 || 24 <= hour)
157: if(hour != 24 || (min+sec) !=0) /* Allow 24:00 */
158: return(0); /* ERR: H out of range */
159:
160: /* confirm AM/PM if there */
161: switch(tp->tm_ampm)
162: { case 0: case TMNULL: /* Ignore these values */
163: break;
164: case 1: /* AM */
165: case 2: /* PM */
166: if(hour > 12) return(0); /* ERR: hrs 13-23 bad */
167: if(hour ==12) hour = 0; /* Modulo 12 */
168: if(tp->tm_ampm == 2) /* If PM, then */
169: hour += 12; /* get 24-hour time */
170: break;
171: default: return(0); /* ERR: illegal TM_AMPM value */
172: }
173:
174: tres += sec + 60L*(min + 60L*hour); /* Add in # secs of time */
175:
176: #ifdef DEBUG
177: printf("HMS: %d %d %d T=%ld\n",hour,min,sec,tres);
178: #endif DEBUG
179: /*
180: * We now have the GMT date/time and must make final
181: * adjustment for the specified time zone. If none is specified,
182: * the local time-zone is assumed.
183: */
184: if((zone = tp->tm_zon) == TMNULL /* If unspecified */
185: || (zone == 1)) /* or local-zone requested */
186: zone = localzone(); /* then set to local zone */
187: if(zone < 0 || 24*60 <= zone)
188: return(0); /* ERR: zone out of range */
189:
190: /* See if must apply Daylight Saving Time shift.
191: * Note that if DST is specified, validity is not checked.
192: */
193: if((dst = tp->tm_isdst) == TMNULL) /* Must we figure it out? */
194: { curtim = tres +localzone()*60L; /* Yuck. Get equiv local */
195: dst = localtime(&curtim)->tm_isdst; /* time, and ask. */
196: }
197: tres += zone*60L -(dst?3600:0); /* Add in # seconds of zone adj */
198:
199: return(tres);
200: }
201:
202:
203: /* LOCALZONE return local timezone in # mins west of GMT
204: *
205: */
206:
207: #ifdef V6
208: extern long timezone;
209: #else
210: #ifdef USG
211: extern long timezone;
212: #else /* V7 */
213: #include <sys/types.h>
214: #include <sys/timeb.h>
215: #endif USG
216: #endif V6
217:
218: int _lclzon = -1;
219: localzone()
220: {
221: #ifdef V6
222: return(_lclzon >= 0 ? _lclzon : (_lclzon = timezone/60L));
223: #else
224: #ifdef USG
225: tzset();
226: return(_lclzon >= 0 ? _lclzon : (_lclzon = timezone/60L));
227: #else /* V7 */
228: struct timeb tb;
229:
230: if(_lclzon < 0)
231: { ftime(&tb);
232: _lclzon = tb.timezone;
233: }
234: return(_lclzon);
235:
236: #endif USG
237: #endif V6
238: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.