Permalink
Browse files

added ambiguous year threshold setting

  • Loading branch information...
1 parent 7c0c1af commit 7aac14c874481c70f55439804ec6acd113aa9975 @adzap adzap committed Jun 6, 2009
Showing with 89 additions and 38 deletions.
  1. +13 −0 README.rdoc
  2. +54 −38 lib/validates_timeliness/formats.rb
  3. +22 −0 spec/formats_spec.rb
View
@@ -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
@@ -21,6 +21,17 @@ class Formats
: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 @@ def remove_us_formats
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 @@ def expression_set(type, string)
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
@@ -155,6 +155,28 @@
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')

0 comments on commit 7aac14c

Please sign in to comment.