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>
21 /* maximum values for relative dates */
23 #define MAX_YEAR_VALUE 0
24 #define MAX_MONTH_VALUE 11
25 #define MAX_DAY_VALUE 30
27 /* for parsing relative expiration dates */
28 static struct parseseqS
{
31 afs_int32 ps_maxValue
;
34 KTIMEDATE_YEAR
, 'y', MAX_YEAR_VALUE
,}, /* no max. value */
36 KTIMEDATE_MONTH
, 'm', MAX_MONTH_VALUE
,}, /* months max. 12 */
38 KTIMEDATE_DAY
, 'd', MAX_DAY_VALUE
,}, /* days max. 31 */
43 /* Encodings to and from relative dates. The caller is responsible for
44 * enforcing appropriate use of these routines
48 /* ktimeRelDate_ToInt32
49 * converts a relative ktime date into an afs_int32.
51 * afs_int32 value of encoded date.
55 ktimeRelDate_ToInt32(struct ktime_date
*kdptr
)
60 (((kdptr
->year
* (MAX_MONTH_VALUE
+ 1)) +
61 kdptr
->month
) * (MAX_DAY_VALUE
+ 1)) + kdptr
->day
;
65 /* Int32To_ktimeRelDate
66 * Convert a relative date encoded in an afs_int32 - back into a ktime_date
71 Int32To_ktimeRelDate(afs_int32 int32Date
, struct ktime_date
*kdptr
)
73 memset(kdptr
, 0, sizeof(*kdptr
));
75 kdptr
->day
= int32Date
% (MAX_DAY_VALUE
+ 1);
77 kdptr
->mask
|= KTIMEDATE_DAY
;
79 int32Date
= int32Date
/ (MAX_DAY_VALUE
+ 1);
81 kdptr
->month
= int32Date
% (MAX_MONTH_VALUE
+ 1);
82 if (kdptr
->month
!= 0)
83 kdptr
->mask
|= KTIMEDATE_MONTH
;
85 int32Date
= int32Date
/ (MAX_MONTH_VALUE
+ 1);
87 kdptr
->year
= int32Date
;
89 kdptr
->mask
|= KTIMEDATE_YEAR
;
94 /* ktimeDate_FromInt32
95 * Converts a time in seconds, to a time (in ktime_date format).
96 * Result is a conventional ktime_date structure.
97 * placed in the supplied structure
99 * timeSecs - time in seconds
100 * ktimePtr - ptr to struct for the return value
104 ktimeDate_FromInt32(afs_int32 timeSecs
, struct ktime_date
*ktimePtr
)
106 time_t tt
= timeSecs
;
113 memset(&timeP
, 0, sizeof(timeP
));
114 localtime_r(&tt
, &timeP
);
116 timePtr
= localtime(&tt
);
119 /* copy the relevant fields */
120 ktimePtr
->sec
= timePtr
->tm_sec
;
121 ktimePtr
->min
= timePtr
->tm_min
;
122 ktimePtr
->hour
= timePtr
->tm_hour
;
123 ktimePtr
->day
= timePtr
->tm_mday
;
124 ktimePtr
->month
= timePtr
->tm_mon
+ 1;
125 ktimePtr
->year
= timePtr
->tm_year
;
128 KTIMEDATE_YEAR
| KTIMEDATE_MONTH
| KTIMEDATE_DAY
| KTIMEDATE_HOUR
|
129 KTIMEDATE_MIN
| KTIMEDATE_SEC
;
134 #define RD_DIGIT_LIMIT 4 /* max. no. digits permitted */
137 * Parses a relative date of the form <n>y<n>m<n>d representing years
138 * months and days. <n> is limited to RD_DIGIT_LIMIT digits in length
139 * and is further restricted by the maximums specified at the head
142 * dateStr - ptr to string to parse. Leading white space ingnored.
144 * returns a ptr to a static ktime_date structure containing
145 * appropriately set fields. The mask field is unused.
146 * 0 - error in date specification
150 ParseRelDate(char *dateStr
, struct ktime_date
* relDatePtr
)
152 struct parseseqS
*psPtr
;
153 afs_int32 value
, digit_limit
;
154 afs_int32 type_index
;
156 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
)) {
170 value
= value
* 10 + *dateStr
- '0';
172 if (digit_limit
-- == 0)
176 psPtr
= &parseseq
[type_index
];
177 /* determine the units. Search for a matching type character */
178 while ((psPtr
->ps_keychar
!= *dateStr
)
179 && (psPtr
->ps_keychar
!= 0)
182 psPtr
= &parseseq
[type_index
];
185 /* no matching type found */
186 if (psPtr
->ps_keychar
== 0)
189 /* check the bounds on the maximum value. Can't be negative
190 * and if a maximum value is specified, check against it
193 || ((psPtr
->ps_maxValue
> 0) && (value
> psPtr
->ps_maxValue
))
197 /* save computed value in the relevant type field */
198 switch (psPtr
->ps_field
) {
200 relDatePtr
->year
= value
;
201 relDatePtr
->mask
|= KTIMEDATE_YEAR
;
204 case KTIMEDATE_MONTH
:
205 if (value
> MAX_MONTH_VALUE
)
207 relDatePtr
->month
= value
;
208 relDatePtr
->mask
|= KTIMEDATE_MONTH
;
212 if (value
> MAX_DAY_VALUE
)
215 relDatePtr
->mask
|= KTIMEDATE_DAY
;
216 relDatePtr
->day
= value
;
222 dateStr
++; /* next digit */
225 /* no more chars to process, return the result */
235 * returns a static string representing the relative date. This is in
236 * a format acceptable to the relative date parser.
238 * datePtr - relative date to be converted.
240 * ptr to static string
244 RelDatetoString(struct ktime_date
*datePtr
)
246 static char dateString
[64];
247 char tempstring
[64], *sptr
;
250 sptr
= &dateString
[0];
252 if (datePtr
->mask
& KTIMEDATE_YEAR
) {
253 sprintf(tempstring
, "%-dy", datePtr
->year
);
254 strcat(sptr
, tempstring
);
257 if (datePtr
->mask
& KTIMEDATE_MONTH
) {
259 sprintf(tempstring
, "%-dm", datePtr
->month
);
260 strcat(sptr
, tempstring
);
263 if (datePtr
->mask
& KTIMEDATE_DAY
) {
265 sprintf(tempstring
, "%-dd", datePtr
->day
);
266 strcat(sptr
, tempstring
);
271 /* Add_RelDate_to_Time
272 * Returns current time with a relative time added. Note that the
273 * computation adds in most significant fields first, i.e. year, month
274 * day etc. Addition of least significant fields would produce different
275 * results (depending on the data).
277 * relDatePtr - a ktime_date containing a relative time specification
279 * returns specified time with relative time added.
283 Add_RelDate_to_Time(struct ktime_date
* relDatePtr
, afs_int32 atime
)
286 static struct ktime_date absDate
;
288 ktimeDate_FromInt32(atime
, &absDate
); /* convert to ktime */
291 if (relDatePtr
->mask
& KTIMEDATE_YEAR
)
292 absDate
.year
+= relDatePtr
->year
;
295 if (relDatePtr
->mask
& KTIMEDATE_MONTH
)
296 absDate
.month
+= relDatePtr
->month
;
298 if (absDate
.month
> 12) {
299 moreYears
= absDate
.month
/ 12;
300 absDate
.month
= absDate
.month
% 12;
301 absDate
.year
+= moreYears
;
304 /* day computations depend upon month size, so do these in seconds */
305 atime
= ktime_InterpretDate(&absDate
);
307 if (relDatePtr
->mask
& KTIMEDATE_DAY
)
308 atime
= atime
+ relDatePtr
->day
* 24 * 60 * 60;
310 if (relDatePtr
->mask
& KTIMEDATE_HOUR
)
311 atime
= atime
+ relDatePtr
->hour
* 60 * 60;
313 if (relDatePtr
->mask
& KTIMEDATE_MIN
)
314 atime
= atime
+ relDatePtr
->min
* 60;
316 if (relDatePtr
->mask
& KTIMEDATE_SEC
)
317 atime
= atime
+ relDatePtr
->sec
;