2 ======================================================================
4 CREATOR: eric 02 June 2000
6 $Id: icalduration.c,v 1.21 2008-01-15 23:17:40 dothebart Exp $
9 (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of either:
14 The LGPL as published by the Free Software Foundation, version
15 2.1, available at: http://www.fsf.org/copyleft/lesser.html
19 The Mozilla Public License Version 1.0. You may obtain a copy of
20 the License at http://www.mozilla.org/MPL/
22 The Original Code is eric. The Initial Developer of the Original
26 ======================================================================*/
32 #include "icalduration.h"
39 #include "icalerror.h"
40 #include "icalmemory.h"
41 #include "icalvalue.h"
44 #define snprintf _snprintf
47 /* From Seth Alves, <alves@hungry.com> */
48 struct icaldurationtype icaldurationtype_from_int(int t)
50 struct icaldurationtype dur;
53 dur = icaldurationtype_null_duration();
60 if (t % (60 * 60 * 24 * 7) == 0) {
61 dur.weeks = t / (60 * 60 * 24 * 7);
63 used += dur.weeks * (60 * 60 * 24 * 7);
64 dur.days = (t - used) / (60 * 60 * 24);
65 used += dur.days * (60 * 60 * 24);
66 dur.hours = (t - used) / (60 * 60);
67 used += dur.hours * (60 * 60);
68 dur.minutes = (t - used) / (60);
69 used += dur.minutes * (60);
70 dur.seconds = (t - used);
76 struct icaldurationtype icaldurationtype_from_string(const char* str)
85 size_t size = strlen(str);
87 struct icaldurationtype d;
89 memset(&d, 0, sizeof(struct icaldurationtype));
91 for(i=0;i != size;i++){
97 if(i != 0 || begin_flag == 1) goto error;
104 if (i != 0 && i !=1 ) goto error;
126 /* HACK. Skip any more digits if the l;ast one
127 read has not been assigned */
132 if (begin_flag == 0) goto error;
133 /* Get all of the digits, not one at a time */
134 scan_size = sscanf(&str[i],"%d",&digits);
135 if(scan_size == 0) goto error;
140 if (time_flag == 0||d.hours !=0||digits ==-1)
142 d.hours = digits; digits = -1;
146 if (time_flag == 0||d.minutes != 0||digits ==-1)
148 d.minutes = digits; digits = -1;
152 if (time_flag == 0||d.seconds!=0||digits ==-1)
154 d.seconds = digits; digits = -1;
158 if (time_flag==1||date_flag==1||d.weeks!=0||digits ==-1)
160 d.weeks = digits; digits = -1;
164 if (time_flag==1||d.days!=0||digits ==-1)
167 d.days = digits; digits = -1;
181 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
182 return icaldurationtype_bad_duration();
185 #define TMP_BUF_SIZE 1024
187 void append_duration_segment(char** buf, char** buf_ptr, size_t* buf_size,
188 const char* sep, unsigned int value) {
190 char temp[TMP_BUF_SIZE];
192 snprintf(temp,sizeof(temp),"%d",value);
194 icalmemory_append_string(buf, buf_ptr, buf_size, temp);
195 icalmemory_append_string(buf, buf_ptr, buf_size, sep);
199 char* icaldurationtype_as_ical_string(struct icaldurationtype d)
202 buf = icaldurationtype_as_ical_string_r(d);
203 icalmemory_add_tmp_buffer(buf);
208 char* icaldurationtype_as_ical_string_r(struct icaldurationtype d)
212 size_t buf_size = 256;
216 buf = (char*)icalmemory_new_buffer(buf_size);
220 seconds = icaldurationtype_as_int(d);
225 icalmemory_append_char(&buf, &buf_ptr, &buf_size, '-');
228 icalmemory_append_char(&buf, &buf_ptr, &buf_size, 'P');
231 append_duration_segment(&buf, &buf_ptr, &buf_size, "W", d.weeks);
235 append_duration_segment(&buf, &buf_ptr, &buf_size, "D", d.days);
238 if (d.hours != 0 || d.minutes != 0 || d.seconds != 0) {
240 icalmemory_append_string(&buf, &buf_ptr, &buf_size, "T");
243 append_duration_segment(&buf, &buf_ptr, &buf_size, "H", d.hours);
245 if (d.minutes != 0 ) {
246 append_duration_segment(&buf, &buf_ptr, &buf_size, "M",
249 if (d.seconds != 0 ) {
250 append_duration_segment(&buf, &buf_ptr, &buf_size, "S",
256 icalmemory_append_string(&buf, &buf_ptr, &buf_size, "PT0S");
263 /* From Russel Steinthal */
264 int icaldurationtype_as_int(struct icaldurationtype dur)
266 return (int)( (dur.seconds +
268 (60 * 60 * dur.hours) +
269 (60 * 60 * 24 * dur.days) +
270 (60 * 60 * 24 * 7 * dur.weeks))
271 * (dur.is_neg==1? -1 : 1) ) ;
274 struct icaldurationtype icaldurationtype_null_duration(void)
276 struct icaldurationtype d;
278 memset(&d,0,sizeof(struct icaldurationtype));
283 int icaldurationtype_is_null_duration(struct icaldurationtype d)
285 if(icaldurationtype_as_int(d) == 0){
292 /* in icalvalue_new_from_string_with_error, we should not call
293 icaldurationtype_is_null_duration() to see if there is an error
294 condition. Null duration is perfectly valid for an alarm.
295 We cannot depend on the caller to check icalerrno either,
296 following the philosophy of unix errno. we set the is_neg
297 to -1 to indicate that this is a bad duration.
299 struct icaldurationtype icaldurationtype_bad_duration()
301 struct icaldurationtype d;
302 memset(&d,0,sizeof(struct icaldurationtype));
307 int icaldurationtype_is_bad_duration(struct icaldurationtype d)
309 return (d.is_neg == -1);
313 struct icaltimetype icaltime_add(struct icaltimetype t,
314 struct icaldurationtype d)
317 t.second += d.seconds;
318 t.minute += d.minutes;
321 t.day += d.weeks * 7;
323 t.second -= d.seconds;
324 t.minute -= d.minutes;
327 t.day -= d.weeks * 7;
330 t = icaltime_normalize(t);
335 struct icaldurationtype icaltime_subtract(struct icaltimetype t1,
336 struct icaltimetype t2)
339 time_t t1t = icaltime_as_timet(t1);
340 time_t t2t = icaltime_as_timet(t2);
342 return icaldurationtype_from_int((int)(t1t-t2t));