push dummy date value assignment into Formats.parse and allow custom values to be used

This commit is contained in:
Adam Meehan
2009-09-12 13:07:01 +10:00
parent d3c5101f92
commit 6db8b7d908
4 changed files with 54 additions and 18 deletions

View File

@@ -263,6 +263,18 @@ Now you get:
year of 20 is considered 1920 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: === TEMPORAL RESTRICTION ERRORS:
When using the validation temporal restrictions there are times when the restriction When using the validation temporal restrictions there are times when the restriction

View File

@@ -23,6 +23,7 @@ module ValidatesTimeliness
# Set the threshold value for a two digit year to be considered last century # Set the threshold value for a two digit year to be considered last century
#
# Default: 30 # Default: 30
# #
# Example: # Example:
@@ -32,6 +33,14 @@ module ValidatesTimeliness
cattr_accessor :ambiguous_year_threshold cattr_accessor :ambiguous_year_threshold
self.ambiguous_year_threshold = 30 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: # Format tokens:
# y = year # y = year
# m = month # m = month
@@ -196,7 +205,11 @@ module ValidatesTimeliness
break(proc) if matches = full.match(string.strip) break(proc) if matches = full.match(string.strip)
end end
last = options[:include_offset] ? 8 : 7 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 end
# Delete formats of specified type. Error raised if format not found. # Delete formats of specified type. Error raised if format not found.

View File

@@ -10,22 +10,17 @@ module ValidatesTimeliness
time_array = ValidatesTimeliness::Formats.parse(raw_value, type, options.reverse_merge(:strict => true)) time_array = ValidatesTimeliness::Formats.parse(raw_value, type, options.reverse_merge(:strict => true))
return nil if time_array.nil? 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 if type == :date
Date.new(*time_array[0..2]) Date.new(*time_array[0..2]) rescue nil
else else
make_time(time_array[0..7]) make_time(time_array[0..7])
end end
end end
def make_time(time_array) 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 if Time.respond_to?(:zone) && ValidatesTimeliness.use_time_zones
Time.zone.local(*time_array) Time.zone.local(*time_array)
else else

View File

@@ -1,11 +1,6 @@
require File.expand_path(File.dirname(__FILE__) + '/spec_helper') require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
describe ValidatesTimeliness::Formats do describe ValidatesTimeliness::Formats do
attr_reader :formats
before do
@formats = ValidatesTimeliness::Formats
end
describe "format proc generator" do describe "format proc generator" do
it "should generate proc which outputs date array with values in correct order" 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 it "should return time array from date string" do
time_array = formats.parse('12:13:14', :time, :strict => true) 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 end
it "should return date array from time string" do 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 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 = 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 end
it "should return zone offset when :include_offset options is true" do it "should return zone offset when :include_offset options is true" do
@@ -177,6 +172,22 @@ describe ValidatesTimeliness::Formats do
end end
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 describe "removing formats" do
it "should remove format from format array" do it "should remove format from format array" do
formats.remove_formats(:time, 'h.nn_ampm') 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') formats.add_formats(:time, "ss:hh:nn", :before => 'hh:nn:ss')
validate("59:23:58", :time).should be_true validate("59:23:58", :time).should be_true
time_array = formats.parse('59:23:58', :time) 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 end
it "should raise error if format exists" do it "should raise error if format exists" do
@@ -251,6 +262,11 @@ describe ValidatesTimeliness::Formats do
end end
end end
def formats
ValidatesTimeliness::Formats
end
def validate(time_string, type) def validate(time_string, type)
valid = false valid = false
formats.send("#{type}_expressions").each do |format, regexp, processor| formats.send("#{type}_expressions").each do |format, regexp, processor|