added ambiguous year threshold setting

This commit is contained in:
Adam Meehan 2009-06-06 11:16:19 +10:00
parent 7c0c1afe1c
commit 7aac14c874
3 changed files with 89 additions and 38 deletions

View File

@ -250,6 +250,19 @@ Now a time of '59:30:23' will be interpreted as 11:30:59 pm. This option saves
you adding a new one and deleting an old one to get it to work.
=== AMBIGUOUS YEAR THRESHOLD
When dealing with 2 digit year values, by default a year is interpreted as being
in the last century at or above 30. You can customize this however
ValidatesTimeliness::Formats.ambiguous_year_threshold = 20
Now you get:
year of 19 is considered 2019
year of 20 is considered 1920
=== TEMPORAL RESTRICTION ERRORS:
When using the validation temporal restrictions there are times when the restriction

View File

@ -21,6 +21,17 @@ module ValidatesTimeliness
:format_tokens,
:format_proc_args
# Set the threshold value for a two digit year to be considered last century
# Default: 30
#
# Example:
# year = '29' is considered 2029
# year = '30' is considered 1930
#
cattr_accessor :ambiguous_year_threshold
self.ambiguous_year_threshold = 30
# Format tokens:
# y = year
# m = month
@ -226,6 +237,49 @@ module ValidatesTimeliness
compile_format_expressions
end
def full_hour(hour, meridian)
hour = hour.to_i
return hour if meridian.nil?
if meridian.delete('.').downcase == 'am'
hour == 12 ? 0 : hour
else
hour == 12 ? hour : hour + 12
end
end
def unambiguous_year(year)
if year.length <= 2
century = Time.now.year.to_s[0..1].to_i
century -= 1 if year.to_i >= ambiguous_year_threshold
year = "#{century}#{year.rjust(2,'0')}"
end
year.to_i
end
def month_index(month)
return month.to_i if month.to_i.nonzero?
abbr_month_names.index(month.capitalize) || month_names.index(month.capitalize)
end
def month_names
defined?(I18n) ? I18n.t('date.month_names') : Date::MONTHNAMES
end
def abbr_month_names
defined?(I18n) ? I18n.t('date.abbr_month_names') : Date::ABBR_MONTHNAMES
end
def microseconds(usec)
(".#{usec}".to_f * 1_000_000).to_i
end
def offset_in_seconds(offset)
sign = offset =~ /^-/ ? -1 : 1
parts = offset.scan(/\d\d/).map {|p| p.to_f }
parts[1] = parts[1].to_f / 60
(parts[0] + parts[1]) * sign * 3600
end
private
# Compile formats into validation regexps and format procs
@ -285,44 +339,6 @@ module ValidatesTimeliness
end
end
def full_hour(hour, meridian)
hour = hour.to_i
return hour if meridian.nil?
if meridian.delete('.').downcase == 'am'
hour == 12 ? 0 : hour
else
hour == 12 ? hour : hour + 12
end
end
def unambiguous_year(year, threshold=30)
year = "#{year.to_i < threshold ? '20' : '19'}#{year}" if year.length == 2
year.to_i
end
def month_index(month)
return month.to_i if month.to_i.nonzero?
abbr_month_names.index(month.capitalize) || month_names.index(month.capitalize)
end
def month_names
defined?(I18n) ? I18n.t('date.month_names') : Date::MONTHNAMES
end
def abbr_month_names
defined?(I18n) ? I18n.t('date.abbr_month_names') : Date::ABBR_MONTHNAMES
end
def microseconds(usec)
(".#{usec}".to_f * 1_000_000).to_i
end
def offset_in_seconds(offset)
sign = offset =~ /^-/ ? -1 : 1
parts = offset.scan(/\d\d/).map {|p| p.to_f }
parts[1] = parts[1].to_f / 60
(parts[0] + parts[1]) * sign * 3600
end
end
end
end

View File

@ -155,6 +155,28 @@ describe ValidatesTimeliness::Formats do
end
end
describe "parsing date with ambiguous year" do
it "should return year in current century if year below threshold" do
time_array = formats.parse('01-02-29', :date)
time_array.should == [2029,2,1,0,0,0,0]
end
it "should return year in last century if year at or above threshold" do
time_array = formats.parse('01-02-30', :date)
time_array.should == [1930,2,1,0,0,0,0]
end
it "should allow custom threshold" do
default = ValidatesTimeliness::Formats.ambiguous_year_threshold
ValidatesTimeliness::Formats.ambiguous_year_threshold = 40
time_array = formats.parse('01-02-39', :date)
time_array.should == [2039,2,1,0,0,0,0]
time_array = formats.parse('01-02-40', :date)
time_array.should == [1940,2,1,0,0,0,0]
ValidatesTimeliness::Formats.ambiguous_year_threshold = default
end
end
describe "removing formats" do
it "should remove format from format array" do
formats.remove_formats(:time, 'h.nn_ampm')