-
-
Save jeremyf/d1adb9b5fa2e2a53675a7203693c020f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Provides a lookup map for a given unit and how many seconds one of | |
# those units represents. | |
TIME_UNIT_TO_SECONDS_MAP = { | |
"h" => 60 * 60, # seconds in an hour | |
"m" => 60, # seconds in a minute | |
"s" => 1 # seconds in a second | |
} | |
def convert_to_seconds_via_string_splitting(input) | |
# Split on one or more numerals | |
# | |
# Because of the structure, the first element should always be an | |
# empty string. We may want to guard better. On the other hand, | |
# if the user's giving us junk, whatever. | |
units = input.split(/\d+/)[1..-1] | |
return input.to_i unless units | |
# Split on a single alpha character | |
times = input.split(/[a-z]/) | |
seconds = 0 | |
units.each_with_index do |unit, i| | |
seconds += TIME_UNIT_TO_SECONDS_MAP.fetch(unit, 0) * times[i].to_i | |
end | |
return seconds | |
end | |
# This regular expression is a unduly complicated, but highlights an | |
# alternative approach. | |
# | |
# Note there are nine capture regions: | |
#p | |
# 1,4,7: The scalar and it's unit (e.g., "10s", "1h") | |
# 2,5,8: The scalar (e.g., "10", "1") | |
# 3,6,9: The unit (e.g., "s", "h") | |
THREE_TIMES_AND_UNITS_REGEXP = | |
/\A((\d+)([a-z]))?((\d+)([a-z]))?((\d+)([a-z]))?\Z/ | |
def convert_to_seconds_via_verbose_regexp(input) | |
match = THREE_TIMES_AND_UNITS_REGEXP.match(input) | |
seconds = 0 | |
return input.to_i unless match | |
seconds += match[2].to_i * | |
TIME_UNIT_TO_SECONDS_MAP.fetch(match[3], 0) if match[1] | |
seconds += match[5].to_i * | |
TIME_UNIT_TO_SECONDS_MAP.fetch(match[6], 0) if match[4] | |
seconds += match[8].to_i * | |
TIME_UNIT_TO_SECONDS_MAP.fetch(match[9], 0) if match[7] | |
seconds | |
end | |
# This regular expression is a simplified version of | |
# THREE_TIMES_AND_UNITS_REGEXP. | |
# | |
# Note there are three capture regions: | |
# | |
# 1: The scalar (e.g., "10", "1") | |
# 2: The unit (e.g., "s", "h") | |
TIME_AND_UNIT_REGEXP = /(\d+)([a-z])/ | |
def convert_to_seconds_via_regexp_scanner(input) | |
seconds = 0 | |
matched = false | |
input.scan(TIME_AND_UNIT_REGEXP) do |time, unit| | |
next if time.nil? || unit.nil? | |
matched = true | |
seconds += time.to_i * | |
TIME_UNIT_TO_SECONDS_MAP.fetch(unit, 0) | |
end | |
return seconds if matched | |
input.to_i | |
end | |
[ | |
["1h4m2s", 3842], | |
["1m", 60], | |
["1s2m", 121], | |
["1d", 0], | |
["10", 10], | |
].each do |given, expected| | |
puts "Given: #{given}\tExpected: #{expected}" | |
[ | |
:convert_to_seconds_via_string_splitting, | |
:convert_to_seconds_via_verbose_regexp, | |
:convert_to_seconds_via_regexp_scanner, | |
].each do |method| | |
returned_value = __send__(method, given) | |
if returned_value == expected | |
puts "\tSuccess for #{method}." | |
else | |
puts "\tFailure for #{method}. Got: #{returned_value}" | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment