citeproc 0.0.8 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,10 +1,12 @@
1
1
 
2
2
  module CiteProc
3
-
4
- #
3
+
5
4
  # A CiteProc Variable represents the content of a text, numeric, date, or
6
- # name variable.
5
+ # name variable. In its basic form it is thin abstraction that behaves
6
+ # almost like a regular Ruby string; more complex Variables are handled
7
+ # by dedicated sub-classes that make the variable's type more explicit.
7
8
  #
9
+ # @abstract
8
10
  class Variable
9
11
 
10
12
  extend Forwardable
@@ -12,29 +14,29 @@ module CiteProc
12
14
 
13
15
  @fields = Hash.new { |h,k| h.fetch(k.to_sym, nil) }.merge({
14
16
  :date => %w{
15
- accessed container event-date issued original-date submitted
16
- },
17
+ accessed container event-date issued original-date submitted
18
+ },
17
19
 
18
20
  :names => %w{
19
- author collection-editor composer container-author recipient editor
20
- editorial-director illustrator interviewer original-author translator
21
- },
21
+ author collection-editor composer container-author recipient editor
22
+ editorial-director illustrator interviewer original-author translator
23
+ },
24
+
25
+ :number => %w{
26
+ chapter-number collection-number edition issue number number-of-pages
27
+ number-of-volumes volume
28
+ },
22
29
 
23
- :number => %w{
24
- chapter-number collection-number edition issue number number-of-pages
25
- number-of-volumes volume
26
- },
27
-
28
30
  :text => %w{
29
- abstract annote archive archive_location archive-place authority
30
- call-number citation-label citation-number collection-title
31
- container-title container-title-short dimensions DOI event event-place
32
- first-reference-note-number genre ISBN ISSN jurisdiction keyword
33
- locator medium note original-publisher original-publisher-place
34
- original-title page page-first PMID PMCID publisher publisher-place
35
- references section source status title title-short URL version
36
- year-suffix
37
- }
31
+ abstract annote archive archive_location archive-place authority
32
+ call-number citation-label citation-number collection-title
33
+ container-title container-title-short dimensions DOI event event-place
34
+ first-reference-note-number genre ISBN ISSN jurisdiction keyword
35
+ locator medium note original-publisher original-publisher-place
36
+ original-title page page-first PMID PMCID publisher publisher-place
37
+ references section source status title title-short URL version
38
+ year-suffix
39
+ }
38
40
  })
39
41
 
40
42
  @fields.each_value { |v| v.map!(&:to_sym) }
@@ -52,37 +54,92 @@ module CiteProc
52
54
 
53
55
  @fields.freeze
54
56
 
55
- @markup = /<[^>]*>/.freeze
56
-
57
-
57
+ @markup = /<[^>]*>/.freeze
58
+
59
+
58
60
  class << self
59
-
60
- attr_reader :fields, :types, :markup, :factories
61
+
62
+ # @!attribute [r] fields
63
+ # @return [{Symbol => Array<Symbol>}] mapping of variable types to
64
+ # their respective field names
65
+ attr_reader :fields
66
+
67
+ # @!attribute [r] types
68
+ # @return [{Symbol => Symbol}] mapping of field names to variable types
69
+ attr_reader :types
70
+
71
+ # @!attribute [r] factories
72
+ # @return [{Symbol => Class}] mapping of field names to their respective
73
+ # Variable classes
74
+ attr_reader :factories
75
+
76
+ # @!attribute markup
77
+ # @return [Regexp] pattern used to strip markup off values
78
+ attr_accessor :markup
79
+
80
+ # Creates a new {Variable} instance using the passed-in field name
81
+ # to distinguish which {Variable} class to use as factory. This
82
+ # method returns nil if the creation fails.
83
+ #
84
+ # @see .create!
85
+ #
86
+ # @example
87
+ # Variable.create('foo')
88
+ # #-> #<CiteProc::Variable "foo">
89
+ #
90
+ # Variable.create('foo', :title)
91
+ # #-> #<CiteProc::Text "foo">
92
+ #
93
+ # Variable.create(['Matz', 'Flanagan'], :author)
94
+ # #-> #<CiteProc::Names "Matz & Flanagan">
95
+ #
96
+ # Variable.create(2009, :issued)
97
+ # #-> #<CiteProc::Date "2009-01-01">
98
+ #
99
+ # @param value [Object] the variable's value
100
+ # @param field [Symbol] the value's field name
101
+ #
102
+ # @return [Variable] a new {Variable} (or sub-class) instance
103
+ def create(value, field = nil)
104
+ create!(value, field)
105
+ rescue
106
+ nil
107
+ end
108
+
61
109
 
62
- def create(value, type = nil)
63
- create!(value, type)
64
- rescue
65
- nil
66
- end
67
-
68
- def create!(value, type = nil)
69
- factory = factories[type]
70
- value.is_a?(factory) ? value : factory.new(value)
110
+ # Creates a new {Variable} instance using the passed-in field name
111
+ # to distinguish which {Variable} class to use as factory.
112
+ #
113
+ # @see .create
114
+ #
115
+ # @raise [TypeError] if no variable can be created for the given value
116
+ # and type
117
+ #
118
+ # @param value [Object] the variable's value
119
+ # @param field [Symbol] the variable's field name
120
+ #
121
+ # @return [Variable] a new {Variable} (or sub-class) instance
122
+ def create!(value, field = nil)
123
+ factory = factories[field]
124
+ value.is_a?(factory) ? value : factory.new(value)
71
125
  end
72
126
 
73
127
  end
74
-
128
+
129
+ # @!attribute value
130
+ # @return [Object] the value wrapped by this variable
75
131
  attr_accessor :value
76
132
 
77
133
  def_delegators :@value, :to_s,
78
- *::String.instance_methods(false).select {|m| m.to_s =~ /!$/ }
134
+ *::String.instance_methods(false).select {|m| m.to_s =~ /!$/ }
79
135
 
80
136
  def_delegators :to_s, :=~, :===,
81
- *::String.instance_methods(false).reject {|m| m.to_s =~ /^\W|!$|to_s/ }
137
+ *::String.instance_methods(false).reject {|m| m.to_s =~ /^\W|!$|to_s/ }
82
138
 
139
+
140
+ # Creates new Variable for the passed-in value
83
141
  def initialize(value = nil)
84
142
  replace(value)
85
- yield self if block_given?
86
143
  end
87
144
 
88
145
  def initialize_copy(other)
@@ -90,72 +147,94 @@ module CiteProc
90
147
  end
91
148
 
92
149
 
93
- # The replace method is typically called by the Variable's constructor. It
94
- # will try to set the Variable to the passed in value and should accept
95
- # a wide range of argument types; subclasses (especially Date and Names)
96
- # override this method.
97
- def replace(value)
98
- raise TypeError, "failed to set value to #{value.inspect}" unless value.respond_to?(:to_s)
99
- @value = value.to_s
100
- self
101
- end
150
+ # The replace method is typically called by the Variable's constructor. It
151
+ # will try to set the Variable to the passed in value and should accept
152
+ # a wide range of argument types; subclasses (especially Date and Names)
153
+ # override this method.
154
+ #
155
+ # @raise [TypeError] if the variable cannot be set to the passed-in value
156
+ #
157
+ # @param value [Object] the variable's new value
158
+ # @return [self]
159
+ def replace(value)
160
+ raise TypeError, "failed to set value to #{value.inspect}" unless value.respond_to?(:to_s)
161
+ @value = value.to_s
162
+ self
163
+ end
102
164
 
103
- def type
104
- @type ||= self.class.name.split(/::/)[-1].downcase.to_sym
105
- end
165
+ # @return [Symbol] the variable's type
166
+ def type
167
+ @type ||= self.class.name.split(/::/)[-1].downcase.to_sym
168
+ end
106
169
 
107
- # Returns true if the Variable can be (safely) cast to a numeric value.
170
+ # @return [Boolean] whether or not the variable can be (safely) cast to a numeric value
108
171
  def numeric?
109
- match(/\d/) ? to_i : false
172
+ !!match(/\d/)
110
173
  end
111
174
 
112
- # Returns (first) numeric data contained in the variable's value
175
+ # @return [Fixnum] the first (!) numeric data contained in the variable's
176
+ # value; zero if no numeric data is present
113
177
  def to_i
114
- to_s =~ /(-?\d+)/ && $1.to_i || 0
178
+ to_s =~ /([+-]?\d+)/ && $1.to_i || 0
115
179
  end
116
180
 
181
+ # @return [Float] the first (!) numeric or floating point data contained
182
+ # in the variable's value; zero if no numeric data is present
117
183
  def to_f
118
- to_s =~ /(-?\d[\d,\.]*)/ && $1.tr(',','.').to_f || 0.0
184
+ to_s =~ /([+-]?\d[\d,\.]*)/ && $1.tr(',','.').to_f || 0.0
119
185
  end
120
186
 
187
+ # @return [String] the variable's value stripped of markup
121
188
  def strip_markup
122
189
  gsub(Variable.markup, '')
123
190
  end
124
191
 
192
+ # Strips markup off the variable's value.
193
+ # @return [self]
125
194
  def strip_markup!
126
195
  gsub!(Variable.markup, '')
127
196
  end
128
197
 
198
+ # Compares the variable with the passed-in value. If other responds
199
+ # to {#strip_markup} the stripped strings will be compared; otherwise
200
+ # both objects will be converted to and compared as strings.
201
+ #
202
+ # @param other [Object] the object used for comparison
203
+ # @return [Fixnum,nil] -1, 0, or 1 depending on the result of the
204
+ # comparison; or nil if the two objects cannot be ignored.
129
205
  def <=>(other)
130
206
  case
131
207
  when other.respond_to?(:strip_markup)
132
208
  strip_markup <=> other.strip_markup
133
-
134
209
  when other && other.respond_to?(:to_s)
135
210
  to_s <=> other.to_s
136
-
137
211
  else
138
212
  nil
139
213
  end
140
214
  end
215
+
216
+ # @!method to_s
217
+ # @return [String] the variable's value as a string
218
+ alias to_citeproc to_s
141
219
 
142
- alias to_citeproc to_s
143
-
220
+ # @return [String] a JSON string representation of the variable
144
221
  def to_json
145
222
  MultiJson.encode(to_citeproc)
146
223
  end
147
224
 
148
- def inspect
149
- "#<#{self.class.name}: #{to_s.inspect}>"
150
- end
151
-
225
+ # @return [String] a human-readable representation of the variable
226
+ def inspect
227
+ "#<#{self.class.name} #{to_s.inspect}>"
228
+ end
229
+
152
230
  end
153
231
 
232
+ # A CiteProc Variable used for string values.
233
+ class Text < Variable
234
+ end
154
235
 
155
- class Text < Variable
156
- end
157
-
158
- class Number < Variable
159
- end
236
+ # A CiteProc Variable used for numeric values.
237
+ class Number < Variable
238
+ end
160
239
 
161
240
  end
@@ -1,3 +1,3 @@
1
1
  module CiteProc
2
- VERSION = '0.0.8'.freeze
2
+ VERSION = '0.0.9'.freeze
3
3
  end
@@ -1,6 +1,3 @@
1
- require 'spec_helper'
2
- require 'tempfile'
3
-
4
1
  module CiteProc
5
2
 
6
3
  describe 'Assets' do
@@ -56,9 +53,18 @@ module CiteProc
56
53
  it 'returns the given string if it looks like XML' do
57
54
  Style.open('<b>foo bar!</b>').to_s.should == '<b>foo bar!</b>'
58
55
  end
59
-
60
56
  end
61
57
 
58
+ describe '.extend_name' do
59
+ it 'adds the default extension if the file does not already end with it' do
60
+ Style.extend_name(name.sub(/#{extension}$/,'')).should == name
61
+ end
62
+
63
+ it 'does not add the default extension if the file already ends with it' do
64
+ Style.extend_name(name).should == name
65
+ end
66
+ end
67
+
62
68
  end
63
69
  end
64
70
  end
@@ -3,6 +3,101 @@ require 'spec_helper'
3
3
  module CiteProc
4
4
  describe Date do
5
5
 
6
+ class Date
7
+ describe DateParts do
8
+ it { should_not be_nil }
9
+ it { should be_empty }
10
+
11
+ describe 'sorting' do
12
+ it 'treats [2003] as less than [2003,1]' do
13
+ DateParts.new(2003).should be < DateParts.new(2003,1)
14
+ end
15
+
16
+ it 'treats [1992,9,23] as less than [1993,8,22]' do
17
+ DateParts.new(1992,9,23).should be < DateParts.new(1993,8,22)
18
+ end
19
+
20
+ it 'treats [1992,9,23] as less than [1992,10,22]' do
21
+ DateParts.new(1992,9,23).should be < DateParts.new(1992,10,22)
22
+ end
23
+
24
+ it 'treats [1992,9,23] as less than [1992,9,24]' do
25
+ DateParts.new(1992,9,23).should be < DateParts.new(1992,9,24)
26
+ end
27
+
28
+ it 'treats [-50] as less than [-25]' do
29
+ DateParts.new(-50).should be < DateParts.new(-25)
30
+ end
31
+
32
+ it 'treats [-50] as less than [-50,12]' do
33
+ DateParts.new(-50).should be < DateParts.new(-50,12)
34
+ end
35
+
36
+ it 'treats [1994,1,23] as less than today' do
37
+ DateParts.new(1994,1,23).should be < ::Date.today
38
+ end
39
+ end
40
+
41
+ describe '#dup' do
42
+ let(:date) { DateParts.new(1991,8,22) }
43
+
44
+ it 'creates a copy that contains the same parts' do
45
+ date.dup.to_a.should == [1991,8,22]
46
+ end
47
+
48
+ it 'does not return self' do
49
+ date.dup.should_not equal(date)
50
+ date.dup.should == date
51
+ end
52
+ end
53
+
54
+ describe '#update' do
55
+ it 'accepts a hash' do
56
+ DateParts.new.update(:month => 2, :year => 80).to_a.should == [80,2,nil]
57
+ end
58
+
59
+ it 'accepts an array' do
60
+ DateParts.new.update([80,2]).to_a.should == [80,2,nil]
61
+ end
62
+ end
63
+
64
+ describe '#strftime' do
65
+ it 'formats the date parts according to the format string' do
66
+ DateParts.new(1998,2,4).strftime('FOO %0m%0d%y').should == 'FOO 020498'
67
+ end
68
+ end
69
+
70
+ describe 'to_citeproc' do
71
+ it 'returns an empty list by default' do
72
+ DateParts.new.to_citeproc.should == []
73
+ end
74
+
75
+ it 'returns a list with the year if only the year is set' do
76
+ DateParts.new(2001).to_citeproc.should == [2001]
77
+ end
78
+
79
+ it 'supports zero parts' do
80
+ DateParts.new(0,0).to_citeproc.should == [0,0]
81
+ end
82
+ end
83
+
84
+ describe '#open?' do
85
+ it 'returns false by default' do
86
+ DateParts.new.should_not be_open
87
+ end
88
+
89
+ it 'returns false for [1999,8,24]' do
90
+ DateParts.new(1999, 8, 24).should_not be_open
91
+ end
92
+
93
+ it 'returns true for [0]' do
94
+ DateParts.new(0).should be_open
95
+ end
96
+ end
97
+ end
98
+ end
99
+
100
+
6
101
  let(:ad2k) { Date.create('date-parts' => [[2000]])}
7
102
  let(:may) { Date.create('date-parts' => [[2000, 5]])}
8
103
  let(:first_of_may) { Date.create('date-parts' => [[2000, 5, 1]])}
@@ -17,11 +112,68 @@ module CiteProc
17
112
  it { should_not be_numeric }
18
113
 
19
114
  describe '.new' do
115
+ it 'accepts a hash as input' do
116
+ Date.new(:literal => 'Summer').to_s.should == 'Summer'
117
+ end
118
+
119
+ it 'accepts a hash as input and converts date parts' do
120
+ Date.new(:'date-parts' => [[2003,2]]).parts[0].should be_a(Date::DateParts)
121
+ end
122
+
123
+ it 'accepts a fixnum and treats it as the year' do
124
+ Date.new(1666).year.should == 1666
125
+ end
126
+
127
+ it 'accepts a date' do
128
+ Date.new(::Date.new(1980,4)).month.should == 4
129
+ end
130
+
131
+ it 'accepts a date and creates date parts' do
132
+ Date.new(::Date.new(1980,4)).parts[0].to_citeproc.should == [1980,4,1]
133
+ end
134
+
135
+ it 'is empty by default' do
136
+ Date.new.should be_empty
137
+ end
138
+
139
+ it 'accepts date strings' do
140
+ Date.new('2009-03-19').day.should == 19
141
+ end
142
+
143
+ it 'accepts JSON strings' do
144
+ Date.new('{ "date-parts": [[2001,1,19]]}').day.should == 19
145
+ end
146
+
147
+ it 'accepts date parts in an array' do
148
+ Date.new([2009,3]).month.should == 3
149
+ end
150
+
151
+ it 'accepts ranges as an array' do
152
+ Date.new([[2009],[2012]]).should be_range
153
+ end
154
+
155
+ it 'accepts year ranges' do
156
+ Date.new(2009..2012).should be_range
157
+ end
158
+
159
+ it 'accepts exclusive date ranges' do
160
+ Date.new(::Date.new(2009) ... ::Date.new(2011)).end_date.year.should == 2010
161
+ end
162
+
163
+ it 'accepts inclusive date ranges' do
164
+ Date.new(::Date.new(2009) .. ::Date.new(2011)).end_date.year.should == 2011
165
+ end
20
166
 
167
+ it 'accepts EDTF date strings' do
168
+ Date.new('2009?-03-19').should be_uncertain
169
+ end
170
+
171
+ it 'accepts EDTF intervals' do
172
+ Date.new('2009-03-19/2010-11-21').parts.map(&:to_citeproc).should == [[2009,3,19],[2010,11,21]]
173
+ end
21
174
  end
22
175
 
23
176
  describe '.parse' do
24
-
25
177
  it 'returns nil by default' do
26
178
  Date.parse('').should be nil
27
179
  Date.parse(nil).should be nil
@@ -38,6 +190,32 @@ module CiteProc
38
190
  end
39
191
  end
40
192
 
193
+ describe '#dup' do
194
+ let(:date) { Date.new([1991,8]) }
195
+
196
+ it 'creates a copy that contains the same parts' do
197
+ date.dup.parts.map(&:to_citeproc).should == [[1991,8]]
198
+ end
199
+
200
+ it 'copies uncertainty' do
201
+ date.dup.should_not be_uncertain
202
+ date.uncertain!.dup.should be_uncertain
203
+ end
204
+
205
+ it 'makes a deep copy of attributes' do
206
+ expect { date.dup.uncertain! }.not_to change { date.uncertain? }
207
+ end
208
+
209
+ it 'makes a deep copy of date parts' do
210
+ expect { date.dup.parts[0].update(:year => 2012) }.not_to change { date.year }
211
+ end
212
+
213
+ it 'does not return self' do
214
+ date.dup.should_not equal(date)
215
+ date.dup.should == date
216
+ end
217
+ end
218
+
41
219
  describe 'literal dates' do
42
220
  it 'is not literal by default' do
43
221
  Date.new.should_not be_literal
@@ -51,16 +229,36 @@ module CiteProc
51
229
  Date.create('date-parts' => [[2000]], :literal => 'foo').should be_literal
52
230
  end
53
231
  end
232
+
233
+ describe 'seasons' do
234
+ it 'is no season by default' do
235
+ Date.new.should_not be_season
236
+ end
237
+
238
+ it 'is a season if contains only a season field' do
239
+ Date.new(:season => 'Winter').should be_season
240
+ end
241
+
242
+ it 'is a season if contains a season field' do
243
+ Date.new(:'date-parts' => [[2001]], :season => 'Winter').should be_season
244
+ end
245
+ end
54
246
 
55
247
  describe 'uncertain dates' do
56
248
  it 'are uncertain' do
57
249
  Date.new({ 'date-parts' => [[-225]], 'circa' => '1' }).should be_uncertain
58
- Date.new { |d| d.parts = [[-225]]; d.uncertain! }.should be_uncertain
250
+ Date.new { |d| d.parts = [[-225]]; d.uncertain! }.should_not be_certain
251
+ end
252
+
253
+ describe '#(un)certain!' do
254
+ it 'returns self' do
255
+ ad2k.uncertain!.should equal(ad2k)
256
+ ad2k.certain!.should equal(ad2k)
257
+ end
59
258
  end
60
259
  end
61
260
 
62
261
  describe 'sorting' do
63
-
64
262
  it 'dates with more date-parts will come after those with fewer parts' do
65
263
  (ad2k < may && may < first_of_may).should be true
66
264
  end
@@ -68,8 +266,42 @@ module CiteProc
68
266
  it 'negative years are sorted inversely' do
69
267
  [ad50, bc100, bc50, ad100].sort.map(&:year).should == [-100, -50, 50, 100]
70
268
  end
269
+
270
+ it 'can be compared to dates' do
271
+ ad50.should be < ::Date.new(50,2)
272
+ ad50.should be > ::Date.new(49)
273
+ end
274
+ end
275
+
276
+ describe '#start_date' do
277
+ it 'returns nil by default' do
278
+ Date.new.start_date.should be_nil
279
+ end
280
+
281
+ it 'returns a ruby date when date-parts are set' do
282
+ Date.new(1999).start_date.year.should == 1999
283
+ end
71
284
  end
72
285
 
286
+ describe '#end_date' do
287
+ it 'returns nil by default' do
288
+ Date.new.end_date.should be_nil
289
+ end
290
+
291
+ it 'returns nil when there is a single date-parts set' do
292
+ Date.new(1312).end_date.should be_nil
293
+ end
294
+
295
+ it 'returns a ruby date when date-parts are a closed range' do
296
+ Date.new(1999..2000).end_date.year.should == 2000
297
+ end
298
+ end
299
+
300
+ describe '#-@' do
301
+ it 'inverts the year' do
302
+ (-ad50).should == bc50
303
+ end
304
+ end
73
305
 
74
306
  describe '#display' do
75
307
  it 'returns an empty string by default' do
@@ -114,21 +346,49 @@ module CiteProc
114
346
  it 'today is not b.c.' do
115
347
  Date.today.should_not be_bc
116
348
  end
117
-
349
+
118
350
  it 'the year 2000 is not a.d.' do
119
351
  ad2k.should_not be_ad
120
352
  end
121
353
 
122
354
  end
123
355
 
356
+ describe '#empty?' do
357
+ it 'returns true by default' do
358
+ Date.new.should be_empty
359
+ end
360
+
361
+ it 'returns true when it contains no date parts' do
362
+ Date.new({}).should be_empty
363
+ end
364
+
365
+ it 'returns false for today' do
366
+ Date.today.should_not be_empty
367
+ end
368
+
369
+ it 'returns false for literal dates' do
370
+ Date.new(:literal => 'foo').should_not be_empty
371
+ end
372
+
373
+ it 'returns false for seasons' do
374
+ Date.new(:season => 'Summer').should_not be_empty
375
+ end
376
+ end
377
+
124
378
  describe '#to_json' do
125
379
  it 'supports simple parts' do
126
380
  Date.new(%w{2000 1 15}).to_json.should == '{"date-parts":[[2000,1,15]]}'
127
381
  end
128
382
 
129
- it 'supports integers and strings parts' do
383
+ it 'supports string parts' do
130
384
  Date.new(['2000', '1', '15']).to_json.should == '{"date-parts":[[2000,1,15]]}'
385
+ end
386
+
387
+ it 'supports integer parts' do
131
388
  Date.new([2000, 1, 15]).to_json.should == '{"date-parts":[[2000,1,15]]}'
389
+ end
390
+
391
+ it 'supports mixed parts' do
132
392
  Date.new(['2000', 1, '15']).to_json.should == '{"date-parts":[[2000,1,15]]}'
133
393
  end
134
394
 
@@ -136,9 +396,12 @@ module CiteProc
136
396
  Date.new(-200).to_json.should == '{"date-parts":[[-200]]}'
137
397
  end
138
398
 
399
+ it 'treats seasons as a strings' do
400
+ Date.create({:season => '1', 'date-parts' => [[1950]]}).to_json.should =~ /"season":"1"/
401
+ end
402
+
139
403
  it 'supports seasons' do
140
- Date.create({:season => '1', 'date-parts' => [[1950]]}).to_json.should == '{"date-parts":[[1950]],"season":"1"}'
141
- Date.create({:season => 'Trinity', 'date-parts' => [[1975]]}).to_json.should == '{"date-parts":[[1975]],"season":"Trinity"}'
404
+ Date.create({:season => 'Trinity', 'date-parts' => [[1975]]}).to_json.should =~ /"season":"Trinity"/
142
405
  end
143
406
 
144
407
  it 'supports string literals' do
@@ -149,8 +412,11 @@ module CiteProc
149
412
  Date.new(:raw => '23 May 1955').to_json.should == '{"date-parts":[[1955,5,23]]}'
150
413
  end
151
414
 
152
- it 'supports open and closed ranges' do
415
+ it 'supports closed ranges' do
153
416
  Date.new([[2000,11],[2000,12]]).to_json.should == '{"date-parts":[[2000,11],[2000,12]]}'
417
+ end
418
+
419
+ it 'supports open ranges' do
154
420
  Date.new([[2000,11],[0,0]]).to_json.should == '{"date-parts":[[2000,11],[0,0]]}'
155
421
  end
156
422
  end