From cec1e06899426dcd7669c0cf2a6442539c690eeb Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Wed, 23 Jan 2008 21:03:40 -0500 Subject: [PATCH] Improved rules parsing and storage, making the method able to accept more rules. Improved test, adding summary and colors. Added thorough documentation for usage. --- timeparse/timeparse.rb | 132 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 116 insertions(+), 16 deletions(-) diff --git a/timeparse/timeparse.rb b/timeparse/timeparse.rb index aae36c8..1171818 100755 --- a/timeparse/timeparse.rb +++ b/timeparse/timeparse.rb @@ -1,29 +1,121 @@ #!/usr/bin/env ruby -wKU -def parse_time(field) +require 'date' + +# colorize +def color(text, color_val) + "#{color_val}#{text}\e[0m" +end +# colors +def green(text); color(text, "\e[32m"); end +def red(text); color(text, "\e[31m"); end +def magenta(text); color(text, "\e[35m"); end +def yellow(text); color(text, "\e[33m"); end +def blue(text); color(text, "\e[34m"); end + +# parses the given time value (a string in the format "hh:mm:ss"), respecting +# a certain set of rules and modifying the given numbers to honor them, then +# returns the fully parsed value back, either as a DateTime object or as a +# String. +# +# == usage +# +# simply calling parse_time with the appropriate string will return +# similar results to the following: +# +# '00:123:00' becomes '02:03:00' +# '00:12:15' becomes '00:12:15' +# '01:00:00' becomes '01:00:00' +# '00:60:00' becomes '01:00:00' +# '00:00:00' becomes '00:00:00' +# '00:10:121' becomes '00:12:01' +# '30:12:61' becomes '24:00:00' +# '' becomes '00:00:00' +# +# also, #parse_time provides you the ability to add your own rules: +# +# parse_time( +# val, +# proc do |h,m,s| +# # do stuff +# [h,m,s] +# end, +# # halves all time values +# proc{|h,m,s|[h/2, m/2, s/2]} +# ) +# +# you can also add one rule to the beginning of the rule list by providing a +# block to the method: +# +# parse_time(val) {|h,m,s| [h*2, m*2, s*2]} +# +# which will double all the time as the very first step. +def parse_time(field, to_string = true, *additional_rules, &block_rule) + # establish rules; takes in hours, minutes, and seconds and expects an array + # with the new hours, minutes, and seconds. + # + # for example: + # + # proc do |h, m, s| + # # do magic things + # [h, m, s] + # end + # + # Calling is handled internally. + rules = [ + # when seconds is greater than 59, increase minutes by that many seconds + # divided 60 and leaving the remainder as the seconds. + proc do |hours, minutes, seconds| + if seconds > 59 + minutes += seconds / 60 + seconds = seconds % 60 + end + [hours, minutes, seconds] + end, + + # when minutes is greater than 59, increase hours by the dividend of + # minutes divided by 60, minutes being assigned the remainder. + proc {|h,m,s|[(h+(m/60)),(m%60),s]}, + + # when hours is larger than 24, set time to 24:00:00 + proc {|h,m,s|h > 24 ? [24, 0, 0] : [h, m, s]}, + # TODO: Evaluate how this will affect database representation and + # calculations, possibly removing. + + # add any additional rules. + *additional_rules + + # finish, adding the supplied block if it's set as the first rule + ].unshift *(block_given? ? [block_rule] : []) + # parse field for data values field, match, hours, minutes, seconds = *field.match(/((\d{2,}):(\d{2,}):(\d{2,}))/) hours, minutes, seconds = Integer(hours), Integer(minutes), Integer(seconds) - # correct errors - if seconds > 59 - minutes += seconds / 60 - seconds = seconds % 60 - end - if minutes > 59 - hours += minutes / 60 - minutes = minutes % 60 - end - if hours > 24 - hours = 24 + # run rules + rules.each do |rule| + hours, minutes, seconds = *rule.call(hours, minutes, seconds) end - # return value - "%02d:%02d:%02d" % [hours, minutes, seconds] + # format final value + value = ("%02d:%02d:%02d" % [hours, minutes, seconds]) + + # return appropriate object + if to_string + # returns a String, formatted: "00:00:00" + return value + else + # returns an equivalent DateTime object to the value (determined by + # DateTime.parse). + DateTime.parse(value) + end end if $0 == __FILE__ - [ + puts "\e[31mTesting parse_time():\e[0m" + elapsed = 0.0 + puts "\e[0m" << "="*60 << "\e[0m" + examples = [ "00:123:00", "00:12:15", "01:00:00", @@ -33,6 +125,14 @@ if $0 == __FILE__ "30:12:61", "" ].each do |time| - puts "%12s becomes %s" % ["'#{time}'", "'#{parse_time(time)}'"] + start = Time.now + parsed_time = parse_time(time) + finish = Time.now + puts "%25s => %s" % ["'\e[33m#{time}\e[0m'", "'\e[35m#{parsed_time}\e[0m'"] + elapsed += finish - start end + puts "\e[0m" << "="*60 << "\e[0m" + puts "Finished testing \e[32m#{examples.length} examples\e[0m." + puts "Elapsed time: \e[32m#{elapsed} seconds\e[0m." + puts "Avg parse time: \e[32m#{elapsed/examples.length} seconds\e[0m." end -- 2.11.4.GIT