2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afsconfig.h>
11 #include <afs/param.h>
17 #include <sys/types.h>
32 /* maximum values for relative dates */
34 #define MAX_YEAR_VALUE 0
35 #define MAX_MONTH_VALUE 11
36 #define MAX_DAY_VALUE 30
38 /* for parsing relative expiration dates */
39 static struct parseseqS {
42 afs_int32 ps_maxValue;
45 KTIMEDATE_YEAR, 'y', MAX_YEAR_VALUE,}, /* no max. value */
47 KTIMEDATE_MONTH, 'm', MAX_MONTH_VALUE,}, /* months max. 12 */
49 KTIMEDATE_DAY, 'd', MAX_DAY_VALUE,}, /* days max. 31 */
54 /* Encodings to and from relative dates. The caller is responsible for
55 * enforcing appropriate use of these routines
59 /* ktimeRelDate_ToInt32
60 * converts a relative ktime date into an afs_int32.
62 * afs_int32 value of encoded date.
66 ktimeRelDate_ToInt32(struct ktime_date *kdptr)
71 (((kdptr->year * (MAX_MONTH_VALUE + 1)) +
72 kdptr->month) * (MAX_DAY_VALUE + 1)) + kdptr->day;
76 /* Int32To_ktimeRelDate
77 * Convert a relative date encoded in an afs_int32 - back into a ktime_date
82 Int32To_ktimeRelDate(afs_int32 int32Date, struct ktime_date *kdptr)
84 memset(kdptr, 0, sizeof(*kdptr));
86 kdptr->day = int32Date % (MAX_DAY_VALUE + 1);
88 kdptr->mask |= KTIMEDATE_DAY;
90 int32Date = int32Date / (MAX_DAY_VALUE + 1);
92 kdptr->month = int32Date % (MAX_MONTH_VALUE + 1);
93 if (kdptr->month != 0)
94 kdptr->mask |= KTIMEDATE_MONTH;
96 int32Date = int32Date / (MAX_MONTH_VALUE + 1);
98 kdptr->year = int32Date;
100 kdptr->mask |= KTIMEDATE_YEAR;
105 /* ktimeDate_FromInt32
106 * Converts a time in seconds, to a time (in ktime_date format).
107 * Result is a conventional ktime_date structure.
108 * placed in the supplied structure
110 * timeSecs - time in seconds
111 * ktimePtr - ptr to struct for the return value
115 ktimeDate_FromInt32(afs_int32 timeSecs, struct ktime_date *ktimePtr)
117 time_t tt = timeSecs;
124 memset(&timeP, 0, sizeof(timeP));
125 localtime_r(&tt, &timeP);
127 timePtr = localtime(&tt);
130 /* copy the relevant fields */
131 ktimePtr->sec = timePtr->tm_sec;
132 ktimePtr->min = timePtr->tm_min;
133 ktimePtr->hour = timePtr->tm_hour;
134 ktimePtr->day = timePtr->tm_mday;
135 ktimePtr->month = timePtr->tm_mon + 1;
136 ktimePtr->year = timePtr->tm_year;
139 KTIMEDATE_YEAR | KTIMEDATE_MONTH | KTIMEDATE_DAY | KTIMEDATE_HOUR |
140 KTIMEDATE_MIN | KTIMEDATE_SEC;
145 #define RD_DIGIT_LIMIT 4 /* max. no. digits permitted */
148 * Parses a relative date of the form <n>y<n>m<n>d representing years
149 * months and days. <n> is limited to RD_DIGIT_LIMIT digits in length
150 * and is further restricted by the maximums specified at the head
153 * dateStr - ptr to string to parse. Leading white space ingnored.
155 * returns a ptr to a static ktime_date structure containing
156 * appropriately set fields. The mask field is unused.
157 * 0 - error in date specification
161 ParseRelDate(char *dateStr, struct ktime_date * relDatePtr)
163 struct parseseqS *psPtr;
164 afs_int32 value, digit_limit;
165 afs_int32 type_index;
167 memset(relDatePtr, 0, sizeof(*relDatePtr));
172 while (isspace(*dateStr)) /* skip leading whitespace */
175 if (isdigit(*dateStr) == 0)
178 digit_limit = RD_DIGIT_LIMIT;
180 while (isdigit(*dateStr)) {
181 value = value * 10 + *dateStr - '0';
183 if (digit_limit-- == 0)
187 psPtr = &parseseq[type_index];
188 /* determine the units. Search for a matching type character */
189 while ((psPtr->ps_keychar != *dateStr)
190 && (psPtr->ps_keychar != 0)
193 psPtr = &parseseq[type_index];
196 /* no matching type found */
197 if (psPtr->ps_keychar == 0)
200 /* check the bounds on the maximum value. Can't be negative
201 * and if a maximum value is specified, check against it
204 || ((psPtr->ps_maxValue > 0) && (value > psPtr->ps_maxValue))
208 /* save computed value in the relevant type field */
209 switch (psPtr->ps_field) {
211 relDatePtr->year = value;
212 relDatePtr->mask |= KTIMEDATE_YEAR;
215 case KTIMEDATE_MONTH:
216 if (value > MAX_MONTH_VALUE)
218 relDatePtr->month = value;
219 relDatePtr->mask |= KTIMEDATE_MONTH;
223 if (value > MAX_DAY_VALUE)
226 relDatePtr->mask |= KTIMEDATE_DAY;
227 relDatePtr->day = value;
233 dateStr++; /* next digit */
236 /* no more chars to process, return the result */
246 * returns a static string representing the relative date. This is in
247 * a format acceptable to the relative date parser.
249 * datePtr - relative date to be converted.
251 * ptr to static string
255 RelDatetoString(struct ktime_date *datePtr)
257 static char dateString[64];
258 char tempstring[64], *sptr;
261 sptr = &dateString[0];
263 if (datePtr->mask & KTIMEDATE_YEAR) {
264 sprintf(tempstring, "%-dy", datePtr->year);
265 strcat(sptr, tempstring);
268 if (datePtr->mask & KTIMEDATE_MONTH) {
270 sprintf(tempstring, "%-dm", datePtr->month);
271 strcat(sptr, tempstring);
274 if (datePtr->mask & KTIMEDATE_DAY) {
276 sprintf(tempstring, "%-dd", datePtr->day);
277 strcat(sptr, tempstring);
282 /* Add_RelDate_to_Time
283 * Returns current time with a relative time added. Note that the
284 * computation adds in most significant fields first, i.e. year, month
285 * day etc. Addition of least significant fields would produce different
286 * results (depending on the data).
288 * relDatePtr - a ktime_date containing a relative time specification
290 * returns specified time with relative time added.
294 Add_RelDate_to_Time(struct ktime_date * relDatePtr, afs_int32 atime)
297 static struct ktime_date absDate;
299 ktimeDate_FromInt32(atime, &absDate); /* convert to ktime */
302 if (relDatePtr->mask & KTIMEDATE_YEAR)
303 absDate.year += relDatePtr->year;
306 if (relDatePtr->mask & KTIMEDATE_MONTH)
307 absDate.month += relDatePtr->month;
309 if (absDate.month > 12) {
310 moreYears = absDate.month / 12;
311 absDate.month = absDate.month % 12;
312 absDate.year += moreYears;
315 /* day computations depend upon month size, so do these in seconds */
316 atime = ktime_InterpretDate(&absDate);
318 if (relDatePtr->mask & KTIMEDATE_DAY)
319 atime = atime + relDatePtr->day * 24 * 60 * 60;
321 if (relDatePtr->mask & KTIMEDATE_HOUR)
322 atime = atime + relDatePtr->hour * 60 * 60;
324 if (relDatePtr->mask & KTIMEDATE_MIN)
325 atime = atime + relDatePtr->min * 60;
327 if (relDatePtr->mask & KTIMEDATE_SEC)
328 atime = atime + relDatePtr->sec;