moved formats to root module and retrieve from there in validations

added benchmarks for alternates
This commit is contained in:
Adam Meehan
2008-07-17 15:00:18 +10:00
parent 0dcc255901
commit 69ed88a086
2 changed files with 94 additions and 60 deletions

42
benchmark.rb Normal file
View File

@@ -0,0 +1,42 @@
require 'date'
require 'parsedate'
require 'benchmark'
require 'rubygems'
require 'rails/version'
require 'active_support'
require 'active_record'
require 'action_controller'
require 'action_view'
$: << 'lib'
require 'lib/validates_timeliness'
n = 10000
Benchmark.bm do |x|
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/
Time.mktime($1, $2, $3, $3, $5, $6)
end
}
x.report('parsedate') {
n.times do
arr = ParseDate.parsedate("2000-01-04 12:12:12")
Date.new(*arr[0..2])
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') {
n.times do
DateTime.strptime("2000-01-04 12:12:12", '%Y-%m-%d %H:%M:%s')
end
}
end

View File

@@ -1,36 +1,8 @@
module ValidatesTimeliness module ValidatesTimeliness
# 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.
module Validations
mattr_accessor :valid_time_formats mattr_accessor :valid_time_formats
mattr_accessor :valid_date_formats mattr_accessor :valid_date_formats
mattr_accessor :valid_datetime_formats mattr_accessor :valid_datetime_formats
# Error messages added to AR defaults to allow global override if you need.
def self.included(base)
base.extend ClassMethods
error_messages = {
:invalid_datetime => "is not a valid %s",
:before => "must be before %s",
:on_or_before => "must be on or before %s",
:after => "must be after %s",
:on_or_after => "must be on or after %s"
}
ActiveRecord::Errors.default_error_messages.update(error_messages)
base.class_inheritable_hash :valid_time_formats
base.class_inheritable_hash :valid_date_formats
base.class_inheritable_hash :valid_datetime_formats
base.valid_time_formats = self.valid_time_formats
base.valid_date_formats = self.valid_date_formats
base.valid_datetime_formats = self.valid_datetime_formats
end
# The if you want to combine a time regexp with a date regexp then you # 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 # 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 # match strings are still checked for validity, and fail the match if they
@@ -39,7 +11,7 @@ module ValidatesTimeliness
# The proc object should return an array with 1-3 elements with values # 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 # ordered like so [hour, minute, second]. The proc should have as many
# arguments as groups in the regexp or you will get an error. # arguments as groups in the regexp or you will get an error.
self.valid_time_formats = { @@valid_time_formats = {
:hhnnss_colons => /(\d{2}):(\d{2}):(\d{2})/, :hhnnss_colons => /(\d{2}):(\d{2}):(\d{2})/,
:hhnnss_dashes => /(\d{2})-(\d{2})-(\d{2})/, :hhnnss_dashes => /(\d{2})-(\d{2})-(\d{2})/,
:hhnn_colons => /(\d{2}):(\d{2})/, :hhnn_colons => /(\d{2}):(\d{2})/,
@@ -56,7 +28,7 @@ module ValidatesTimeliness
# The proc object should return an array with 3 elements with values # The proc object should return an array with 3 elements with values
# ordered like so year, month, day. The proc should have as many # ordered like so year, month, day. The proc should have as many
# arguments as groups in the regexp or you will get an error. # arguments as groups in the regexp or you will get an error.
self.valid_date_formats = { @@valid_date_formats = {
:yyyymmdd_slashes => /(\d{4})\/(\d{2})\/(\d{2})/, :yyyymmdd_slashes => /(\d{4})\/(\d{2})\/(\d{2})/,
:yyyymmdd_dashes => /(\d{4})-(\d{2})-(\d{2})/, :yyyymmdd_dashes => /(\d{4})-(\d{2})-(\d{2})/,
:yyyymmdd_slashes => /(\d{4})\.(\d{2})\.(\d{2})/, :yyyymmdd_slashes => /(\d{4})\.(\d{2})\.(\d{2})/,
@@ -72,12 +44,32 @@ module ValidatesTimeliness
:d_mmm_yy => [ /(\d{1,2}) (\w{3,9}) (\d{2})/, lambda {|d, m ,y| [unambiguous_year(y), m, d] } ] :d_mmm_yy => [ /(\d{1,2}) (\w{3,9}) (\d{2})/, lambda {|d, m ,y| [unambiguous_year(y), m, d] } ]
} }
self.valid_datetime_formats = { @@valid_datetime_formats = {
:yyyymmdd_dashes_hhnnss_colons => /#{valid_date_formats[:yyyymmdd_dashes]}\s#{valid_time_formats[:hhnnss_colons]}/, :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]}/, :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}))?/ :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.
module Validations
# Error messages added to AR defaults to allow global override if you need.
def self.included(base)
base.extend ClassMethods
error_messages = {
:invalid_datetime => "is not a valid %s",
:before => "must be before %s",
:on_or_before => "must be on or before %s",
:after => "must be after %s",
:on_or_after => "must be on or after %s"
}
ActiveRecord::Errors.default_error_messages.update(error_messages)
end
module ClassMethods module ClassMethods
def full_hour(hour, meridian) def full_hour(hour, meridian)
@@ -121,7 +113,7 @@ module ValidatesTimeliness
def timeliness_date_time_parse(raw_value, type, strict=true) 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) return raw_value.to_time if raw_value.acts_like?(:time) || raw_value.is_a?(Date)
time_array = extract_date_time_values(raw_value, self.send("valid_#{type}_formats".to_sym), strict) time_array = extract_date_time_values(raw_value, ValidatesTimeliness.send("valid_#{type}_formats".to_sym), strict)
raise if time_array.nil? raise if time_array.nil?
if type == :time if type == :time