icalendar 1.4.3 → 1.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8a1a061b2cdba8b3b5058a77d5a3f6c06a795c34
4
- data.tar.gz: a404fedca32cb195c8f939b42e384114a227611d
3
+ metadata.gz: 3bb514e630455e28b49f977bb6c316dc470cb98f
4
+ data.tar.gz: 02953a2e8e74af0680d02e6ae889dd30fee8cedb
5
5
  SHA512:
6
- metadata.gz: 825777c1bd1bd283931d9ed8b81305ba0bfa2ffc6114054452b2ea47f300114d3c1704cf53a15a21abbb81ba5b2ff5190c14797aece6d0f56de6288194f45967
7
- data.tar.gz: 6f568404d5a15e36d83294552076135504b964516780f856aa60e3d7a3ba40f6a93dde4bd1e95c658d8c3cb00818d2ae761e3aae21a0d7d6b11073ddb1c82fbb
6
+ metadata.gz: 107461d20bf35d2f4df715e52605126a55a532c8dabb51c6b35eda16828fe50220a073b7c76b09dda00165c34745414b5172206a422aeeee4e9fc2ba7df46cef
7
+ data.tar.gz: 66694d2dd3cc7f70d3ddcbd81d6682fca411dffe57bd76afacc015f6c1328b0f6f67ffed512c42b08d500644d8d8e514502c2c438e32644b43c66f9c2976bde9
data/.gitignore CHANGED
@@ -3,3 +3,5 @@
3
3
  .ruby-gemset
4
4
  Gemfile.lock
5
5
  pkg/
6
+ .bundle
7
+ vendor/
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0.0
4
+ - 1.9.3
5
+ script: bundle exec rake test
data/History.txt CHANGED
@@ -1,3 +1,10 @@
1
+ === 1.4.4 2013-11-05
2
+ * Allow user to handle TZInfo::AmbiguousTime error - David Bradford
3
+ * Better handling of multiple exdate and rdate values
4
+
5
+ === 1.4.3 2013-09-18
6
+ * Fix concatenation of multiple BYWEEK or BYMONTH recurrence rules
7
+
1
8
  === 1.4.2 2013-09-11
2
9
  * Double Quote parameter values that contain forbidden characters
3
10
  * Update Component#respond_to? to match Ruby 2.0 - Keith Marcum
data/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  iCalendar -- Internet calendaring, Ruby style
2
2
  ===
3
3
 
4
+ [![Build Status](https://travis-ci.org/icalendar/icalendar.png)](https://travis-ci.org/icalendar/icalendar)
5
+
4
6
  <http://github.com/icalendar/icalendar>
5
7
 
6
8
  DESCRIPTION
data/icalendar.gemspec CHANGED
@@ -25,5 +25,6 @@ Gem::Specification.new do |s|
25
25
  s.add_development_dependency 'rake', '~> 10.0'
26
26
  s.add_development_dependency 'bundler', '~> 1.3'
27
27
  s.add_development_dependency 'tzinfo', '~> 0.3'
28
+ s.add_development_dependency 'timecop', '~> 0.6.3'
28
29
  end
29
30
 
@@ -11,7 +11,7 @@ require 'logger'
11
11
 
12
12
  module Icalendar #:nodoc:
13
13
 
14
- VERSION = '1.4.3'
14
+ VERSION = '1.4.4'
15
15
 
16
16
  # A simple error class to differentiate iCalendar library exceptions
17
17
  # from ruby language exceptions or others.
@@ -314,16 +314,24 @@ module Icalendar
314
314
  # Getter for whole array
315
315
  unless instance_methods.include? plural
316
316
  code = <<-code
317
- def #{plural}(a = nil)
317
+ def #{plural}(a = nil, params = nil)
318
318
  if a.nil?
319
319
  @properties["#{property}"] || []
320
320
  else
321
- self.#{plural}=(a)
321
+ self.#{plural}=(a).tap do |val|
322
+ unless params.nil?
323
+ unless val.respond_to?(:ical_params)
324
+ val.class.class_eval { attr_accessor :ical_params }
325
+ end
326
+ val.ical_params = params
327
+ end
328
+ end
322
329
  end
323
330
  end
324
331
  code
325
332
 
326
333
  class_eval code, "component.rb", 186
334
+ alias_method property, plural
327
335
  end
328
336
  end
329
337
 
@@ -333,13 +341,9 @@ module Icalendar
333
341
  code = <<-code
334
342
  def #{plural}=(a)
335
343
  if a.respond_to?(:to_ary)
336
- a.to_ary.each do |val|
337
- unless val.respond_to?(:to_ical)
338
- raise(NotImplementedError, "Property values do not support to_ical method!")
339
- end
340
- end
341
-
342
344
  @properties["#{property}"] = a.to_ary
345
+ elsif a =~ /^[^"].*(?<!\\\\),.*[^"]$/
346
+ @properties["#{property}"] = a.split(/(?<!\\\\),/).to_ary
343
347
  else
344
348
  raise ArgumentError, "#{plural} is a multi-property that must be an array! Use the add_[property] method to add single entries."
345
349
  end
@@ -176,7 +176,7 @@ module Icalendar
176
176
  # Replace dashes with underscores
177
177
  name = name.gsub('-', '_')
178
178
 
179
- if component.multi_property?(name)
179
+ if component.multiline_property?(name)
180
180
  adder = "add_" + name
181
181
  if component.respond_to?(adder)
182
182
  component.send(adder, value, params)
@@ -286,13 +286,15 @@ module Icalendar
286
286
  @parsers["DUE"] = m
287
287
  @parsers["DTSTART"] = m
288
288
  @parsers["RECURRENCE-ID"] = m
289
- @parsers["EXDATE"] = m
290
- @parsers["RDATE"] = m
291
289
  @parsers["CREATED"] = m
292
290
  @parsers["DTSTAMP"] = m
293
291
  @parsers["LAST-MODIFIED"] = m
294
292
  @parsers["ACKNOWLEDGED"] = m
295
293
 
294
+ m = self.method(:parse_multi_datetime)
295
+ @parsers["EXDATE"] = m
296
+ @parsers["RDATE"] = m
297
+
296
298
  # URI's
297
299
  m = self.method(:parse_uri)
298
300
  @parsers["TZURL"] = m
@@ -331,26 +333,48 @@ module Icalendar
331
333
  # Dates, Date-Times & Times
332
334
  # NOTE: invalid dates & times will be returned as strings...
333
335
  def parse_datetime(name, params, value)
334
- begin
335
- if params["VALUE"] && params["VALUE"].first == "DATE"
336
- result = Date.parse(value)
336
+ if params["VALUE"] && params["VALUE"].first == "DATE"
337
+ result = Date.parse(value)
338
+ else
339
+ result = DateTime.parse(value)
340
+ if /Z$/ =~ value
341
+ timezone = "UTC"
342
+ else
343
+ timezone = params["TZID"].first if params["TZID"]
344
+ end
345
+ result.icalendar_tzid = timezone
346
+ end
347
+ result
348
+ rescue Exception
349
+ value
350
+ end
351
+
352
+ # Multiple valued Dates
353
+ def parse_multi_datetime(name, params, value)
354
+ use_date = params['VALUE'] && params['VALUE'].first == 'DATE'
355
+ tzid = params['TZIID'].first if params['TZID']
356
+ result = []
357
+ value.split(/,/).each do |val|
358
+ if use_date
359
+ result << Date.parse(val)
337
360
  else
338
- result = DateTime.parse(value)
339
- if /Z$/ =~ value
340
- timezone = "UTC"
361
+ dt = DateTime.parse val
362
+ if /Z$/ =~ val
363
+ timezone = 'UTC'
341
364
  else
342
- timezone = params["TZID"].first if params["TZID"]
365
+ timezone = tzid
343
366
  end
344
- result.icalendar_tzid = timezone
367
+ dt.icalendar_tzid = timezone
368
+ result << dt
345
369
  end
346
- result
347
- rescue Exception
348
- value
349
370
  end
371
+ result
372
+ rescue Exception
373
+ [value]
350
374
  end
351
-
375
+
352
376
  def parse_recur(name, params, value)
353
- ::Icalendar::RRule.new(name, params, value)
377
+ [::Icalendar::RRule.new(name, params, value)]
354
378
  end
355
379
 
356
380
  # Durations
@@ -75,8 +75,12 @@ module Icalendar
75
75
  end
76
76
 
77
77
  def parse_date_val(name, string)
78
- match = string.match(/;#{name}=(.*?)(;|$)/)
79
- match ? DateTime.parse(match[1]) : nil
78
+ match = string.match(/;#{name}=(.*?)(Z)?(;|$)/)
79
+ if match
80
+ DateTime.parse(match[1]).tap do |dt|
81
+ dt.icalendar_tzid = 'UTC' unless match[2].nil?
82
+ end
83
+ end
80
84
  end
81
85
 
82
86
  def parse_int_val(name, string)
@@ -43,8 +43,8 @@
43
43
 
44
44
  module TZInfo
45
45
  class Timezone
46
- def ical_timezone(date)
47
- period = period_for_local(date)
46
+ def ical_timezone(date, dst = Timezone.default_dst)
47
+ period = period_for_local(date, dst)
48
48
  timezone = Icalendar::Timezone.new
49
49
  timezone.timezone_id = identifier
50
50
  if period.start_transition.nil?
@@ -8,7 +8,7 @@ require 'date'
8
8
  class TestConversions < Test::Unit::TestCase
9
9
  include Icalendar
10
10
 
11
- RESULT = <<EOS
11
+ RESULT = <<EOS.gsub("\n", "\r\n")
12
12
  BEGIN:VCALENDAR
13
13
  VERSION:2.0
14
14
  CALSCALE:GREGORIAN
@@ -17,8 +17,8 @@ BEGIN:VEVENT
17
17
  CATEGORIES:foo,bar,baz
18
18
  DESCRIPTION:desc
19
19
  DTSTAMP:20060720T174052
20
- DTSTART:20060720
21
- EXDATE:20121012T170000Z,20121102T170000Z
20
+ DTSTART;VALUE=DATE:20060720
21
+ EXDATE;TZID=America/New_York:20121012T170000,20121102T170000
22
22
  GEO:46.01;8.57
23
23
  LAST-MODIFIED:19960817T133000
24
24
  ORGANIZER:mailto:joe@example.com?subject=Ruby
@@ -56,7 +56,7 @@ EOS
56
56
  organizer(URI::MailTo.build(['joe@example.com', 'subject=Ruby']))
57
57
 
58
58
  # Date
59
- start Date.parse("2006-07-20")
59
+ start Date.parse("2006-07-20"), {'VALUE' => 'DATE'}
60
60
 
61
61
  # DateTime
62
62
  timestamp DateTime.parse("2006-07-20T17:40:52+0200")
@@ -67,12 +67,12 @@ EOS
67
67
  uid "foobar"
68
68
 
69
69
  add_rrule "FREQ=WEEKLY;UNTIL=20130220T180000Z;BYDAY=FR"
70
-
71
- add_exdate "20121012T170000Z"
72
- add_exdate "20121102T170000Z"
70
+ exception_dates %w(20121012T170000 20121102T170000), {'TZID' => 'America/New_York'}
73
71
  end
74
72
 
75
- assert_equal(RESULT.gsub("\n", "\r\n"), @cal.to_ical)
73
+ assert_equal(RESULT, @cal.to_ical)
74
+ # test round-trip
75
+ assert_equal(@cal.to_ical, Icalendar.parse(RESULT).to_ical)
76
76
  end
77
77
 
78
78
  def test_to_ical_folding
data/test/test_tzinfo.rb CHANGED
@@ -4,6 +4,7 @@ require 'test/unit'
4
4
  require 'icalendar'
5
5
  require 'tzinfo'
6
6
  require 'icalendar/tzinfo'
7
+ require 'timecop'
7
8
 
8
9
  class TestTZInfoExt < Test::Unit::TestCase
9
10
  def setup
@@ -31,7 +32,7 @@ class TestTZInfoExt < Test::Unit::TestCase
31
32
  BEGIN:VTIMEZONE
32
33
  TZID:America/Cayman
33
34
  BEGIN:STANDARD
34
- DTSTART:19120201T000712
35
+ DTSTART:19120201T000711
35
36
  TZNAME:EST
36
37
  TZOFFSETFROM:-0652
37
38
  TZOFFSETTO:-0500
@@ -54,4 +55,29 @@ END:STANDARD
54
55
  END:VTIMEZONE
55
56
  EXPECTED
56
57
  end
58
+
59
+ def test_dst_transition
60
+ tz = TZInfo::Timezone.get "America/Los_Angeles"
61
+
62
+ # DST transition in America/Los_Angeles
63
+ Timecop.freeze('2013-11-03T01:30:00-08:00') do
64
+ assert_raises(TZInfo::AmbiguousTime) { tz.ical_timezone( tz.now ) }
65
+ assert_raises(TZInfo::AmbiguousTime) { tz.ical_timezone( tz.now, nil ) }
66
+ assert_raises(TZInfo::AmbiguousTime) do
67
+ TZInfo::Timezone.default_dst = nil
68
+ tz.ical_timezone( tz.now )
69
+ end
70
+
71
+ assert_nothing_raised { tz.ical_timezone( tz.now, true ) }
72
+ assert_nothing_raised { tz.ical_timezone( tz.now, false ) }
73
+ assert_nothing_raised do
74
+ TZInfo::Timezone.default_dst = true
75
+ tz.ical_timezone( tz.now )
76
+ end
77
+ assert_nothing_raised do
78
+ TZInfo::Timezone.default_dst = false
79
+ tz.ical_timezone( tz.now )
80
+ end
81
+ end
82
+ end
57
83
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: icalendar
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.3
4
+ version: 1.4.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Ahearn
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-09-18 00:00:00.000000000 Z
11
+ date: 2013-11-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - ~>
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0.3'
55
+ - !ruby/object:Gem::Dependency
56
+ name: timecop
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 0.6.3
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: 0.6.3
55
69
  description: |2
56
70
  Implements the iCalendar specification (RFC-2445) in Ruby. This allows
57
71
  for the generation and parsing of .ics files, which are used by a
@@ -63,6 +77,7 @@ extensions: []
63
77
  extra_rdoc_files: []
64
78
  files:
65
79
  - .gitignore
80
+ - .travis.yml
66
81
  - COPYING
67
82
  - GPL
68
83
  - Gemfile