From c37c3e82fa1dbde50b8947227447ba446ced72f1 Mon Sep 17 00:00:00 2001 From: Adam Meehan Date: Thu, 17 Jul 2008 15:08:33 +1000 Subject: [PATCH] moved formats to own module --- benchmark.rb | 14 +++--- lib/validates_timeliness.rb | 1 + lib/validates_timeliness/formats.rb | 56 ++++++++++++++++++++++ lib/validates_timeliness/validations.rb | 62 ++----------------------- 4 files changed, 69 insertions(+), 64 deletions(-) create mode 100644 lib/validates_timeliness/formats.rb diff --git a/benchmark.rb b/benchmark.rb index ddde9ea..3609782 100644 --- a/benchmark.rb +++ b/benchmark.rb @@ -12,6 +12,12 @@ require 'lib/validates_timeliness' n = 10000 Benchmark.bm do |x| + x.report('timeliness') { + n.times do + ActiveRecord::Base.timeliness_date_time_parse("2000-01-04 12:12:12", :datetime) + end + } + x.report('time') { n.times do "2000-01-04 12:12:12" =~ /\A(\d{4})-(\d{2})-(\d{2}) (\d{2})[\. :](\d{2})([\. :](\d{2}))?\Z/ @@ -26,14 +32,8 @@ Benchmark.bm do |x| Time.mktime(*arr) end } - - x.report('timeliness') { - n.times do - ActiveRecord::Base.timeliness_date_time_parse("2000-01-04 12:12:12", :datetime) - end - } - x.report('datetime') { + x.report('strptime') { n.times do DateTime.strptime("2000-01-04 12:12:12", '%Y-%m-%d %H:%M:%s') end diff --git a/lib/validates_timeliness.rb b/lib/validates_timeliness.rb index 1bcf809..1912c92 100644 --- a/lib/validates_timeliness.rb +++ b/lib/validates_timeliness.rb @@ -1,5 +1,6 @@ require 'validates_timeliness/attribute_methods' require 'validates_timeliness/validations' +require 'validates_timeliness/formats' require 'validates_timeliness/multiparameter_attributes' require 'validates_timeliness/instance_tag' require 'validates_timeliness/validate_timeliness_matcher' if ENV['RAILS_ENV'] == 'test' diff --git a/lib/validates_timeliness/formats.rb b/lib/validates_timeliness/formats.rb new file mode 100644 index 0000000..99417e7 --- /dev/null +++ b/lib/validates_timeliness/formats.rb @@ -0,0 +1,56 @@ +# TODO add support switching US to euro date formats +module ValidatesTimeliness + module Formats + mattr_accessor :valid_time_formats + mattr_accessor :valid_date_formats + mattr_accessor :valid_datetime_formats + + # The if you want to combine a time regexp with a date regexp then you + # should not use line begin or end anchors in the expression. Pre and post + # match strings are still checked for validity, and fail the match if they + # are not empty. + # + # The proc object should return an array with 1-3 elements with values + # ordered like so [hour, minute, second]. The proc should have as many + # arguments as groups in the regexp or you will get an error. + @@valid_time_formats = { + :hhnnss_colons => /(\d{2}):(\d{2}):(\d{2})/, + :hhnnss_dashes => /(\d{2})-(\d{2})-(\d{2})/, + :hhnn_colons => /(\d{2}):(\d{2})/, + :hnn_dots => /(\d{1,2})\.(\d{2})/, + :hnn_spaces => /(\d{1,2})\s(\d{2})/, + :hnn_dashes => /(\d{1,2})-(\d{2})/, + :hnn_ampm_colons => [ /(\d{1,2}):(\d{2})\s?((?:a|p)\.?m\.?)/i, lambda {|h, n, md| [full_hour(h, md), n, 0] } ], + :hnn_ampm_dots => [ /(\d{1,2})\.(\d{2})\s?((?:a|p)\.?m\.?)/i, lambda {|h, n, md| [full_hour(h, md), n, 0] } ], + :hnn_ampm_spaces => [ /(\d{1,2})\s(\d{2})\s?((?:a|p)\.?m\.?)/i, lambda {|h, n, md| [full_hour(h, md), n, 0] } ], + :hnn_ampm_dashes => [ /(\d{1,2})-(\d{2})\s?((?:a|p)\.?m\.?)/i, lambda {|h, n, md| [full_hour(h, md), n, 0] } ], + :h_ampm => [ /(\d{1,2})\s?((?:a|p)\.?m\.?)/i, lambda {|h, md| [full_hour(h, md), 0, 0] } ] + } + + # The proc object should return an array with 3 elements with values + # ordered like so year, month, day. The proc should have as many + # arguments as groups in the regexp or you will get an error. + @@valid_date_formats = { + :yyyymmdd_slashes => /(\d{4})\/(\d{2})\/(\d{2})/, + :yyyymmdd_dashes => /(\d{4})-(\d{2})-(\d{2})/, + :yyyymmdd_slashes => /(\d{4})\.(\d{2})\.(\d{2})/, + :mdyyyy_slashes => [ /(\d{1,2})\/(\d{1,2})\/(\d{4})/, lambda {|m, d, y| [y, m, d] } ], + :dmyyyy_slashes => [ /(\d{1,2})\/(\d{1,2})\/(\d{4})/, lambda {|d, m ,y| [y, m, d] } ], + :dmyyyy_dashes => [ /(\d{1,2})-(\d{1,2})-(\d{4})/, lambda {|d, m ,y| [y, m, d] } ], + :dmyyyy_dots => [ /(\d{1,2})\.(\d{1,2})\.(\d{4})/, lambda {|d, m ,y| [y, m, d] } ], + :mdyy_slashes => [ /(\d{1,2})\/(\d{1,2})\/(\d{2})/, lambda {|m, d ,y| [unambiguous_year(y), m, d] } ], + :dmyy_slashes => [ /(\d{1,2})\/(\d{1,2})\/(\d{2})/, lambda {|d, m ,y| [unambiguous_year(y), m, d] } ], + :dmyy_dashes => [ /(\d{1,2})-(\d{1,2})-(\d{2})/, lambda {|d, m ,y| [unambiguous_year(y), m, d] } ], + :dmyy_dots => [ /(\d{1,2})\.(\d{1,2})\.(\d{2})/, lambda {|d, m ,y| [unambiguous_year(y), m, d] } ], + :d_mmm_yyyy => [ /(\d{1,2}) (\w{3,9}) (\d{4})/, lambda {|d, m ,y| [y, m, d] } ], + :d_mmm_yy => [ /(\d{1,2}) (\w{3,9}) (\d{2})/, lambda {|d, m ,y| [unambiguous_year(y), m, d] } ] + } + + @@valid_datetime_formats = { + :yyyymmdd_dashes_hhnnss_colons => /#{valid_date_formats[:yyyymmdd_dashes]}\s#{valid_time_formats[:hhnnss_colons]}/, + :yyyymmdd_dashes_hhnn_colons => /#{valid_date_formats[:yyyymmdd_dashes]}\s#{valid_time_formats[:hhnn_colons]}/, + :iso8601 => /#{valid_date_formats[:yyyymmdd_dashes]}T#{valid_time_formats[:hhnnss_colons]}(?:Z|[-+](\d{2}):(\d{2}))?/ + } + + end +end diff --git a/lib/validates_timeliness/validations.rb b/lib/validates_timeliness/validations.rb index ff8fa4b..351d2a8 100644 --- a/lib/validates_timeliness/validations.rb +++ b/lib/validates_timeliness/validations.rb @@ -1,56 +1,4 @@ module ValidatesTimeliness - mattr_accessor :valid_time_formats - mattr_accessor :valid_date_formats - mattr_accessor :valid_datetime_formats - - # The if you want to combine a time regexp with a date regexp then you - # should not use line begin or end anchors in the expression. Pre and post - # match strings are still checked for validity, and fail the match if they - # are not empty. - # - # The proc object should return an array with 1-3 elements with values - # ordered like so [hour, minute, second]. The proc should have as many - # arguments as groups in the regexp or you will get an error. - @@valid_time_formats = { - :hhnnss_colons => /(\d{2}):(\d{2}):(\d{2})/, - :hhnnss_dashes => /(\d{2})-(\d{2})-(\d{2})/, - :hhnn_colons => /(\d{2}):(\d{2})/, - :hnn_dots => /(\d{1,2})\.(\d{2})/, - :hnn_spaces => /(\d{1,2})\s(\d{2})/, - :hnn_dashes => /(\d{1,2})-(\d{2})/, - :hnn_ampm_colons => [ /(\d{1,2}):(\d{2})\s?((?:a|p)\.?m\.?)/i, lambda {|h, n, md| [full_hour(h, md), n, 0] } ], - :hnn_ampm_dots => [ /(\d{1,2})\.(\d{2})\s?((?:a|p)\.?m\.?)/i, lambda {|h, n, md| [full_hour(h, md), n, 0] } ], - :hnn_ampm_spaces => [ /(\d{1,2})\s(\d{2})\s?((?:a|p)\.?m\.?)/i, lambda {|h, n, md| [full_hour(h, md), n, 0] } ], - :hnn_ampm_dashes => [ /(\d{1,2})-(\d{2})\s?((?:a|p)\.?m\.?)/i, lambda {|h, n, md| [full_hour(h, md), n, 0] } ], - :h_ampm => [ /(\d{1,2})\s?((?:a|p)\.?m\.?)/i, lambda {|h, md| [full_hour(h, md), 0, 0] } ] - } - - # The proc object should return an array with 3 elements with values - # ordered like so year, month, day. The proc should have as many - # arguments as groups in the regexp or you will get an error. - @@valid_date_formats = { - :yyyymmdd_slashes => /(\d{4})\/(\d{2})\/(\d{2})/, - :yyyymmdd_dashes => /(\d{4})-(\d{2})-(\d{2})/, - :yyyymmdd_slashes => /(\d{4})\.(\d{2})\.(\d{2})/, - :mdyyyy_slashes => [ /(\d{1,2})\/(\d{1,2})\/(\d{4})/, lambda {|m, d, y| [y, m, d] } ], - :dmyyyy_slashes => [ /(\d{1,2})\/(\d{1,2})\/(\d{4})/, lambda {|d, m ,y| [y, m, d] } ], - :dmyyyy_dashes => [ /(\d{1,2})-(\d{1,2})-(\d{4})/, lambda {|d, m ,y| [y, m, d] } ], - :dmyyyy_dots => [ /(\d{1,2})\.(\d{1,2})\.(\d{4})/, lambda {|d, m ,y| [y, m, d] } ], - :mdyy_slashes => [ /(\d{1,2})\/(\d{1,2})\/(\d{2})/, lambda {|m, d ,y| [unambiguous_year(y), m, d] } ], - :dmyy_slashes => [ /(\d{1,2})\/(\d{1,2})\/(\d{2})/, lambda {|d, m ,y| [unambiguous_year(y), m, d] } ], - :dmyy_dashes => [ /(\d{1,2})-(\d{1,2})-(\d{2})/, lambda {|d, m ,y| [unambiguous_year(y), m, d] } ], - :dmyy_dots => [ /(\d{1,2})\.(\d{1,2})\.(\d{2})/, lambda {|d, m ,y| [unambiguous_year(y), m, d] } ], - :d_mmm_yyyy => [ /(\d{1,2}) (\w{3,9}) (\d{4})/, lambda {|d, m ,y| [y, m, d] } ], - :d_mmm_yy => [ /(\d{1,2}) (\w{3,9}) (\d{2})/, lambda {|d, m ,y| [unambiguous_year(y), m, d] } ] - } - - @@valid_datetime_formats = { - :yyyymmdd_dashes_hhnnss_colons => /#{valid_date_formats[:yyyymmdd_dashes]}\s#{valid_time_formats[:hhnnss_colons]}/, - :yyyymmdd_dashes_hhnn_colons => /#{valid_date_formats[:yyyymmdd_dashes]}\s#{valid_time_formats[:hhnn_colons]}/, - :iso8601 => /#{valid_date_formats[:yyyymmdd_dashes]}T#{valid_time_formats[:hhnnss_colons]}(?:Z|[-+](\d{2}):(\d{2}))?/ - } - - # Adds ActiveRecord validation methods for date, time and datetime validation. # The validity of values can be restricted to be before and/or certain dates # or times. @@ -86,9 +34,9 @@ module ValidatesTimeliness year.to_i end - # loop through regexp and call proc on matches if available. Allow pre or - # post match strings if bounded is false. Lastly fills out time_array to - # full 6 part datetime array. + # loop through format regexps and call proc on matches if available. Allow + # pre or post match strings if bounded is false. Lastly fills out + # time_array to full 6 part datetime array. def extract_date_time_values(time_string, formats, bounded=true) time_array = nil formats.each do |name, (regexp, processor)| @@ -113,10 +61,10 @@ module ValidatesTimeliness def timeliness_date_time_parse(raw_value, type, strict=true) return raw_value.to_time if raw_value.acts_like?(:time) || raw_value.is_a?(Date) - time_array = extract_date_time_values(raw_value, ValidatesTimeliness.send("valid_#{type}_formats".to_sym), strict) + time_array = extract_date_time_values(raw_value, ValidatesTimeliness::Formats.send("valid_#{type}_formats".to_sym), strict) raise if time_array.nil? - if type == :time + if type == :time time_array[3..5] = time_array[0..2] # Rails dummy time date part is defined as 2000-01-01 time_array[0..2] = 2000, 1, 1