jerryluk-jruby-rfc2445 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/MIT-LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2009 Jerry Luk <jerryluk@gmail.com>
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,14 @@
1
+ jruby-rfc2445
2
+ =============
3
+ A JRuby implementation of RFC 2445 (ical) recurrence rules.
4
+
5
+ This library makes use of the google-rfc-2445 library (http://code.google.com/p/google-rfc-2445/)
6
+ To see the usage, please see the RSpec test cases.
7
+
8
+ The JTime class uses Joda-time as its underlying implementation. To find out more about Joda time, visit:
9
+ http://joda-time.sourceforge.net/
10
+
11
+ Getting Started
12
+ ===============
13
+ 1. Make sure you can install RubyGem from GitHub (you only have to do this once): jruby -S gem sources -a http://gems.github.com
14
+ 2. Install JRuby RFC 2445 library: jruby -S gem install jerryluk-jruby-rfc2445
data/lib/jtime.rb ADDED
@@ -0,0 +1,201 @@
1
+ require 'java'
2
+ require File.dirname(__FILE__) + '/rfc2445.jar'
3
+
4
+ class JTime
5
+ include Comparable
6
+ include_class('org.joda.time.DateTime'){|package,name| "J#{name}" }
7
+
8
+ # Class Methods
9
+ class << self
10
+ # Creates a new time object with the given number of seconds (and optional
11
+ # microseconds) from epoch.
12
+ #
13
+ # ==== Options
14
+ # +seconds+:: given number of seconds from epoch
15
+ # +microseconds+:: Optional. microseconds from epoch
16
+ #
17
+ def at(seconds, microseconds=0)
18
+ datetime = JDateTime.new(seconds * 1000 + microseconds)
19
+ new(datetime)
20
+ end
21
+
22
+ # Creates a time based on given values, interpreted as UTC (GMT).
23
+ # The year must be specified. Other values default to the minimum
24
+ # value for that field.
25
+ #
26
+ # ==== Options
27
+ # +year+:: Year
28
+ # +month+:: Optional. Numbers from 1 to 12, or by the three-letter
29
+ # English month names
30
+ # +hour+:: Optional.24-hour clock (0..23)
31
+ # +min+:: Optional. 0..59
32
+ # +sec+:: Optional. seconds of the time
33
+ # +usec+:: Optional. microsecond of the time
34
+ def utc(year, month=1, day=1, hour=0, min=0, sec=0, usec=0)
35
+ datetime = JDateTime.new(year, numeric_month(month), day, hour, min, sec, usec,
36
+ org.joda.time.DateTimeZone::UTC)
37
+ new(datetime)
38
+ end
39
+
40
+ # Same as JTime.utc, but interprets the values in local time zone
41
+ def local(year, month=1, day=1, hour=0, min=0, sec=0, usec=0)
42
+ datetime = JDateTime.new(year, numeric_month(month), day, hour, min, sec, usec)
43
+ new(datetime)
44
+ end
45
+
46
+ # Initialize a JTime object from DateTimeValue
47
+ def from_date_time_value(dtv)
48
+ utc(dtv.year, dtv.month, dtv.day, dtv.hour, dtv.minute, dtv.second)
49
+ end
50
+
51
+ # Initialize a JTime object from Ruby Time object
52
+ def from_time(time)
53
+ datetime = JDateTime.new((time.to_f * 1000).to_i)
54
+ new(datetime)
55
+ end
56
+
57
+ alias :now :new
58
+ alias :gm :utc
59
+ alias :mktime :local
60
+
61
+ protected
62
+ MONTH_NAME_HASH = {
63
+ 'jan' => 1,
64
+ 'feb' => 2,
65
+ 'mar' => 3,
66
+ 'apr' => 4,
67
+ 'may' => 5,
68
+ 'jun' => 6,
69
+ 'jul' => 7,
70
+ 'aug' => 8,
71
+ 'sep' => 9,
72
+ 'oct' => 10,
73
+ 'nov' => 11,
74
+ 'dec' => 12
75
+ }
76
+
77
+ def numeric_month(mon)
78
+ return mon if mon.kind_of? Fixnum
79
+ MONTH_NAME_HASH[mon.downcase]
80
+ end
81
+ end
82
+
83
+ # Instance Methods
84
+
85
+ # Returns a JTime object. If a Java DateTime object is passed, it is initialized
86
+ # from the Java JDateTime object, otherwise it is initialized to the current
87
+ # system time
88
+ #
89
+ # ==== Options
90
+ # +datetime+:: Optional. The Java DateTime (org.joda.time.DateTime')object
91
+ #
92
+ def initialize(datetime = JDateTime.new)
93
+ @time = datetime
94
+ self
95
+ end
96
+
97
+ # Returns a Ruby Time object
98
+ def to_time
99
+ millis = @time.getMillis
100
+ Time.at(millis / 1000, millis % 1000 * 1000)
101
+ end
102
+
103
+ # Returns the underlying Java DateTime object
104
+ def to_java
105
+ @time
106
+ end
107
+
108
+ # Returns the value of time as an integer number of seconds since epoch
109
+ def to_i
110
+ @time.getMillis / 1000
111
+ end
112
+
113
+ # Returns the value of time as a floating point number of seconds since epoch
114
+ def to_f
115
+ @time.getMillis / 1000.0
116
+ end
117
+
118
+ # Returns a string representing JTime
119
+ def to_s
120
+ @time.toString
121
+ end
122
+
123
+ # Returns a new JTime object in UTC time. The receiver is unchanged
124
+ # IMPORTANT: The original utc in Ruby modified the receiver object
125
+ def utc
126
+ datetime = @time.toDateTime(org.joda.time.DateTimeZone::UTC)
127
+ self.class.new(datetime)
128
+ end
129
+
130
+ def <=>(another_time)
131
+ @time.compareTo(another_time.to_java)
132
+ end
133
+
134
+ def year
135
+ @time.getYear
136
+ end
137
+
138
+ def month
139
+ @time.getMonthOfYear
140
+ end
141
+
142
+ def day
143
+ @time.getDayOfMonth
144
+ end
145
+
146
+ def hour
147
+ @time.getHourOfDay
148
+ end
149
+
150
+ def min
151
+ @time.getMinuteOfHour
152
+ end
153
+
154
+ def sec
155
+ @time.getSecondOfMinute
156
+ end
157
+
158
+ def wday
159
+ @time.getDayOfWeek
160
+ end
161
+
162
+ def yday
163
+ @time.getDayOfYear
164
+ end
165
+
166
+ def week
167
+ @time.getWeekOfWeekyear
168
+ end
169
+
170
+ # Returns the name of the timezone used for time.
171
+ # IMPORTANT: Unlike Ruby Time, which returns "PST"
172
+ # it actuallys return real timezone ID such as 'America/Los_Angeles'
173
+ def zone
174
+ @time.getZone.getID
175
+ end
176
+
177
+ # Returns DateTimeValue object
178
+ def to_date_time_value
179
+ com.google.ical.values.DateTimeValueImpl.new(self.year, self.month, self.day, self.hour, self.min, self.sec)
180
+ end
181
+
182
+ # Returns the Java Timezone object
183
+ def java_zone
184
+ @time.getZone
185
+ end
186
+
187
+ # Returns true if time occurs during Daylight Saveing Time in its timeezone
188
+ def isdst
189
+ timezone = @time.getZone.toTimeZone
190
+ timezone.inDaylightTime(@time.toDate)
191
+ end
192
+
193
+ # We should consider getting rid of this or implement this using meta-programming
194
+ def method_missing(key, *params)
195
+ @time.send(key, *params)
196
+ end
197
+
198
+ alias :mon :month
199
+ alias :dst? :isdst
200
+
201
+ end
data/lib/rdate_list.rb ADDED
@@ -0,0 +1,95 @@
1
+ require 'java'
2
+ require File.dirname(__FILE__) + '/rfc2445.jar'
3
+
4
+ class RDateList
5
+ include_class('com.google.ical.values.RDateList') { |package,name| "J#{name}" }
6
+ include_class('java.util.TimeZone') { |package,name| "J#{name}" }
7
+
8
+ RDATE = 'RDATE'
9
+ EXDATE = 'EXDATE'
10
+ VEVENT = 'VEVENT'
11
+
12
+ # Initializes a RDateList with optionally a time zone ID and an iCal string
13
+ #
14
+ # ==== Options
15
+ # +timezone+:: Optional. Time zone ID. For instance, the time zone ID for the
16
+ # U.S. Pacific Time zone is "America/Los_Angeles"
17
+ # If no timezone is specify, it uses time zone where the program
18
+ # is run
19
+ # +ical_string+:: Optional. The iCal string for the recurrent rule.
20
+ # The string must specify the rule type (RRULE, EXRULE or VEVENT)
21
+ #
22
+ def initialize(timezone=nil, ical_string=nil)
23
+ tz = timezone ? JTimeZone.getTimeZone(timezone) : JTimeZone.getDefault
24
+ @rdatelist = ical_string ?
25
+ JRDateList.new(ical_string, tz) :
26
+ JRDateList.new(tz)
27
+ self
28
+ end
29
+
30
+ # Returns the underlying Java object
31
+ def to_java
32
+ @rdatelist
33
+ end
34
+
35
+ # Returns the unfolded RFC 2445 content line.
36
+ def to_ical
37
+ @rdatelist.toIcal
38
+ end
39
+
40
+ # Returns a hash map of any extension parameters such as
41
+ # the X-FOO=BAR in RRULE;X-FOO=BAR
42
+ def ext_params
43
+ h = {}
44
+ @rdatelist.getExtParams.to_a.each do |p|
45
+ h[p[0]] = p[1]
46
+ end
47
+ h
48
+ end
49
+
50
+ # Returns the type of the object name such as
51
+ # RRULE, EXRULE, or VEVENT
52
+ def name
53
+ @rdatelist.getName
54
+ end
55
+
56
+ # Sets the type of the object such as
57
+ # RRULE, EXRULE, or VEVENT
58
+ #
59
+ # ==== Options
60
+ # +new_name+:: 'RRULE', 'EXRULE', or 'VEVENT'
61
+ def name=(new_name)
62
+ @rdatelist.setName(new_name)
63
+ self
64
+ end
65
+
66
+ # Returns the timezone ID. For instance, the time zone ID for the
67
+ # U.S. Pacific Time zone is "America/Los_Angeles"
68
+ def zone
69
+ @rdatelist.getTzid.getID
70
+ end
71
+
72
+ # Sets the timezone using Time zone ID
73
+ def zone=(timezone)
74
+ @rdatelist.setTzid(JTimeZone.getTimeZone(timezone))
75
+ self
76
+ end
77
+
78
+ # Returns the JTime in UTC time zone
79
+ def utc_dates
80
+ dates = @rdatelist.getDatesUtc
81
+ dates.map do |d|
82
+ JTime.utc(d.year, d.month, d.day)
83
+ end
84
+ end
85
+
86
+ # Sets the dates. It will convert the dates into UTC.
87
+ def utc_dates=(dates)
88
+ dates = dates.map do |d|
89
+ utc_d = d.utc
90
+ com.google.ical.values.DateValueImpl.new(utc_d.year, utc_d.month, utc_d.day)
91
+ end
92
+ @rdatelist.setDatesUtc(dates.to_java('com.google.ical.values.DateValue'))
93
+ self
94
+ end
95
+ end
data/lib/rfc2445.rb ADDED
@@ -0,0 +1,9 @@
1
+ require 'java'
2
+ require File.dirname(__FILE__) + '/jtime.rb'
3
+ require File.dirname(__FILE__) + '/weekday.rb'
4
+ require File.dirname(__FILE__) + '/weekday_num.rb'
5
+ require File.dirname(__FILE__) + '/rrule.rb'
6
+ require File.dirname(__FILE__) + '/rdate_list.rb'
7
+ require File.dirname(__FILE__) + '/recurrence_time.rb'
8
+ require File.dirname(__FILE__) + '/ical_parse_util.rb'
9
+ include_class "com.google.ical.values.Frequency"
data/lib/rrule.rb ADDED
@@ -0,0 +1,244 @@
1
+ require 'java'
2
+ require File.dirname(__FILE__) + '/rfc2445.jar'
3
+
4
+ class RRule
5
+ include_class('com.google.ical.values.RRule'){|package,name| "J#{name}" }
6
+
7
+ RRULE = 'RRULE'
8
+ EXRULE = 'EXRULE'
9
+ VEVENT = 'VEVENT'
10
+
11
+ # Initializes a Recurrence Rule with optionally an iCal string
12
+ #
13
+ # ==== Options
14
+ # +ical_string+:: Optional. The iCal string for the recurrent rule.
15
+ # The string must specify the rule type (RRULE, EXRULE or VEVENT)
16
+ #
17
+ def initialize(ical_string=nil)
18
+ @rrule = ical_string ? JRRule.new(ical_string) : JRRule.new
19
+ self
20
+ end
21
+
22
+ # Returns the underlying Java object
23
+ def to_java
24
+ @rrule
25
+ end
26
+
27
+ # Returns the unfolded RFC 2445 content line.
28
+ def to_ical
29
+ @rrule.toIcal
30
+ end
31
+
32
+ # Returns a hash map of any extension parameters such as
33
+ # the X-FOO=BAR in RRULE;X-FOO=BAR
34
+ def ext_params
35
+ h = {}
36
+ @rrule.getExtParams.to_a.each do |p|
37
+ h[p[0]] = p[1]
38
+ end
39
+ h
40
+ end
41
+
42
+ def count
43
+ @rrule.getCount
44
+ end
45
+
46
+ # ==== Options
47
+ # +new_count+:: number of count
48
+ def count=(new_count)
49
+ @rrule.setCount(new_count)
50
+ self
51
+ end
52
+
53
+ def hours
54
+ @rrule.getByHour.to_a
55
+ end
56
+
57
+ # ==== Options
58
+ # +new_hours+:: array of numbers (0..23)
59
+ def hours=(new_hours=[])
60
+ @rrule.setByHour(new_hours.to_java(:int))
61
+ self
62
+ end
63
+
64
+ def minutes
65
+ @rrule.getByMinute.to_a
66
+ end
67
+
68
+ # ==== Options
69
+ # +new_minutes+:: array of numbers (0..59)
70
+ def minutes=(new_minutes=[])
71
+ @rrule.setByMinute(new_minutes.to_java(:int))
72
+ self
73
+ end
74
+
75
+ def months
76
+ @rrule.getByMonth.to_a
77
+ end
78
+
79
+ # ==== Options
80
+ # +new_months+:: array of numbers (1..12)
81
+ def months=(new_months=[])
82
+ @rrule.setByMonth(new_months.to_java(:int))
83
+ self
84
+ end
85
+
86
+ # Gets the days of month
87
+ def mdays
88
+ @rrule.getByMonthDay.to_a
89
+ end
90
+
91
+ # Sets the days of month
92
+ #
93
+ # ==== Options
94
+ # +new_mdays+:: array of days of month (1..31)
95
+ def mdays=(new_mdays=[])
96
+ @rrule.setByMonthDay(new_mdays.to_java(:int))
97
+ self
98
+ end
99
+
100
+ def seconds
101
+ @rrule.getBySecond.to_a
102
+ end
103
+
104
+ # ==== Options
105
+ # +new_seconds+:: array of days of month (0..59)
106
+ def seconds=(new_seconds=[])
107
+ @rrule.setBySecond(new_seconds.to_java(:int))
108
+ self
109
+ end
110
+
111
+ def setpos
112
+ @rrule.getBySetPos.to_a
113
+ end
114
+
115
+ def setpos=(new_setpos=[])
116
+ @rrule.setByPos(new_setpos.to_java(:int))
117
+ self
118
+ end
119
+
120
+ def weeknums
121
+ @rrule.getByWeekNo.to_a
122
+ end
123
+
124
+ # Sets the numbers of week
125
+ #
126
+ # ==== Options
127
+ # +new_weeknums+:: array of weeks (1..52)
128
+ def weeknums=(new_weeknums=[])
129
+ @rrule.setByWeekNo(new_weeknums.to_java(:int))
130
+ self
131
+ end
132
+
133
+ # Gets the day of year
134
+ def ydays
135
+ @rrule.getByYearDay.to_a
136
+ end
137
+
138
+ # Sets the day of year
139
+ #
140
+ # ==== Options
141
+ # +new_ydays+:: array of day of year (1..365)
142
+ def ydays=(new_ydays=[])
143
+ @rrule.setByYearDay(new_ydays.to_java(:int))
144
+ self
145
+ end
146
+
147
+ # Gets the recurrence frequency, return type is defined in
148
+ # "com.google.ical.values.Frequency", such as Frequency::MONTHLY
149
+ def frequency
150
+ @rrule.getFreq
151
+ end
152
+
153
+ # Sets the recurrence frequency
154
+ #
155
+ # ==== Options
156
+ # +freq+:: defined in com.google.ical.values.Frequency, such as
157
+ # Frequency::MONTHLY or Frequency::DAILY
158
+ def frequency=(freq)
159
+ @rrule.setFreq(freq)
160
+ self
161
+ end
162
+
163
+ def interval
164
+ @rrule.getInterval
165
+ end
166
+
167
+ def interval=(new_interval)
168
+ @rrule.setInterval(new_interval)
169
+ self
170
+ end
171
+
172
+ # Returns the type of the recurrence rule such as
173
+ # RRULE, EXRULE, or VEVENT
174
+ def name
175
+ @rrule.getName
176
+ end
177
+
178
+ # Sets the type of the recurrence rule such as
179
+ # RRULE, EXRULE, or VEVENT
180
+ #
181
+ # ==== Options
182
+ # +new_name+:: 'RRULE', 'EXRULE', or 'VEVENT'
183
+ def name=(new_name)
184
+ @rrule.setName(new_name)
185
+ self
186
+ end
187
+
188
+ # Gets the WeekdayNums for the recurrence rule
189
+ # WeekdayNum is an object which specifies the week of year
190
+ # and the day of week
191
+ def days
192
+ @rrule.getByDay.to_a.map do |d|
193
+ WeekdayNum.new(d)
194
+ end
195
+ end
196
+
197
+ # Sets the WeekdayNums for the recurrence rule
198
+ # WeekdayNum is an object which specifies the week of year
199
+ # and the day of week
200
+ #
201
+ # ==== Options
202
+ # +new_days+:: Array of WeekdayNums
203
+ def days=(new_days)
204
+ @rrule.setByDay(new_days.map {|d| d.to_java})
205
+ self
206
+ end
207
+
208
+ # Gets the starting day of the week (0-6)
209
+ def wdaystart
210
+ weekday = @rrule.getWkSt
211
+ Weekday::MAP[weekday]
212
+ end
213
+
214
+ # Sets the starting day of the week (0-6, Mon-Sun, Mo-Su)
215
+ #
216
+ # ==== Options
217
+ # +wday+:: 0-6, 'Mon' - 'Sun', or 'Mo' - 'Su'
218
+ def wdaystart=(wday)
219
+ wday = Weekday::MAP[wday.to_s.downcase]
220
+ @rrule.setWkSt(wday)
221
+ self
222
+ end
223
+
224
+ # Gets the end date
225
+ def until
226
+ d = @rrule.getUntil
227
+ d ? JTime.local(d.year, d.month, d.day, d.hour, d.minute, d.second) : nil
228
+ end
229
+
230
+ # Sets the end date
231
+ #
232
+ # ==== Options
233
+ # +new_date+:: JTime object
234
+ def until=(new_date)
235
+ d = com.google.ical.values.DateTimeValueImpl.new(new_date.year, new_date.month, new_date.day, new_date.hour, new_date.min, new_date.sec)
236
+ @rrule.setUntil(d)
237
+ self
238
+ end
239
+
240
+ # We should consider getting rid of this or implement this using meta-programming
241
+ def method_missing(key, *params)
242
+ @rrule.send(key, *params)
243
+ end
244
+ end
@@ -0,0 +1,501 @@
1
+ require 'rubygems'
2
+ require 'spec'
3
+ require File.dirname(__FILE__) + '/../lib/rfc2445'
4
+
5
+ describe JTime do
6
+ it "should able to initialize a new JTime with the current time" do
7
+ now = Time.now
8
+ time = JTime.new
9
+ time.should_not be_nil
10
+ time.to_java.getYear.should == now.year
11
+ time.to_java.getDayOfMonth.should == now.day
12
+ time.to_java.getMonthOfYear.should == now.month
13
+ time.to_java.getHourOfDay.should == now.hour
14
+ time.to_java.getMinuteOfHour.should == now.min
15
+
16
+ time = JTime.now
17
+ time.should_not be_nil
18
+ time.to_java.getYear.should == now.year
19
+ time.to_java.getDayOfMonth.should == now.day
20
+ time.to_java.getMonthOfYear.should == now.month
21
+ time.to_java.getHourOfDay.should == now.hour
22
+ time.to_java.getMinuteOfHour.should == now.min
23
+ end
24
+
25
+ it "should able to initialize a new JTime with epoch second" do
26
+ now = Time.now
27
+ time = JTime.at(now.to_i)
28
+ time.to_java.getYear.should == now.year
29
+ time.to_java.getDayOfMonth.should == now.day
30
+ time.to_java.getMonthOfYear.should == now.month
31
+ time.to_java.getHourOfDay.should == now.hour
32
+ time.to_java.getMinuteOfHour.should == now.min
33
+ end
34
+
35
+ it "should able to initialize a new JTime with utc" do
36
+ time = JTime.utc(2000, "dec", 25, 20, 15, 1)
37
+ time.to_java.getYear.should == 2000
38
+ time.to_java.getMonthOfYear.should == 12
39
+ time.to_java.getDayOfMonth.should == 25
40
+ time.to_java.getHourOfDay.should == 20
41
+ time.to_java.getMinuteOfHour.should == 15
42
+ end
43
+
44
+ it "should able to initialize a new JTime with local" do
45
+ time = JTime.local(2000, "dec", 25, 20, 15, 1)
46
+ time.to_java.getYear.should == 2000
47
+ time.to_java.getMonthOfYear.should == 12
48
+ time.to_java.getDayOfMonth.should == 25
49
+ time.to_java.getHourOfDay.should == 20
50
+ time.to_java.getMinuteOfHour.should == 15
51
+ end
52
+
53
+ it "should able to initialize a new JTime with DateTimeValue" do
54
+ dtv = com.google.ical.values.DateTimeValueImpl.new(2000, 12, 25, 20, 15, 1)
55
+ time = JTime.from_date_time_value(dtv)
56
+ time.to_java.getYear.should == 2000
57
+ time.to_java.getMonthOfYear.should == 12
58
+ time.to_java.getDayOfMonth.should == 25
59
+ time.to_java.getHourOfDay.should == 20
60
+ time.to_java.getMinuteOfHour.should == 15
61
+ end
62
+
63
+ it "should able to initialize a new JTime object from Ruby Time" do
64
+ now = Time.now
65
+ jtime = JTime.from_time(now)
66
+ jtime.should be_instance_of(JTime)
67
+ jtime.year.should == now.year
68
+ jtime.month.should == now.month
69
+ jtime.day.should == now.day
70
+ jtime.hour.should == now.hour
71
+ jtime.min.should == now.min
72
+ end
73
+
74
+ it "should return a Ruby time object" do
75
+ now = Time.now
76
+ time = JTime.new
77
+ rtime = time.to_time
78
+ rtime.should be_instance_of(Time)
79
+ rtime.year.should == now.year
80
+ rtime.month.should == now.month
81
+ rtime.day.should == now.day
82
+ rtime.hour.should == now.hour
83
+ rtime.min.should == now.min
84
+ end
85
+
86
+ it "should return a Java DateTime object" do
87
+ time = JTime.new
88
+ jtime = time.to_java
89
+ jtime.java_kind_of?(org.joda.time.DateTime).should == true
90
+ end
91
+
92
+ it "should return a date time value object" do
93
+ time = JTime.new
94
+ dtv = time.to_date_time_value
95
+ dtv.java_kind_of?(com.google.ical.values.DateTimeValueImpl).should == true
96
+ end
97
+
98
+ it "should able to return a UTC time" do
99
+ time = JTime.now
100
+ utc_time = time.utc
101
+ ruby_utc_time = time.to_time.utc
102
+ utc_time.to_java.getHourOfDay.should == ruby_utc_time.hour
103
+ utc_time.to_java.getMinuteOfHour.should == ruby_utc_time.min
104
+ end
105
+
106
+ it "should return if dst" do
107
+ time1 = JTime.local(2008, "dec", 25, 20, 15, 1)
108
+ time2 = JTime.local(2008, "jul", 1, 20, 15, 1)
109
+ time1.dst?.should == false
110
+ time2.isdst.should == true
111
+ end
112
+
113
+ it "should able to compare with another JTime" do
114
+ time1 = JTime.new
115
+ time2 = JTime.local(2000, "dec", 25, 20, 15, 1)
116
+ (time1 > time2).should == true
117
+ (time1 < time2).should == false
118
+ (time1 == time1).should == true
119
+ end
120
+
121
+ it "should return the year for time" do
122
+ time = JTime.local(2008, "dec", 25, 20, 15, 1)
123
+ time.year.should == 2008
124
+ end
125
+
126
+ it "should return the month of the year" do
127
+ time = JTime.local(2008, "dec", 25, 20, 15, 1)
128
+ time.month.should == 12
129
+ time.mon.should == 12
130
+ end
131
+
132
+ it "should return the day of the month" do
133
+ time = JTime.local(2008, "dec", 25, 20, 15, 1)
134
+ time.day.should == 25
135
+ end
136
+
137
+ it "should return the hour of the day" do
138
+ time = JTime.local(2008, "dec", 25, 20, 15, 1)
139
+ time.hour.should == 20
140
+ end
141
+
142
+ it "should return the minute of the hour" do
143
+ time = JTime.local(2008, "dec", 25, 20, 15, 1)
144
+ time.min.should == 15
145
+ end
146
+
147
+ it "should return the second of the minute" do
148
+ time = JTime.local(2008, "dec", 25, 20, 15, 1)
149
+ time.day.should == 25
150
+ end
151
+
152
+ it "should return the day of the week"do
153
+ time = JTime.local(2008, "dec", 25, 20, 15, 1)
154
+ time.wday.should == 4
155
+ end
156
+
157
+ it "should return the day of the year"do
158
+ time = JTime.local(2008, "dec", 25, 20, 15, 1)
159
+ time.yday.should == 360
160
+ end
161
+
162
+ it "should return the week number of the year"do
163
+ time = JTime.local(2008, "dec", 25, 20, 15, 1)
164
+ time.week.should == 52
165
+ end
166
+
167
+ it "should return a value of time as a floating-point number of seconds since epoch" do
168
+ time = JTime.new
169
+ rtime = time.to_time
170
+ time.to_f.should == rtime.to_f
171
+ end
172
+
173
+ it "should return a value of time as an integer number of seconds since epoch" do
174
+ time = JTime.new
175
+ rtime = time.to_time
176
+ time.to_i.should == rtime.to_i
177
+ end
178
+
179
+ it "should return a string representing time" do
180
+ time = JTime.new
181
+ time.should respond_to(:to_s)
182
+ end
183
+
184
+ it "should return the name of the time zone" do
185
+ # Notice that it is different than the Ruby Time object, it returns the real ID 'America/Los_Angeles' instead of "PST"
186
+ time = JTime.new.utc
187
+ time.should respond_to(:zone)
188
+ time.zone.should == 'UTC'
189
+ end
190
+ end
191
+
192
+ describe RRule do
193
+ before(:each) do
194
+ @rrule = RRule.new
195
+ end
196
+
197
+ it "should initialize a RRule object with ical string" do
198
+ ical_string = "RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13;COUNT=13"
199
+ rrule = RRule.new(ical_string)
200
+ rrule.should_not be_nil
201
+ end
202
+
203
+ it "should return an ical string" do
204
+ ical_string = "RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13;COUNT=13"
205
+ rrule = RRule.new(ical_string)
206
+ (rrule.to_ical =~ /FREQ=MONTHLY/).should_not be_nil
207
+ (rrule.to_ical =~ /BYDAY=FR/).should_not be_nil
208
+ (rrule.to_ical =~ /BYMONTHDAY=13/).should_not be_nil
209
+ (rrule.to_ical =~ /COUNT=13/).should_not be_nil
210
+ end
211
+
212
+ it "should return extra parameters" do
213
+ ical_string = "RRULE;X-FOO=BAR:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13;COUNT=13;"
214
+ rrule = RRule.new(ical_string)
215
+ ext_params = rrule.ext_params
216
+ ext_params['X-FOO'].should == 'BAR'
217
+ end
218
+
219
+ it "should set and get the count" do
220
+ @rrule.count = 13
221
+ @rrule.count.should == 13
222
+ end
223
+
224
+ it "should set and get the days" do
225
+ wday = WeekdayNum.new(5, 'Fri')
226
+ @rrule.days = [wday]
227
+ (@rrule.days.first == wday).should == true
228
+ end
229
+
230
+ it "should set and get the hours" do
231
+ @rrule.hours = [1, 13]
232
+ @rrule.hours.include?(1).should == true
233
+ @rrule.hours.include?(13).should == true
234
+ end
235
+
236
+ it "should set and get the minutes" do
237
+ @rrule.minutes = [1, 13]
238
+ @rrule.minutes.include?(1).should == true
239
+ @rrule.minutes.include?(13).should == true
240
+ end
241
+
242
+ it "should set and get the monthdays" do
243
+ @rrule.mdays = [1, 13]
244
+ @rrule.mdays.include?(1).should == true
245
+ @rrule.mdays.include?(13).should == true
246
+ end
247
+
248
+ it "should set and get the seconds" do
249
+ @rrule.seconds = [1, 13]
250
+ @rrule.seconds.include?(1).should == true
251
+ @rrule.seconds.include?(13).should == true
252
+ end
253
+
254
+ it "should set and get the week numbers" do
255
+ @rrule.weeknums = [1, 13]
256
+ @rrule.weeknums.include?(1).should == true
257
+ @rrule.weeknums.include?(13).should == true
258
+ end
259
+
260
+ it "should set and get the year days" do
261
+ @rrule.ydays = [1, 360]
262
+ @rrule.ydays.include?(1).should == true
263
+ @rrule.ydays.include?(360).should == true
264
+ end
265
+
266
+ it "should set and get the frequency" do
267
+ @rrule.frequency = Frequency::MONTHLY
268
+ @rrule.frequency.should == Frequency::MONTHLY
269
+ end
270
+
271
+ it "should set and get the starting weekday" do
272
+ @rrule.wdaystart = 'Fri'
273
+ @rrule.wdaystart.should == 5
274
+ @rrule.wdaystart = 3
275
+ @rrule.wdaystart.should == 3
276
+ end
277
+
278
+ it "should set and get the interval" do
279
+ @rrule.interval = 10
280
+ @rrule.interval.should == 10
281
+ end
282
+
283
+ it "should set and get the object name, such as RRULE, EXRULE, VEVENT" do
284
+ @rrule.name = RRule::EXRULE
285
+ @rrule.name.should == RRule::EXRULE
286
+ end
287
+
288
+ it "should set and get the until date" do
289
+ now = JTime.new
290
+ @rrule.until = now
291
+ @rrule.until.year.should == now.year
292
+ @rrule.until.month.should == now.month
293
+ @rrule.until.day.should == now.day
294
+ @rrule.until.hour.should == now.hour
295
+ @rrule.until.min.should == now.min
296
+ @rrule.until.sec.should == now.sec
297
+ end
298
+ end
299
+
300
+ describe RDateList do
301
+ before(:each) do
302
+ @rdatelist = RDateList.new
303
+ end
304
+
305
+ it "should initialize a RDateList object with no params" do
306
+ @rdatelist.should_not be_nil
307
+ end
308
+
309
+ it "should initialize a RDatelist object with a timezone" do
310
+ rdatelist = RDateList.new('UTC')
311
+ @rdatelist.should_not be_nil
312
+ end
313
+
314
+ it "should initialize a RDateList object with ical string" do
315
+ ical_string = "RDATE:19960402T010000,19960403T010000,19960404T010000"
316
+ rdatelist = RDateList.new(nil, ical_string)
317
+ rdatelist.should_not be_nil
318
+ end
319
+
320
+ it "should return an ical string" do
321
+ ical_string = "RDATE:19960402T010000,19960403T010000,19960404T010000"
322
+ rdatelist = RDateList.new(nil, ical_string)
323
+ (rdatelist.to_ical =~ /TZID=/).should_not be_nil
324
+ (rdatelist.to_ical =~ /VALUE=DATE-TIME:/).should_not be_nil
325
+ (rdatelist.to_ical =~ /19960402/).should_not be_nil
326
+ (rdatelist.to_ical =~ /19960403/).should_not be_nil
327
+ (rdatelist.to_ical =~ /19960404/).should_not be_nil
328
+ end
329
+
330
+ it "should return extra parameters" do
331
+ ical_string = "RDATE;X-FOO=BAR:19960402T010000,19960403T010000,19960404T010000"
332
+ rdatelist = RDateList.new(nil, ical_string)
333
+ ext_params = rdatelist.ext_params
334
+ ext_params['X-FOO'].should == 'BAR'
335
+ end
336
+
337
+ it "should set and get the object name, such as RRULE, EXRULE, VEVENT" do
338
+ @rdatelist.name = RRule::EXRULE
339
+ @rdatelist.name.should == RRule::EXRULE
340
+ end
341
+
342
+ it "should set and get timezone" do
343
+ @rdatelist.zone = 'UTC'
344
+ @rdatelist.zone.should == 'UTC'
345
+ end
346
+
347
+ it "should set array of utc dates and get array of utc dates" do
348
+ utc_date = JTime.utc(2008, 12, 25)
349
+ @rdatelist.utc_dates = [utc_date]
350
+ @rdatelist.utc_dates.first.year.should == 2008
351
+ @rdatelist.utc_dates.first.month.should == 12
352
+ @rdatelist.utc_dates.first.day.should == 25
353
+ end
354
+ end
355
+
356
+ describe ICalParseUtil do
357
+ it "should parse an ical string and timezone to a date time value" do
358
+ dtv = ICalParseUtil.parse_date_value('20090327T180000', 'America/Los_Angeles')
359
+ dtv.java_kind_of?(com.google.ical.values.DateTimeValueImpl).should == true
360
+ dtv.hour.should == 1
361
+ dtv.day.should == 28
362
+ end
363
+
364
+ it "should return nil if passing nil to parse_date_value" do
365
+ dtv = ICalParseUtil.parse_date_value(nil)
366
+ dtv.should be_nil
367
+ end
368
+
369
+ it "should parse an ical string and timezone to a JTime object" do
370
+ jtime = ICalParseUtil.parse_jtime('20090327T180000', 'America/Los_Angeles')
371
+ jtime.should be_instance_of(JTime)
372
+ jtime.hour.should == 1
373
+ jtime.day.should == 28
374
+ end
375
+
376
+ it "should return nil if passing nil to parse_jtime" do
377
+ jtime = ICalParseUtil.parse_jtime(nil)
378
+ jtime.should be_nil
379
+ end
380
+
381
+ it "should parse a recurrence block" do
382
+ string = <<-end_src
383
+ DTSTART;TZID=America/Los_Angeles:20090320T170000
384
+ DTEND;TZID=America/Los_Angeles:20090320T180000
385
+ RRULE:FREQ=WEEKLY;BYDAY=FR;WKST=SU
386
+ EXRULE:FREQ=MONTHLY;BYDAY=1FR
387
+ RDATE;TZID=America/Los_Angeles:20090321T170000
388
+ BEGIN:VTIMEZONE
389
+ TZID:America/Los_Angeles
390
+ X-LIC-LOCATION:America/Los_Angeles
391
+ BEGIN:DAYLIGHT
392
+ TZOFFSETFROM:-0800
393
+ TZOFFSETTO:-0700
394
+ TZNAME:PDT
395
+ DTSTART:19700308T020000
396
+ RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
397
+ END:DAYLIGHT
398
+ BEGIN:STANDARD
399
+ TZOFFSETFROM:-0700
400
+ TZOFFSETTO:-0800
401
+ TZNAME:PST
402
+ DTSTART:19701101T020000
403
+ RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
404
+ END:STANDARD
405
+ END:VTIMEZONE
406
+ end_src
407
+
408
+ r = ICalParseUtil.parse_recurrence(string)
409
+ r[:dtstart].should == "DTSTART;TZID=America/Los_Angeles:20090320T170000"
410
+ r[:dtend].should == "DTEND;TZID=America/Los_Angeles:20090320T180000"
411
+ r[:rrule].should == "RRULE:FREQ=WEEKLY;BYDAY=FR;WKST=SU"
412
+ r[:exrule].should == "EXRULE:FREQ=MONTHLY;BYDAY=1FR"
413
+ r[:rdate].should == "RDATE;TZID=America/Los_Angeles:20090321T170000"
414
+ r[:exdate].should == nil
415
+ end
416
+
417
+ it "should parse datetime into JTime" do
418
+ jtime1 = ICalParseUtil.parse_datetime('DTSTART;TZID=America/Los_Angeles:20090320T170000')
419
+ jtime1.should be_instance_of(JTime)
420
+ jtime1.hour.should == 0
421
+
422
+ jtime2 = ICalParseUtil.parse_datetime('DTEND;TZID=America/Los_Angeles:20090320T170000')
423
+ jtime2.should be_instance_of(JTime)
424
+ jtime2.hour.should == 0
425
+
426
+ jtime3 = ICalParseUtil.parse_datetime(nil)
427
+ jtime3.should be_nil
428
+ end
429
+ end
430
+
431
+ describe RecurrenceTime do
432
+ before(:each) do
433
+ @ical_string = "RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13;COUNT=13"
434
+ @start_date = JTime.local(2001, 4, 13)
435
+ @rtime = RecurrenceTime.new(@ical_string, @start_date)
436
+ end
437
+
438
+ it "should be initialized by RRule object" do
439
+ rrule = RRule.new(@ical_string)
440
+ rtime = RecurrenceTime.new(rrule, @start_date)
441
+ rtime.should be_instance_of(RecurrenceTime)
442
+ end
443
+
444
+ it "should be initialized by an array of RRules" do
445
+ rrule1 = RRule.new(@ical_string)
446
+ # The first date is excluded
447
+ rrule2 = RRule.new("EXRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13;COUNT=1")
448
+ rtime = RecurrenceTime.new([rrule1, rrule2], @start_date)
449
+ rtime.should be_instance_of(RecurrenceTime)
450
+ rtime.next.should > @start_date
451
+ end
452
+
453
+ it "should initialized by an array of RRules and RDateLists" do
454
+ rrule = RRule.new(@ical_string)
455
+ rdatelist = RDateList.new
456
+ rdatelist.utc_dates = [JTime.utc(2001, 4, 14)]
457
+ rtime = RecurrenceTime.new([rdatelist, rrule], @start_date)
458
+ rtime.should be_instance_of(RecurrenceTime)
459
+ rtime.next
460
+ first_next = rtime.next
461
+ first_next.mon.should == 4
462
+ first_next.day.should == 14
463
+ first_next.year.should == 2001
464
+ end
465
+
466
+ it "should able to generate a JTime by invoking next" do
467
+ nexttime = @rtime.next
468
+ nexttime.should be_instance_of(JTime)
469
+ (nexttime <=> @start_date).should == 0
470
+ end
471
+
472
+ it "should able to advance to a specific date" do
473
+ # It skips 2 dates 4/13 and 7/13
474
+ @rtime.advance_to(JTime.utc(2001, 7, 15))
475
+ third_next = @rtime.next
476
+ third_next.mon.should == 9
477
+ third_next.day.should == 13
478
+ third_next.year.should == 2002
479
+ end
480
+
481
+ it "should return true if there is more time for the recurrence time" do
482
+ 13.times do
483
+ @rtime.has_next?.should == true
484
+ @rtime.next
485
+ end
486
+ @rtime.has_next?.should == false
487
+ end
488
+
489
+ it "should return the java iterator" do
490
+ @rtime.to_java.java_kind_of?(com.google.ical.compat.jodatime.DateTimeIterator).should == true
491
+ end
492
+
493
+ it "should able to iterate" do
494
+ i = 0
495
+ @rtime.each do |t|
496
+ i += 1
497
+ t.should be_instance_of(JTime)
498
+ end
499
+ i.should == 13
500
+ end
501
+ end
metadata ADDED
@@ -0,0 +1,63 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jerryluk-jruby-rfc2445
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Jerry Luk
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-03-24 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: A JRuby implementation of RFC 2445 (ical) recurrence rule
17
+ email: jerryluk@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - README
26
+ - MIT-LICENSE
27
+ - lib/ical_parse_util.jar
28
+ - lib/jtime.rb
29
+ - lib/rdate_list.rb
30
+ - lib/recurrence_time.jar
31
+ - lib/rfc2445.rb
32
+ - lib/rrule.rb
33
+ - weekday.rb
34
+ - weekday_num.rb
35
+ - spec/rfc2445_spec.rb
36
+ has_rdoc: false
37
+ homepage: http://www.linkedin.com/in/jerryluk
38
+ post_install_message:
39
+ rdoc_options: []
40
+
41
+ require_paths:
42
+ - lib
43
+ required_ruby_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: "0"
48
+ version:
49
+ required_rubygems_version: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: "0"
54
+ version:
55
+ requirements: []
56
+
57
+ rubyforge_project:
58
+ rubygems_version: 1.2.0
59
+ signing_key:
60
+ specification_version: 2
61
+ summary: A JRuby implementation of RFC 2445 (ical) recurrence rule
62
+ test_files:
63
+ - spec/rfc2445_spec.rb