lib/validates_timeliness/formats.rb in adzap-validates_timeliness-2.0.0 vs lib/validates_timeliness/formats.rb in adzap-validates_timeliness-2.1.0

- old
+ new

@@ -19,10 +19,21 @@ :date_expressions, :datetime_expressions, :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 # d = day # h = hour @@ -44,11 +55,11 @@ # x = 1 or 2 digits for unit (e.g. 'h' means an hour can be '9' or '09') # xx = 2 digits exactly for unit (e.g. 'hh' means an hour can only be '09') # # Special Cases: # yy = 2 or 4 digit year - # yyyyy = exactly 4 digit year + # yyyy = exactly 4 digit year # mmm = month long name (e.g. 'Jul' or 'July') # ddd = Day name of 3 to 9 letters (e.g. Wed or Wednesday) # u = microseconds matches 1 to 6 digits # # Any other invalid combination of repeating tokens will be swallowed up @@ -83,10 +94,11 @@ ] @@datetime_formats = [ 'yyyy-mm-dd hh:nn:ss', 'yyyy-mm-dd h:nn', + 'yyyy-mm-dd h:nn_ampm', 'yyyy-mm-dd hh:nn:ss.u', 'm/d/yy h:nn:ss', 'm/d/yy h:nn_ampm', 'm/d/yy h:nn', 'd/m/yy hh:nn:ss', @@ -224,10 +236,53 @@ date_formats.reject! { |format| us_format_regexp =~ format } datetime_formats.reject! { |format| us_format_regexp =~ format } 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 def format_expression_generator(string_format) regexp = string_format.dup @@ -257,11 +312,16 @@ def format_proc(order) arg_map = format_proc_args args = order.invert.sort.map {|p| arg_map[p[1]][1] } arr = [nil] * 7 order.keys.each {|k| i = arg_map[k][0]; arr[i] = arg_map[k][2] unless i.nil? } - proc_string = "lambda {|#{args.join(',')}| md||=nil; [#{arr.map {|i| i.nil? ? 'nil' : i }.join(',')}].map {|i| i.is_a?(Float) ? i : i.to_i } }" + proc_string = <<-EOL + lambda {|#{args.join(',')}| + md ||= nil + [#{arr.map {|i| i.nil? ? 'nil' : i }.join(',')}].map {|i| i.is_a?(Float) ? i : i.to_i } + } + EOL eval proc_string end def compile_formats(formats) formats.map { |format| [ format, *format_expression_generator(format) ] } @@ -283,47 +343,9 @@ datetime_expressions + date_expressions end 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 ValidatesTimeliness::Formats.compile_format_expressions