Skip to content
Browse files

ready to merge

  • Loading branch information...
1 parent a891aa4 commit 31fd75f725271c718ef752e18d1038c9f2fee6b7 @rubyredrick committed
View
1 .gitignore
@@ -1,6 +1,7 @@
coverage/
tmp/
pkg/
+profiles/
doc/
\.DS_Store
.ackrc
View
3 History.txt
@@ -1,3 +1,6 @@
+=== 0.5.3 - 1 June, 2009
+ * Improved performance of time zone enumeration, TimeZonePeriod now caches occurrences
+ * Added a profiling directory which contains ruby programs which benchmark and/or profile performance
=== 0.5.2
* Fixed http://rick_denatale.lighthouseapp.com/projects/30941/tickets/11
Export folding is not UTF-8 Safe
View
4 Manifest.txt
@@ -89,6 +89,10 @@ lib/ri_cal/property_value/text.rb
lib/ri_cal/property_value/uri.rb
lib/ri_cal/property_value/utc_offset.rb
lib/ri_cal/required_timezones.rb
+profiling/ical_files/profile3.ics
+profiling/profile1.rb
+profiling/profile2.rb
+profiling/profile3.rb
ri_cal.gemspec
sample_ical_files/from_ical_dot_app/test1.ics
script/console
View
5 Rakefile
@@ -6,7 +6,7 @@ require File.dirname(__FILE__) + '/lib/ri_cal'
# Generate all the Rake tasks
# Run 'rake -T' to see list of generated tasks (from gem root directory)
-$hoe = Hoe.new('ri-cal', RiCal::VERSION) do |p|
+$hoe = Hoe.new('ri_cal', RiCal::VERSION) do |p|
p.developer('author=Rick DeNatale', 'rick.denatale@gmail.com')
p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
# p.post_install_message = 'PostInstall.txt' # TODO remove if post-install message not required
@@ -15,7 +15,8 @@ $hoe = Hoe.new('ri-cal', RiCal::VERSION) do |p|
# ['tzinfo','>= 2.0.2'],
# ]
p.extra_dev_deps = [
- ['newgem', ">= #{::Newgem::VERSION}"]
+ ['newgem', ">= #{::Newgem::VERSION}"],
+ 'ruby-prof'
]
p.clean_globs |= %w[**/.DS_Store tmp *.log]
View
2 config/website.yml
@@ -0,0 +1,2 @@
+host: rubyredrick@rubyforge.org
+remote_dir: /var/www/gforge-projects/ri-cal
View
2 lib/ri_cal.rb
@@ -14,7 +14,7 @@ module RiCal
autoload :OccurrenceEnumerator, "#{my_dir}/ri_cal/occurrence_enumerator.rb"
# :stopdoc:
- VERSION = '0.5.2'
+ VERSION = '0.5.3'
LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
View
16 lib/ri_cal/component/timezone/timezone_period.rb
@@ -55,13 +55,17 @@ def fill_cache(local_time)
end
def last_before_local(local_time) #:nodoc:
- fill_cache(local_time)
- cand_occurrence = nil
- occurrence_cache.each do |occurrence|
- return cand_occurrence if occurrence.dtstart_property > local_time
- cand_occurrence = occurrence
+ if recurs?
+ fill_cache(local_time)
+ cand_occurrence = nil
+ occurrence_cache.each do |occurrence|
+ return cand_occurrence if occurrence.dtstart_property > local_time
+ cand_occurrence = occurrence
+ end
+ return cand_occurrence
+ else
+ return self
end
- return cand_occurrence
end
def enumeration_instance
View
4 lib/ri_cal/occurrence_enumerator.rb
@@ -232,6 +232,10 @@ def set_occurrence_properties!(occurrence) # :nodoc:
def recurrence(occurrence) # :nodoc:
result = self.dup.set_occurrence_properties!(occurrence)
end
+
+ def recurs?
+ @rrule_property && @rrule_property.length > 0 || @rdate_property && @rdate_property.length > 0
+ end
end
end
View
3,171 profiling/ical_files/profile3.ics
3,171 additions, 0 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
View
97 profiling/profile1.rb
@@ -0,0 +1,97 @@
+require File.expand_path(File.join(File.dirname(__FILE__), %w[.. lib ri_cal]))
+require 'rubygems'
+
+cals = RiCal.parse_string <<-END_OF_DATA
+BEGIN:VCALENDAR
+METHOD:PUBLISH
+X-WR-TIMEZONE:America/New_York
+PRODID:-//Apple Inc.//iCal 3.0//EN
+CALSCALE:GREGORIAN
+X-WR-CALNAME:Test
+VERSION:2.0
+X-WR-RELCALID:58DB0663-196B-4B6B-A05A-A53049661280
+X-APPLE-CALENDAR-COLOR:#0252D4
+BEGIN:VTIMEZONE
+TZID:Europe/Paris
+BEGIN:DAYLIGHT
+TZOFFSETFROM:+0100
+TZOFFSETTO:+0200
+DTSTART:19810329T020000
+RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU
+TZNAME:CEST
+END:DAYLIGHT
+BEGIN:STANDARD
+TZOFFSETFROM:+0200
+TZOFFSETTO:+0100
+DTSTART:19961027T030000
+RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU
+TZNAME:CET
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VTIMEZONE
+TZID:US/Eastern
+BEGIN:DAYLIGHT
+TZOFFSETFROM:-0500
+TZOFFSETTO:-0400
+DTSTART:20070311T020000
+RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
+TZNAME:EDT
+END:DAYLIGHT
+BEGIN:STANDARD
+TZOFFSETFROM:-0400
+TZOFFSETTO:-0500
+DTSTART:20071104T020000
+RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
+TZNAME:EST
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+SEQUENCE:3
+TRANSP:OPAQUE
+UID:AC2EFB19-A8A8-49EF-929F-CA0975374ED6
+DTSTART:20090501T000000Z
+DTSTAMP:20090501T174405Z
+SUMMARY:UTC Event
+CREATED:20090501T174347Z
+DTEND:20090501T010000Z
+END:VEVENT
+BEGIN:VEVENT
+SEQUENCE:2
+TRANSP:OPAQUE
+UID:A5517A09-C53E-4E1F-A642-EA47680BF2B6
+DTSTART;TZID=US/Eastern:20090430T140000
+DTSTAMP:20090501T174428Z
+SUMMARY:Eastern Event
+CREATED:20090501T174415Z
+DTEND;TZID=US/Eastern:20090430T150000
+END:VEVENT
+BEGIN:VEVENT
+SEQUENCE:3
+TRANSP:OPAQUE
+UID:B5024763-9197-4A60-A96E-D8D59D578BB2
+DTSTART;TZID=Europe/Paris:20090430T140000
+DTSTAMP:20090501T174509Z
+SUMMARY:Paris Event
+CREATED:20090501T174439Z
+DTEND;TZID=Europe/Paris:20090430T150000
+END:VEVENT
+END:VCALENDAR
+END_OF_DATA
+
+cal = cals.first
+event = cal.events.find {|event| event.summary == "Paris Event"}
+date_time = event.dtstart_property
+require 'ruby-prof'
+result = RubyProf.profile do
+ date_time.in_time_zone("US/Eastern")
+end
+
+printer = RubyProf::GraphHtmlPrinter.new(result)
+profile_file = File.expand_path(File.join(File.dirname(__FILE__), %w[.. profiles profile1.html]))
+File.open(profile_file, "w") do |pf|
+ printer.print(pf)
+end
+
+system("open #{profile_file}")
+printer = RubyProf::FlatPrinter.new(result)
+printer.print(STDOUT, 0)
View
65 profiling/profile2.rb
@@ -0,0 +1,65 @@
+require File.expand_path(File.join(File.dirname(__FILE__), %w[.. lib ri_cal]))
+require 'rubygems'
+
+cals = RiCal.parse_string <<-ENDCAL
+BEGIN:VCALENDAR
+METHOD:PUBLISH
+PRODID:-//Apple Inc.//iCal 3.0//EN
+CALSCALE:GREGORIAN
+X-WR-CALNAME:Utah Cycling
+X-WR-RELCALID:BF579011-36BF-49C6-8C7D-E96F03DE8055
+VERSION:2.0
+X-WR-TIMEZONE:US/Mountain
+BEGIN:VTIMEZONE
+TZID:US/Mountain
+BEGIN:DAYLIGHT
+TZOFFSETFROM:-0700
+TZOFFSETTO:-0600
+DTSTART:20070311T020000
+RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
+TZNAME:MDT
+END:DAYLIGHT
+BEGIN:STANDARD
+TZOFFSETFROM:-0600
+TZOFFSETTO:-0700
+DTSTART:20071104T020000
+RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
+TZNAME:MST
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+SEQUENCE:11
+TRANSP:OPAQUE
+UID:15208112-E0FA-4A7C-954C-CFDF19D1B0E7
+DTSTART;TZID=US/Mountain:20090114T163000
+DTSTAMP:20090107T024340Z
+SUMMARY:Wild Rose XC/Skate Training Series
+EXDATE;TZID=US/Mountain:20090114T163000
+EXDATE;TZID=US/Mountain:20090128T163000
+EXDATE;TZID=US/Mountain:20090121T163000
+EXDATE;TZID=US/Mountain:20090211T163000
+EXDATE;TZID=US/Mountain:20090204T163000
+EXDATE;TZID=US/Mountain:20090218T163000
+CREATED:20090107T024012Z
+DTEND;TZID=US/Mountain:20090114T180000
+LOCATION:Mountain Dell Golf Course
+RRULE:FREQ=WEEKLY;INTERVAL=1;UNTIL=20090219T065959Z
+END:VEVENT
+END:VCALENDAR
+ENDCAL
+event = cals.first.events.first
+
+require 'ruby-prof'
+result = RubyProf.profile do
+ event.occurrences
+end
+
+printer = RubyProf::GraphHtmlPrinter.new(result)
+profile_file = File.expand_path(File.join(File.dirname(__FILE__), %w[.. profiles profile2.html]))
+File.open(profile_file, "w") do |pf|
+ printer.print(pf)
+end
+
+# system("open #{profile_file}")
+printer = RubyProf::FlatPrinter.new(result)
+printer.print(STDOUT, 0)
View
31 profiling/profile3.rb
@@ -0,0 +1,31 @@
+require File.expand_path(File.join(File.dirname(__FILE__), %w[.. lib ri_cal]))
+require 'rubygems'
+require "benchmark"
+
+calendar_file = File.open(File.join(File.dirname(__FILE__), *%w[ical_files profile3.ics]), 'r')
+calendar = RiCal.parse(calendar_file).first
+cutoff = Date.parse("20100531")
+def code_to_profile(calendar, cutoff, out=STDOUT)
+ calendar.events.each do |event|
+ event.occurrences(:before => cutoff).each do |instance|
+ out.puts "Event #{instance.uid.slice(0..5)}, starting #{instance.dtstart}, ending #{instance.dtend}"
+ end
+ end
+end
+
+devnul = Object.new
+def devnul.puts(string)
+end
+
+Benchmark.bmbm do |results|
+ results.report("Benchmark:") { code_to_profile(calendar, cutoff, devnul) }
+end
+
+require 'ruby-prof'
+
+result = RubyProf.profile do
+ code_to_profile(calendar, cutoff)
+end
+
+printer = RubyProf::FlatPrinter.new(result)
+printer.print(STDOUT, 0)
View
172 spec/ri_cal/component/timezone_spec.rb
@@ -11,27 +11,51 @@
end
end
+ context "for a Timezone with no DST periods" do
+ before(:each) do
+ @it = RiCal.parse_string rectify_ical <<-'ENDCAL'
+ BEGIN:VTIMEZONE
+ TZID:Australia/Brisbane
+ X-LIC-LOCATION:Australia/Brisbane
+ BEGIN:STANDARD
+ TZOFFSETFROM:+1000
+ TZOFFSETTO:+1000
+ TZNAME:EST
+ DTSTART:19700101T000000
+ END:STANDARD
+ END:VTIMEZONE
+ ENDCAL
+ @it = @it.first
+ end
+
+ context ".periods_for_local" do
+ it "should return a single period" do
+ @it.periods_for_local(DateTime.parse("20090530T100000")).length.should == 1
+ end
+ end
+ end
+
context "from an iCal.app calendar for America/New_York starting March 11 2007" do
before(:each) do
- @it = RiCal.parse_string <<TZEND
-BEGIN:VTIMEZONE
-TZID:US/Eastern
-BEGIN:DAYLIGHT
-TZOFFSETFROM:-0500
-TZOFFSETTO:-0400
-DTSTART:20070311T020000
-RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
-TZNAME:EDT
-END:DAYLIGHT
-BEGIN:STANDARD
-TZOFFSETFROM:-0400
-TZOFFSETTO:-0500
-DTSTART:20071104T020000
-RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
-TZNAME:EST
-END:STANDARD
-END:VTIMEZONE
-TZEND
+ @it = RiCal.parse_string rectify_ical <<-'ENDCAL'
+ BEGIN:VTIMEZONE
+ TZID:US/Eastern
+ BEGIN:DAYLIGHT
+ TZOFFSETFROM:-0500
+ TZOFFSETTO:-0400
+ DTSTART:20070311T020000
+ RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
+ TZNAME:EDT
+ END:DAYLIGHT
+ BEGIN:STANDARD
+ TZOFFSETFROM:-0400
+ TZOFFSETTO:-0500
+ DTSTART:20071104T020000
+ RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
+ TZNAME:EST
+ END:STANDARD
+ END:VTIMEZONE
+ ENDCAL
@it = @it.first
end
@@ -69,7 +93,7 @@
it "should return a dst period if the dst parameter is true" do
@it.period_for_local(DateTime.parse("Nov 1, 2009 2:00"), true).should be_dst
end
-
+
it "should return a std period if the dst parameter is false" do
@it.period_for_local(DateTime.parse("Nov 1, 2009 2:00"), false).should_not be_dst
end
@@ -78,27 +102,21 @@
context "with a block" do
it "should return a period if the block returns a TimezonePeriod" do
mock_period = ::RiCal::Component::Timezone::TimezonePeriod.new(nil)
- @it.period_for_local(DateTime.parse("Nov 1, 2009 2:00")) { |results|
- mock_period
- }.should == mock_period
+ @it.period_for_local(DateTime.parse("Nov 1, 2009 2:00")) { |results| mock_period}.should == mock_period
end
-
+
it "should return a period if the block returns a single element array" do
mock_period = :foo
- @it.period_for_local(DateTime.parse("Nov 1, 2009 2:00")) { |results|
- [ mock_period]
- }.should == mock_period
+ @it.period_for_local(DateTime.parse("Nov 1, 2009 2:00")) { |results| [ mock_period]}.should == mock_period
end
-
+
it "should raise TZInfo::PeriodNotFound if the block returns a multi-element array" do
lambda {
- @it.period_for_local(DateTime.parse("Mar 8, 2009 2:30")) {|results| [1,2]}
- }.should raise_error(TZInfo::PeriodNotFound)
+ @it.period_for_local(DateTime.parse("Mar 8, 2009 2:30")) {|results| [1,2]}}.should raise_error(TZInfo::PeriodNotFound)
+ end
end
-
end
end
- end
context ".periods_for_local" do
context "for the date on which DST begins springing ahead e.g. Mar 8, 2009" do
@@ -150,66 +168,66 @@
end
end
end
-
+
context "Bug report from paulsm" do
- before(:each) do
- cals = RiCal.parse_string <<ENDCAL
-BEGIN:VCALENDAR
-X-WR-TIMEZONE:America/New_York
-PRODID:-//Apple Inc.//iCal 3.0//EN
-CALSCALE:GREGORIAN
-X-WR-CALNAME:test
-VERSION:2.0
-X-WR-RELCALID:1884C7F8-BC8E-457F-94AC-297871967D5E
-X-APPLE-CALENDAR-COLOR:#2CA10B
-BEGIN:VTIMEZONE
-TZID:US/Eastern
-BEGIN:DAYLIGHT
-TZOFFSETFROM:-0500
-TZOFFSETTO:-0400
-DTSTART:20070311T020000
-RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
-TZNAME:EDT
-END:DAYLIGHT
-BEGIN:STANDARD
-TZOFFSETFROM:-0400
-TZOFFSETTO:-0500
-DTSTART:20071104T020000
-RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
-TZNAME:EST
-END:STANDARD
-END:VTIMEZONE
-BEGIN:VEVENT
-SEQUENCE:5
-TRANSP:OPAQUE
-UID:00481E53-9258-4EA7-9F8D-947D3041A3F2
-DTSTART;TZID=US/Eastern:20090224T090000
-DTSTAMP:20090225T000908Z
-SUMMARY:Test Event
-CREATED:20090225T000839Z
-DTEND;TZID=US/Eastern:20090224T100000
-RRULE:FREQ=DAILY;INTERVAL=1;UNTIL=20090228T045959Z
-END:VEVENT
-END:VCALENDAR
-ENDCAL
+ before(:each) do
+ cals = RiCal.parse_string rectify_ical <<-'ENDCAL'
+ BEGIN:VCALENDAR
+ X-WR-TIMEZONE:America/New_York
+ PRODID:-//Apple Inc.//iCal 3.0//EN
+ CALSCALE:GREGORIAN
+ X-WR-CALNAME:test
+ VERSION:2.0
+ X-WR-RELCALID:1884C7F8-BC8E-457F-94AC-297871967D5E
+ X-APPLE-CALENDAR-COLOR:#2CA10B
+ BEGIN:VTIMEZONE
+ TZID:US/Eastern
+ BEGIN:DAYLIGHT
+ TZOFFSETFROM:-0500
+ TZOFFSETTO:-0400
+ DTSTART:20070311T020000
+ RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
+ TZNAME:EDT
+ END:DAYLIGHT
+ BEGIN:STANDARD
+ TZOFFSETFROM:-0400
+ TZOFFSETTO:-0500
+ DTSTART:20071104T020000
+ RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
+ TZNAME:EST
+ END:STANDARD
+ END:VTIMEZONE
+ BEGIN:VEVENT
+ SEQUENCE:5
+ TRANSP:OPAQUE
+ UID:00481E53-9258-4EA7-9F8D-947D3041A3F2
+ DTSTART;TZID=US/Eastern:20090224T090000
+ DTSTAMP:20090225T000908Z
+ SUMMARY:Test Event
+ CREATED:20090225T000839Z
+ DTEND;TZID=US/Eastern:20090224T100000
+ RRULE:FREQ=DAILY;INTERVAL=1;UNTIL=20090228T045959Z
+ END:VEVENT
+ END:VCALENDAR
+ ENDCAL
@event = cals.first.events.first
end
-
+
context "the events dtstart" do
it "should be the right DateTime" do
@event.dtstart.should == DateTime.civil(2009, 2, 24, 9, 0, 0, Rational(-5, 24))
end
-
+
it "should have the right tzid" do
@event.dtstart.tzid.should == "US/Eastern"
end
end
-
+
context "the events dtend" do
it "should be the right DateTime" do
@event.dtend.should == DateTime.civil(2009, 2, 24, 10, 0, 0, Rational(-5, 24))
end
-
+
it "should have the right tzid" do
@event.dtend.tzid.should == "US/Eastern"
end

0 comments on commit 31fd75f

Please sign in to comment.
Something went wrong with that request. Please try again.