capture zone offset value in formats to possible usage

This commit is contained in:
Adam Meehan 2009-03-31 21:35:49 +11:00
parent d89266d9f1
commit 1e3c802031
2 changed files with 24 additions and 12 deletions

View File

@ -124,13 +124,13 @@ module ValidatesTimeliness
{ 's' => [ /s{1}/, '(\d{1,2})', :sec ] }, { 's' => [ /s{1}/, '(\d{1,2})', :sec ] },
{ 'u' => [ /u{1,}/, '(\d{1,6})', :usec ] }, { 'u' => [ /u{1,}/, '(\d{1,6})', :usec ] },
{ 'ampm' => [ /ampm/, '((?:[aApP])\.?[mM]\.?)', :meridian ] }, { 'ampm' => [ /ampm/, '((?:[aApP])\.?[mM]\.?)', :meridian ] },
{ 'zo' => [ /zo/, '(?:[+-]\d{2}:?\d{2})'] }, { 'zo' => [ /zo/, '([+-]\d{2}:?\d{2})', :offset ] },
{ 'tz' => [ /tz/, '(?:[A-Z]{1,4})' ] }, { 'tz' => [ /tz/, '(?:[A-Z]{1,4})' ] },
{ '_' => [ /_/, '\s?' ] } { '_' => [ /_/, '\s?' ] }
] ]
# Arguments whichs will be passed to the format proc if matched in the # Arguments which will be passed to the format proc if matched in the
# time string. The key must should the key from the format tokens. The array # time string. The key must be the key from the format tokens. The array
# consists of the arry position of the arg, the arg name, and the code to # consists of the arry position of the arg, the arg name, and the code to
# place in the time array slot. The position can be nil which means the arg # place in the time array slot. The position can be nil which means the arg
# won't be placed in the array. # won't be placed in the array.
@ -146,6 +146,7 @@ module ValidatesTimeliness
:min => [4, 'n', 'n'], :min => [4, 'n', 'n'],
:sec => [5, 's', 's'], :sec => [5, 's', 's'],
:usec => [6, 'u', 'microseconds(u)'], :usec => [6, 'u', 'microseconds(u)'],
:offset => [7, 'z', 'offset_in_seconds(z)'],
:meridian => [nil, 'md', nil] :meridian => [nil, 'md', nil]
} }
@ -175,7 +176,8 @@ module ValidatesTimeliness
end end
matches = full.match(string.strip) matches = full.match(string.strip)
end end
processor.call(*matches[1..7]) if matches last = options[:include_offset] ? 8 : 7
processor.call(*matches[1..last]) if matches
end end
# Delete formats of specified type. Error raised if format not found. # Delete formats of specified type. Error raised if format not found.
@ -208,7 +210,6 @@ module ValidatesTimeliness
compile_format_expressions compile_format_expressions
end end
# Removes formats where the 1 or 2 digit month comes first, to eliminate # Removes formats where the 1 or 2 digit month comes first, to eliminate
# formats which are ambiguous with the European style of day then month. # formats which are ambiguous with the European style of day then month.
# The mmm token is ignored as its not ambigous. # The mmm token is ignored as its not ambigous.
@ -247,17 +248,12 @@ module ValidatesTimeliness
# argument in the position indicated by the first element of the proc arg # argument in the position indicated by the first element of the proc arg
# array. # array.
# #
# Examples:
#
# 'yyyy-mm-dd hh:nn' => lambda {|y,m,d,h,n| md||=0; [unambiguous_year(y),month_index(m),d,full_hour(h,md),n,nil,nil].map {|i| i.to_i } }
# 'dd/mm/yyyy h:nn_ampm' => lambda {|d,m,y,h,n,md| md||=0; [unambiguous_year(y),month_index(m),d,full_hour(h,md),n,nil,nil].map {|i| i.to_i } }
#
def format_proc(order) def format_proc(order)
arg_map = format_proc_args arg_map = format_proc_args
args = order.invert.sort.map {|p| arg_map[p[1]][1] } args = order.invert.sort.map {|p| arg_map[p[1]][1] }
arr = [nil] * 7 arr = [nil] * 7
order.keys.each {|k| i = arg_map[k][0]; arr[i] = arg_map[k][2] unless i.nil? } 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.to_i } }" 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 } }"
eval proc_string eval proc_string
end end
@ -314,6 +310,13 @@ module ValidatesTimeliness
def microseconds(usec) def microseconds(usec)
(".#{usec}".to_f * 1_000_000).to_i (".#{usec}".to_f * 1_000_000).to_i
end 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 end
end end

View File

@ -31,6 +31,10 @@ describe ValidatesTimeliness::Formats do
it "should generate proc which outputs time array with microseconds" do it "should generate proc which outputs time array with microseconds" do
generate_proc('hh:nn:ss.u').call('01', '02', '03', '99').should == [0,0,0,1,2,3,990000] generate_proc('hh:nn:ss.u').call('01', '02', '03', '99').should == [0,0,0,1,2,3,990000]
end end
it "should generate proc which outputs datetime array with zone offset" do
generate_proc('yyyy-mm-dd hh:nn:ss.u zo').call('2001', '02', '03', '04', '05', '06', '99', '+10:00').should == [2001,2,3,4,5,6,990000,36000]
end
end end
describe "validation regexps" do describe "validation regexps" do
@ -132,6 +136,11 @@ describe ValidatesTimeliness::Formats do
time_array = formats.parse('2000-02-01 12:13', :time, :strict => false) time_array = formats.parse('2000-02-01 12:13', :time, :strict => false)
time_array.should == [0,0,0,12,13,0,0] time_array.should == [0,0,0,12,13,0,0]
end end
it "should return zone offset when :include_offset options is true" do
time_array = formats.parse('2000-02-01T12:13:14-10:30', :datetime, :include_offset => true)
time_array.should == [2000,2,1,12,13,14,0,-37800]
end
end end
describe "removing formats" do describe "removing formats" do