diff --git a/README.rdoc b/README.rdoc index 6d504ff..6d303cb 100644 --- a/README.rdoc +++ b/README.rdoc @@ -263,6 +263,18 @@ Now you get: year of 20 is considered 1920 +=== DUMMY DATE FOR TIME TYPES + +Given that Ruby has no support for a time-only type, all time type columns are evaluated +as a regular Time class objects with a dummy date value set. Rails defines the dummy date as +2000-01-01. So a time of '12:30' is evaluated as a Time value of '2000-01-01 12:30'. If you +need to customize this for some reason you can do so as follows + + ValidatesTimeliness::Formats.dummy_date_for_time_type = [2009, 1, 1] + +The value should be an array of 3 values being year, month and day in that order. + + === TEMPORAL RESTRICTION ERRORS: When using the validation temporal restrictions there are times when the restriction diff --git a/lib/validates_timeliness/formats.rb b/lib/validates_timeliness/formats.rb index df84b9f..6f9720c 100644 --- a/lib/validates_timeliness/formats.rb +++ b/lib/validates_timeliness/formats.rb @@ -23,6 +23,7 @@ module ValidatesTimeliness # Set the threshold value for a two digit year to be considered last century + # # Default: 30 # # Example: @@ -32,6 +33,14 @@ module ValidatesTimeliness cattr_accessor :ambiguous_year_threshold self.ambiguous_year_threshold = 30 + # Set the dummy date part for a time type value. Should be an array of 3 values + # being year, month and day in that order. + # + # Default: [ 2000, 1, 1 ] same as ActiveRecord + # + cattr_accessor :dummy_date_for_time_type + self.dummy_date_for_time_type = [ 2000, 1, 1 ] + # Format tokens: # y = year # m = month @@ -196,7 +205,11 @@ module ValidatesTimeliness break(proc) if matches = full.match(string.strip) end last = options[:include_offset] ? 8 : 7 - processor.call(*matches[1..last]) if matches + if matches + values = processor.call(*matches[1..last]) + values[0..2] = dummy_date_for_time_type if type == :time + return values + end end # Delete formats of specified type. Error raised if format not found. diff --git a/lib/validates_timeliness/parser.rb b/lib/validates_timeliness/parser.rb index a640571..16cb7db 100644 --- a/lib/validates_timeliness/parser.rb +++ b/lib/validates_timeliness/parser.rb @@ -10,22 +10,17 @@ module ValidatesTimeliness time_array = ValidatesTimeliness::Formats.parse(raw_value, type, options.reverse_merge(:strict => true)) return nil if time_array.nil? - if type == :time - # Rails dummy time date part is defined as 2000-01-01 - time_array[0..2] = 2000, 1, 1 - else - # Enforce date part validity which Time class does not - return nil unless Date.valid_civil?(*time_array[0..2]) - end - if type == :date - Date.new(*time_array[0..2]) + Date.new(*time_array[0..2]) rescue nil else make_time(time_array[0..7]) end end def make_time(time_array) + # Enforce date part validity which Time class does not + return nil unless Date.valid_civil?(*time_array[0..2]) + if Time.respond_to?(:zone) && ValidatesTimeliness.use_time_zones Time.zone.local(*time_array) else diff --git a/spec/formats_spec.rb b/spec/formats_spec.rb index 580c18b..286f244 100644 --- a/spec/formats_spec.rb +++ b/spec/formats_spec.rb @@ -1,11 +1,6 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper') describe ValidatesTimeliness::Formats do - attr_reader :formats - - before do - @formats = ValidatesTimeliness::Formats - end describe "format proc generator" do it "should generate proc which outputs date array with values in correct order" do @@ -104,7 +99,7 @@ describe ValidatesTimeliness::Formats do it "should return time array from date string" do time_array = formats.parse('12:13:14', :time, :strict => true) - time_array.should == [0,0,0,12,13,14,0] + time_array.should == [2000,1,1,12,13,14,0] end it "should return date array from time string" do @@ -134,7 +129,7 @@ describe ValidatesTimeliness::Formats do it "should ignore date when extracting time and strict is false" do time_array = formats.parse('2000-02-01 12:13', :time, :strict => false) - time_array.should == [0,0,0,12,13,0,0] + time_array.should == [2000,1,1,12,13,0,0] end it "should return zone offset when :include_offset options is true" do @@ -177,6 +172,22 @@ describe ValidatesTimeliness::Formats do end end + describe "parse with custom dummy date values" do + before(:all) do + @old_dummy_date = formats.dummy_date_for_time_type + formats.dummy_date_for_time_type = [2009,1,1] + end + + it "should return time array with custom dummy date" do + time_array = formats.parse('12:13:14', :time, :strict => true) + time_array.should == [2009,1,1,12,13,14,0] + end + + after(:all) do + formats.dummy_date_for_time_type = @old_dummy_date + end + end + describe "removing formats" do it "should remove format from format array" do formats.remove_formats(:time, 'h.nn_ampm') @@ -219,7 +230,7 @@ describe ValidatesTimeliness::Formats do formats.add_formats(:time, "ss:hh:nn", :before => 'hh:nn:ss') validate("59:23:58", :time).should be_true time_array = formats.parse('59:23:58', :time) - time_array.should == [0,0,0,23,58,59,0] + time_array.should == [2000,1,1,23,58,59,0] end it "should raise error if format exists" do @@ -251,6 +262,11 @@ describe ValidatesTimeliness::Formats do end end + + def formats + ValidatesTimeliness::Formats + end + def validate(time_string, type) valid = false formats.send("#{type}_expressions").each do |format, regexp, processor|