From 0a27c1bf9404d31347aad3d35a7c1373b0f7b5a1 Mon Sep 17 00:00:00 2001 From: David Moles Date: Thu, 25 Jun 2026 11:54:30 -0700 Subject: [PATCH] implement include? for open sets (fixes #46) --- lib/edtf/parser.rb | 2 +- lib/edtf/set.rb | 16 ++++- spec/edtf/set_spec.rb | 164 +++++++++++++++++++++++++++++++++++++++++- 3 files changed, 179 insertions(+), 3 deletions(-) diff --git a/lib/edtf/parser.rb b/lib/edtf/parser.rb index f03b4d2..e40ef29 100644 --- a/lib/edtf/parser.rb +++ b/lib/edtf/parser.rb @@ -871,7 +871,7 @@ def next_token "d01_30" ] Ractor.make_shareable(Racc_token_to_s_table) if defined?(Ractor) -Racc_debug_parser = false +Racc_debug_parser = true ##### State transition tables end ##### diff --git a/lib/edtf/set.rb b/lib/edtf/set.rb index 7a92906..a5e5f37 100644 --- a/lib/edtf/set.rb +++ b/lib/edtf/set.rb @@ -7,7 +7,6 @@ class Set include Comparable def_delegators :@dates, :size, :length, :empty? - def_delegators :to_a, :include? attr_accessor :choice, :later, :earlier @@ -29,6 +28,21 @@ def initialize_copy(other) end end + def include?(v) + return false unless v.is_a?(Date) + return false if empty? + + dates_array = to_a + if earlier? + (min = dates_array.first) >= v && min.precision == v.precision + elsif later? + (max = dates_array.last) <= v && max.precision == v.precision + else + dates_array.member?(v) + end + end + alias member? include? + def <<(date) dates << date self diff --git a/spec/edtf/set_spec.rb b/spec/edtf/set_spec.rb index e0a6671..d1f3f9e 100644 --- a/spec/edtf/set_spec.rb +++ b/spec/edtf/set_spec.rb @@ -52,7 +52,7 @@ module EDTF end it 'does not include the date 1671-01-01' do - expect(set.include?(Date.new(1671))).to be false + expect(set.include?(Date.new(1671).day_precision!)).to be false end it 'does not include the year 1669' do @@ -103,5 +103,167 @@ module EDTF expect(set.to_a).to eq(expected_months) end end + + context "open sets" do + describe 'the set {..1984}' do + let(:set) { Date.edtf('{..1984}') } + + it "is not a choice" do + expect(set).not_to be_choice + end + + it 'includes the date 1984' do + expect(set.include?(Date.new(1984).year_precision!)).to be true + end + + it 'includes the date 1984 BCE' do + expect(set.include?(Date.new(-1984).year_precision!)).to be true + end + + it 'does not include the date 1995' do + expect(set.include?(Date.new(1995).year_precision!)).to be false + end + end + + describe 'the set {..1984-05-11}' do + let(:set) { Date.edtf('{..1984-05-11}') } + + it "is not a choice" do + expect(set).not_to be_choice + end + + it 'includes the date 1984-05-11' do + expect(set.include?(Date.new(1984, 5, 11))).to be true + end + + it 'includes the date 11 May 1984 BCE' do + expect(set.include?(Date.new(-1984, 5, 11))).to be true + end + + it 'does not include the date 1995-01-01' do + expect(set.include?(Date.new(1995))).to be false + end + end + + describe 'the set {1984..}' do + let(:set) { Date.edtf('{1984..}') } + + it "is not a choice" do + expect(set).not_to be_choice + end + + it 'includes the date 1984' do + expect(set.include?(Date.new(1984).year_precision!)).to be true + end + + it 'does not include the date 1984 BCE' do + expect(set.include?(Date.new(-1984).year_precision!)).to be false + end + + it 'includes the date 1995' do + expect(set.include?(Date.new(1995).year_precision!)).to be true + end + end + + describe 'the set {1984-05-11..}' do + let(:set) { Date.edtf('{1984-05-11..}') } + + it "is not a choice" do + expect(set).not_to be_choice + end + + it 'includes the date 1984-05-11' do + expect(set.include?(Date.new(1984, 5, 11))).to be true + end + + it 'does not include the date 11 May 1984 BCE' do + expect(set.include?(Date.new(-1984, 5, 11))).to be false + end + + it 'includes the date 1995-01-01' do + expect(set.include?(Date.new(1995))).to be true + end + end + + describe 'the set [..1984]' do + let(:set) { Date.edtf('[..1984]') } + + it "is a choice" do + expect(set).to be_choice + end + + it 'includes the date 1984' do + expect(set.include?(Date.new(1984).year_precision!)).to be true + end + + it 'includes the date 1984 BCE' do + expect(set.include?(Date.new(-1984).year_precision!)).to be true + end + + it 'does not include the date 1995' do + expect(set.include?(Date.new(1995).year_precision!)).to be false + end + end + + describe 'the set [..1984-05-11]' do + let(:set) { Date.edtf('[..1984-05-11]') } + + it "is a choice" do + expect(set).to be_choice + end + + it 'includes the date 1984-05-11' do + expect(set.include?(Date.new(1984, 5, 11))).to be true + end + + it 'includes the date 11 May 1984 BCE' do + expect(set.include?(Date.new(-1984, 5, 11))).to be true + end + + it 'does not include the date 1995-01-01' do + expect(set.include?(Date.new(1995))).to be false + end + end + + describe 'the set [1984..]' do + let(:set) { Date.edtf('[1984..]') } + + it "is a choice" do + expect(set).to be_choice + end + + it 'includes the date 1984' do + expect(set.include?(Date.new(1984).year_precision!)).to be true + end + + it 'does not include the date 1984 BCE' do + expect(set.include?(Date.new(-1984).year_precision!)).to be false + end + + it 'includes the date 1995' do + expect(set.include?(Date.new(1995).year_precision!)).to be true + end + end + + describe 'the set [1984-05-11..]' do + let(:set) { Date.edtf('[1984-05-11..]') } + + it "is a choice" do + expect(set).to be_choice + end + + it 'includes the date 1984-05-11' do + expect(set.include?(Date.new(1984, 5, 11))).to be true + end + + it 'does not include the date 11 May 1984 BCE' do + expect(set.include?(Date.new(-1984, 5, 11))).to be false + end + + it 'includes the date 1995-01-01' do + expect(set.include?(Date.new(1995))).to be true + end + end + end end end