Skip to content

Instantly share code, notes, and snippets.

@jeremyf
Created November 18, 2021 17:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jeremyf/d1adb9b5fa2e2a53675a7203693c020f to your computer and use it in GitHub Desktop.
Save jeremyf/d1adb9b5fa2e2a53675a7203693c020f to your computer and use it in GitHub Desktop.
# 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