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>
15 #include <sys/types.h>
24 /* maximum values for relative dates */
26 #define MAX_YEAR_VALUE 0
27 #define MAX_MONTH_VALUE 11
28 #define MAX_DAY_VALUE 30
30 /* for parsing relative expiration dates */
31 static struct parseseqS {
34 afs_int32 ps_maxValue;
37 KTIMEDATE_YEAR, 'y', MAX_YEAR_VALUE,}, /* no max. value */
39 KTIMEDATE_MONTH, 'm', MAX_MONTH_VALUE,}, /* months max. 12 */
41 KTIMEDATE_DAY, 'd', MAX_DAY_VALUE,}, /* days max. 31 */
46 /* Encodings to and from relative dates. The caller is responsible for
47 * enforcing appropriate use of these routines
51 /* ktimeRelDate_ToInt32
52 * converts a relative ktime date into an afs_int32.
54 * afs_int32 value of encoded date.
58 ktimeRelDate_ToInt32(struct ktime_date *kdptr)
63 (((kdptr->year * (MAX_MONTH_VALUE + 1)) +
64 kdptr->month) * (MAX_DAY_VALUE + 1)) + kdptr->day;
68 /* Int32To_ktimeRelDate
69 * Convert a relative date encoded in an afs_int32 - back into a ktime_date
74 Int32To_ktimeRelDate(afs_int32 int32Date, struct ktime_date *kdptr)
76 memset(kdptr, 0, sizeof(*kdptr));
78 kdptr->day = int32Date % (MAX_DAY_VALUE + 1);
80 kdptr->mask |= KTIMEDATE_DAY;
82 int32Date = int32Date / (MAX_DAY_VALUE + 1);
84 kdptr->month = int32Date % (MAX_MONTH_VALUE + 1);
85 if (kdptr->month != 0)
86 kdptr->mask |= KTIMEDATE_MONTH;
88 int32Date = int32Date / (MAX_MONTH_VALUE + 1);
90 kdptr->year = int32Date;
92 kdptr->mask |= KTIMEDATE_YEAR;
97 /* ktimeDate_FromInt32
98 * Converts a time in seconds, to a time (in ktime_date format).
99 * Result is a conventional ktime_date structure.
100 * placed in the supplied structure
102 * timeSecs - time in seconds
103 * ktimePtr - ptr to struct for the return value
107 ktimeDate_FromInt32(afs_int32 timeSecs, struct ktime_date *ktimePtr)
109 time_t tt = timeSecs;
116 memset(&timeP, 0, sizeof(timeP));
117 localtime_r(&tt, &timeP);
119 timePtr = localtime(&tt);
122 /* copy the relevant fields */
123 ktimePtr->sec = timePtr->tm_sec;
124 ktimePtr->min = timePtr->tm_min;
125 ktimePtr->hour = timePtr->tm_hour;
126 ktimePtr->day = timePtr->tm_mday;
127 ktimePtr->month = timePtr->tm_mon + 1;
128 ktimePtr->year = timePtr->tm_year;
131 KTIMEDATE_YEAR | KTIMEDATE_MONTH | KTIMEDATE_DAY | KTIMEDATE_HOUR |
132 KTIMEDATE_MIN | KTIMEDATE_SEC;
137 #define RD_DIGIT_LIMIT 4 /* max. no. digits permitted */
140 * Parses a relative date of the form <n>y<n>m<n>d representing years
141 * months and days. <n> is limited to RD_DIGIT_LIMIT digits in length
142 * and is further restricted by the maximums specified at the head
145 * dateStr - ptr to string to parse. Leading white space ingnored.
147 * returns a ptr to a static ktime_date structure containing
148 * appropriately set fields. The mask field is unused.
149 * 0 - error in date specification
153 ParseRelDate(char *dateStr, struct ktime_date * relDatePtr)
155 struct parseseqS *psPtr;
156 afs_int32 value, digit_limit;
157 afs_int32 type_index;
159 memset(relDatePtr, 0, sizeof(*relDatePtr));
164 while (isspace(*dateStr)) /* skip leading whitespace */
167 if (isdigit(*dateStr) == 0)
170 digit_limit = RD_DIGIT_LIMIT;
172 while (isdigit(*dateStr)) {
173 value = value * 10 + *dateStr - '0';
175 if (digit_limit-- == 0)
179 psPtr = &parseseq[type_index];
180 /* determine the units. Search for a matching type character */
181 while ((psPtr->ps_keychar != *dateStr)
182 && (psPtr->ps_keychar != 0)
185 psPtr = &parseseq[type_index];
188 /* no matching type found */
189 if (psPtr->ps_keychar == 0)
192 /* check the bounds on the maximum value. Can't be negative
193 * and if a maximum value is specified, check against it
196 || ((psPtr->ps_maxValue > 0) && (value > psPtr->ps_maxValue))
200 /* save computed value in the relevant type field */
201 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 */
228 /* no more chars to process, return the result */
238 * returns a static string representing the relative date. This is in
239 * a format acceptable to the relative date parser.
241 * datePtr - relative date to be converted.
243 * ptr to static string
247 RelDatetoString(struct ktime_date *datePtr)
249 static char dateString[64];
250 char tempstring[64], *sptr;
253 sptr = &dateString[0];
255 if (datePtr->mask & KTIMEDATE_YEAR) {
256 sprintf(tempstring, "%-dy", datePtr->year);
257 strcat(sptr, tempstring);
260 if (datePtr->mask & KTIMEDATE_MONTH) {
262 sprintf(tempstring, "%-dm", datePtr->month);
263 strcat(sptr, tempstring);
266 if (datePtr->mask & KTIMEDATE_DAY) {
268 sprintf(tempstring, "%-dd", datePtr->day);
269 strcat(sptr, tempstring);
274 /* Add_RelDate_to_Time
275 * Returns current time with a relative time added. Note that the
276 * computation adds in most significant fields first, i.e. year, month
277 * day etc. Addition of least significant fields would produce different
278 * results (depending on the data).
280 * relDatePtr - a ktime_date containing a relative time specification
282 * returns specified time with relative time added.
286 Add_RelDate_to_Time(struct ktime_date * relDatePtr, afs_int32 atime)
289 static struct ktime_date absDate;
291 ktimeDate_FromInt32(atime, &absDate); /* convert to ktime */
294 if (relDatePtr->mask & KTIMEDATE_YEAR)
295 absDate.year += relDatePtr->year;
298 if (relDatePtr->mask & KTIMEDATE_MONTH)
299 absDate.month += relDatePtr->month;
301 if (absDate.month > 12) {
302 moreYears = absDate.month / 12;
303 absDate.month = absDate.month % 12;
304 absDate.year += moreYears;
307 /* day computations depend upon month size, so do these in seconds */
308 atime = ktime_InterpretDate(&absDate);
310 if (relDatePtr->mask & KTIMEDATE_DAY)
311 atime = atime + relDatePtr->day * 24 * 60 * 60;
313 if (relDatePtr->mask & KTIMEDATE_HOUR)
314 atime = atime + relDatePtr->hour * 60 * 60;
316 if (relDatePtr->mask & KTIMEDATE_MIN)
317 atime = atime + relDatePtr->min * 60;
319 if (relDatePtr->mask & KTIMEDATE_SEC)
320 atime = atime + relDatePtr->sec;