2 * $Id: duration.c 4518 2011-02-24 15:39:09Z matthijs $
4 * Copyright (c) 2009 NLNet Labs. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
21 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
23 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
25 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 * This file is copied from the OpenDNSSEC source repository
32 * and only slightly adapted to make it fit.
40 #include <ldns/config.h>
41 #include <ldns/duration.h>
50 * Create a new 'instant' duration.
54 ldns_duration_create(void)
56 ldns_duration_type
* duration
;
58 duration
= malloc(sizeof(ldns_duration_type
));
67 duration
->minutes
= 0;
68 duration
->seconds
= 0;
78 ldns_duration_compare(ldns_duration_type
* d1
, ldns_duration_type
* d2
)
87 if (d1
->years
!= d2
->years
) {
88 return (int) (d1
->years
- d2
->years
);
90 if (d1
->months
!= d2
->months
) {
91 return (int) (d1
->months
- d2
->months
);
93 if (d1
->weeks
!= d2
->weeks
) {
94 return (int) (d1
->weeks
- d2
->weeks
);
96 if (d1
->days
!= d2
->days
) {
97 return (int) (d1
->days
- d2
->days
);
99 if (d1
->hours
!= d2
->hours
) {
100 return (int) (d1
->hours
- d2
->hours
);
102 if (d1
->minutes
!= d2
->minutes
) {
103 return (int) (d1
->minutes
- d2
->minutes
);
105 if (d1
->seconds
!= d2
->seconds
) {
106 return (int) (d1
->seconds
- d2
->seconds
);
114 * Create a duration from string.
118 ldns_duration_create_from_string(const char* str
)
120 ldns_duration_type
* duration
= ldns_duration_create();
131 P
= strchr(str
, 'P');
133 ldns_duration_cleanup(duration
);
137 T
= strchr(str
, 'T');
138 X
= strchr(str
, 'Y');
140 duration
->years
= (time_t) atoi(str
+1);
144 X
= strchr(str
, 'M');
145 if (X
&& (!T
|| (size_t) (X
-P
) < (size_t) (T
-P
))) {
146 duration
->months
= (time_t) atoi(str
+1);
150 X
= strchr(str
, 'D');
152 duration
->days
= (time_t) atoi(str
+1);
160 X
= strchr(str
, 'H');
162 duration
->hours
= (time_t) atoi(str
+1);
166 X
= strrchr(str
, 'M');
167 if (X
&& T
&& (size_t) (X
-P
) > (size_t) (T
-P
)) {
168 duration
->minutes
= (time_t) atoi(str
+1);
172 X
= strchr(str
, 'S');
174 duration
->seconds
= (time_t) atoi(str
+1);
179 W
= strchr(str
, 'W');
182 ldns_duration_cleanup(duration
);
185 duration
->weeks
= (time_t) atoi(str
+1);
194 * Get the number of digits in a number.
198 digits_in_number(time_t duration
)
200 uint32_t period
= (uint32_t) duration
;
212 * Convert a duration to a string.
216 ldns_duration2string(ldns_duration_type
* duration
)
218 char* str
= NULL
, *num
= NULL
;
226 if (duration
->years
> 0) {
227 count
= count
+ 1 + digits_in_number(duration
->years
);
229 if (duration
->months
> 0) {
230 count
= count
+ 1 + digits_in_number(duration
->months
);
232 if (duration
->weeks
> 0) {
233 count
= count
+ 1 + digits_in_number(duration
->weeks
);
235 if (duration
->days
> 0) {
236 count
= count
+ 1 + digits_in_number(duration
->days
);
238 if (duration
->hours
> 0) {
239 count
= count
+ 1 + digits_in_number(duration
->hours
);
242 if (duration
->minutes
> 0) {
243 count
= count
+ 1 + digits_in_number(duration
->minutes
);
246 if (duration
->seconds
> 0) {
247 count
= count
+ 1 + digits_in_number(duration
->seconds
);
254 str
= (char*) calloc(count
, sizeof(char));
258 if (duration
->years
> 0) {
259 count
= digits_in_number(duration
->years
);
260 num
= (char*) calloc(count
+2, sizeof(char));
261 snprintf(num
, count
+2, "%uY", (unsigned int) duration
->years
);
262 str
= strncat(str
, num
, count
+2);
265 if (duration
->months
> 0) {
266 count
= digits_in_number(duration
->months
);
267 num
= (char*) calloc(count
+2, sizeof(char));
268 snprintf(num
, count
+2, "%uM", (unsigned int) duration
->months
);
269 str
= strncat(str
, num
, count
+2);
272 if (duration
->weeks
> 0) {
273 count
= digits_in_number(duration
->weeks
);
274 num
= (char*) calloc(count
+2, sizeof(char));
275 snprintf(num
, count
+2, "%uW", (unsigned int) duration
->weeks
);
276 str
= strncat(str
, num
, count
+2);
279 if (duration
->days
> 0) {
280 count
= digits_in_number(duration
->days
);
281 num
= (char*) calloc(count
+2, sizeof(char));
282 snprintf(num
, count
+2, "%uD", (unsigned int) duration
->days
);
283 str
= strncat(str
, num
, count
+2);
287 str
= strncat(str
, "T", 1);
289 if (duration
->hours
> 0) {
290 count
= digits_in_number(duration
->hours
);
291 num
= (char*) calloc(count
+2, sizeof(char));
292 snprintf(num
, count
+2, "%uH", (unsigned int) duration
->hours
);
293 str
= strncat(str
, num
, count
+2);
296 if (duration
->minutes
> 0) {
297 count
= digits_in_number(duration
->minutes
);
298 num
= (char*) calloc(count
+2, sizeof(char));
299 snprintf(num
, count
+2, "%uM", (unsigned int) duration
->minutes
);
300 str
= strncat(str
, num
, count
+2);
303 if (duration
->seconds
> 0) {
304 count
= digits_in_number(duration
->seconds
);
305 num
= (char*) calloc(count
+2, sizeof(char));
306 snprintf(num
, count
+2, "%uS", (unsigned int) duration
->seconds
);
307 str
= strncat(str
, num
, count
+2);
315 * Convert a duration to a time.
319 ldns_duration2time(ldns_duration_type
* duration
)
324 period
+= (duration
->seconds
);
325 period
+= (duration
->minutes
)*60;
326 period
+= (duration
->hours
)*3600;
327 period
+= (duration
->days
)*86400;
328 period
+= (duration
->weeks
)*86400*7;
329 period
+= (duration
->months
)*86400*31;
330 period
+= (duration
->years
)*86400*365;
332 /* [TODO] calculate correct number of days in this month/year */
334 if (duration->months || duration->years) {
347 ldns_duration_cleanup(ldns_duration_type
* duration
)