1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
#include <ruby.h>
#include <libical/ical.h>
#include <time.h>
//#define RRULE "FREQ=MONTHLY;BYMONTH=1,2,3,4,5,6,7,8,9,10,11;BYDAY=-1WE;UNTIL=20091105T220000"
//#define RRULE "FREQ=DAILY;UNTIL=20991111T220000;VFOO"
VALUE occurrences( VALUE dtstart, VALUE dtend, char *rrule ) {
struct icaltimetype start, end;
time_t tt;
VALUE tv_sec, occurr = rb_ary_new();
/* Get method ID for Time.tv_sec */
ID time_tv_sec = rb_intern( "tv_sec" );
ID time_to_time = rb_intern( "to_time" );
if( !rb_respond_to( dtstart, time_tv_sec ) ) {
if( rb_respond_to( dtstart, time_to_time ) )
dtstart = rb_funcall( dtstart, time_to_time, 0 );
else
rb_raise( rb_eTypeError, "Can't convert dtstart into a Time-like object." );
}
if( !rb_respond_to( dtend, time_tv_sec ) ) {
if( rb_respond_to( dtend, time_to_time ) )
dtend = rb_funcall( dtend, time_to_time, 0 );
else
rb_raise( rb_eTypeError, "Can't convert dtend into a Time-like object." );
}
/* Apply .tv_sec to our Time objects (if they are Times ...) */
tv_sec = rb_funcall( dtstart, time_tv_sec, 0 );
tt = NUM2INT( tv_sec );
start = icaltime_from_timet( tt, 0 );
tv_sec = rb_funcall( dtend, time_tv_sec, 0 );
tt = NUM2INT( tv_sec );
end = icaltime_from_timet( tt, 0 );
icalerror_clear_errno();
icalerror_set_error_state( ICAL_MALFORMEDDATA_ERROR, ICAL_ERROR_NONFATAL);
struct icalrecurrencetype recur = icalrecurrencetype_from_string( rrule );
if( icalerrno != ICAL_NO_ERROR ) {
rb_raise(rb_eArgError, "Malformed RRule");
return Qnil;
}
icalrecur_iterator* ritr = icalrecur_iterator_new( recur, start );
while(1) {
struct icaltimetype next = icalrecur_iterator_next(ritr);
if( icaltime_is_null_time(next) || ( icaltime_compare( next, end ) > 0 ) ) {
icalrecur_iterator_free(ritr);
return occurr;
}
rb_ary_push( occurr, rb_time_new( icaltime_as_timet( next ), 0 ) );
};
icalrecur_iterator_free(ritr);
return occurr;
}
VALUE duration_to_fixnum( char * duration ) {
icalerror_clear_errno();
icalerror_set_error_state( ICAL_MALFORMEDDATA_ERROR, ICAL_ERROR_NONFATAL);
struct icaldurationtype dur_struct = icaldurationtype_from_string( duration );
if( icaldurationtype_is_bad_duration( dur_struct ) )
rb_raise(rb_eArgError, "Malformed Duration");
return LONG2FIX(icaldurationtype_as_int( dur_struct ));
}
|