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>
16 #include <sys/types.h>
21 #if defined(AFS_SUN5_ENV) || defined(AFS_NT40_ENV)
29 /* maximum values for relative dates */
31 #define MAX_YEAR_VALUE 0
32 #define MAX_MONTH_VALUE 11
33 #define MAX_DAY_VALUE 30
35 /* for parsing relative expiration dates */
36 static struct parseseqS
40 afs_int32 ps_maxValue;
42 KTIMEDATE_YEAR, 'y', MAX_YEAR_VALUE, /* no max. value */
43 KTIMEDATE_MONTH, 'm', MAX_MONTH_VALUE, /* months max. 12 */
44 KTIMEDATE_DAY, 'd', MAX_DAY_VALUE, /* days max. 31 */
48 /* Encodings to and from relative dates. The caller is responsible for
49 * enforcing appropriate use of these routines
53 /* ktimeRelDate_ToInt32
54 * converts a relative ktime date into an afs_int32.
56 * afs_int32 value of encoded date.
60 ktimeRelDate_ToInt32(kdptr)
61 struct ktime_date *kdptr;
65 retval = (((kdptr->year*(MAX_MONTH_VALUE+1)) +
66 kdptr->month)*(MAX_DAY_VALUE+1)) + kdptr->day;
70 /* Int32To_ktimeRelDate
71 * Convert a relative date encoded in an afs_int32 - back into a ktime_date
75 Int32To_ktimeRelDate(int32Date, kdptr)
77 struct ktime_date *kdptr;
79 memset(kdptr, 0, sizeof(*kdptr));
81 kdptr->day = int32Date % (MAX_DAY_VALUE + 1);
82 if ( kdptr->day != 0 )
83 kdptr->mask |= KTIMEDATE_DAY;
85 int32Date = int32Date/(MAX_DAY_VALUE + 1);
87 kdptr->month = int32Date % (MAX_MONTH_VALUE + 1);
88 if ( kdptr->month != 0 )
89 kdptr->mask |= KTIMEDATE_MONTH;
91 int32Date = int32Date/(MAX_MONTH_VALUE + 1);
93 kdptr->year = int32Date;
94 if ( kdptr->year != 0 )
95 kdptr->mask |= KTIMEDATE_YEAR;
100 /* ktimeDate_FromInt32
101 * Converts a time in seconds, to a time (in ktime_date format).
102 * Result is a conventional ktime_date structure.
103 * placed in the supplied structure
105 * timeSecs - time in seconds
106 * ktimePtr - ptr to struct for the return value
109 ktimeDate_FromInt32(timeSecs, ktimePtr)
111 struct ktime_date *ktimePtr;
115 timePtr = localtime((time_t *)&timeSecs);
117 /* copy the relevant fields */
118 ktimePtr->sec = timePtr->tm_sec;
119 ktimePtr->min = timePtr->tm_min;
120 ktimePtr->hour = timePtr->tm_hour;
121 ktimePtr->day = timePtr->tm_mday;
122 ktimePtr->month = timePtr->tm_mon+1;
123 ktimePtr->year = timePtr->tm_year;
125 ktimePtr->mask = KTIMEDATE_YEAR | KTIMEDATE_MONTH | KTIMEDATE_DAY |
126 KTIMEDATE_HOUR | KTIMEDATE_MIN | KTIMEDATE_SEC;
131 #define RD_DIGIT_LIMIT 4 /* max. no. digits permitted */
134 * Parses a relative date of the form <n>y<n>m<n>d representing years
135 * months and days. <n> is limited to RD_DIGIT_LIMIT digits in length
136 * and is further restricted by the maximums specified at the head
139 * dateStr - ptr to string to parse. Leading white space ingnored.
141 * returns a ptr to a static ktime_date structure containing
142 * appropriately set fields. The mask field is unused.
143 * 0 - error in date specification
147 ParseRelDate(dateStr, relDatePtr)
149 struct ktime_date *relDatePtr;
151 struct parseseqS *psPtr;
152 afs_int32 value, digit_limit;
153 afs_int32 type_index;
155 memset(relDatePtr, 0, sizeof(*relDatePtr));
161 while ( isspace(*dateStr) ) /* skip leading whitespace */
164 if ( isdigit(*dateStr) == 0 )
167 digit_limit = RD_DIGIT_LIMIT;
169 while ( isdigit(*dateStr) )
171 value = value*10 + *dateStr - '0';
173 if ( digit_limit-- == 0 )
177 psPtr = &parseseq[type_index];
178 /* determine the units. Search for a matching type character */
179 while ( (psPtr->ps_keychar != *dateStr)
180 && (psPtr->ps_keychar != 0)
184 psPtr = &parseseq[type_index];
187 /* no matching type found */
188 if ( psPtr->ps_keychar == 0 )
191 /* check the bounds on the maximum value. Can't be negative
192 * and if a maximum value is specified, check against it
195 || ((psPtr->ps_maxValue > 0) && (value > psPtr->ps_maxValue))
199 /* save computed value in the relevant type field */
200 switch ( psPtr->ps_field )
203 relDatePtr->year = value;
204 relDatePtr->mask |= KTIMEDATE_YEAR;
207 case KTIMEDATE_MONTH:
208 if ( value > MAX_MONTH_VALUE )
210 relDatePtr->month = value;
211 relDatePtr->mask |= KTIMEDATE_MONTH;
215 if ( value > MAX_DAY_VALUE )
218 relDatePtr->mask |= KTIMEDATE_DAY;
219 relDatePtr->day = value;
225 dateStr++; /* next digit */
229 /* no more chars to process, return the result */
239 * returns a static string representing the relative date. This is in
240 * a format acceptable to the relative date parser.
242 * datePtr - relative date to be converted.
244 * ptr to static string
248 RelDatetoString(datePtr)
249 struct ktime_date *datePtr;
251 static char dateString[64];
252 char tempstring[64], *sptr;
255 sptr = &dateString[0];
257 if ( datePtr->mask & KTIMEDATE_YEAR )
259 sprintf(tempstring, "%-dy", datePtr->year);
260 strcat(sptr, tempstring);
263 if ( datePtr->mask & KTIMEDATE_MONTH )
266 sprintf(tempstring, "%-dm", datePtr->month);
267 strcat(sptr, tempstring);
270 if ( datePtr->mask & KTIMEDATE_DAY )
273 sprintf(tempstring, "%-dd", datePtr->day);
274 strcat(sptr, tempstring);
279 /* Add_RelDate_to_Time
280 * Returns current time with a relative time added. Note that the
281 * computation adds in most significant fields first, i.e. year, month
282 * day etc. Addition of least significant fields would produce different
283 * results (depending on the data).
285 * relDatePtr - a ktime_date containing a relative time specification
287 * returns specified time with relative time added.
291 Add_RelDate_to_Time(relDatePtr, atime)
292 struct ktime_date *relDatePtr;
296 static struct ktime_date absDate;
298 ktimeDate_FromInt32(atime, &absDate); /* convert to ktime */
301 if ( relDatePtr->mask & KTIMEDATE_YEAR )
302 absDate.year += relDatePtr->year;
305 if ( relDatePtr->mask & KTIMEDATE_MONTH )
306 absDate.month += relDatePtr->month;
308 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;