Skip to content

Instantly share code, notes, and snippets.

@rkuzsma
Last active July 24, 2017 02:46
Show Gist options
  • Save rkuzsma/1277834d935450e587e0bf0897081edd to your computer and use it in GitHub Desktop.
Save rkuzsma/1277834d935450e587e0bf0897081edd to your computer and use it in GitHub Desktop.
TimeUnit helper written in Ruby to convert time expressions with a unit to milliseconds. e.g. 1m -> 60_000, 60s -> 60_000, 5000ms -> 5, 10s -> 10_000
# Created under Apache 2.0 License.
# Author: Rich Kuzsma
# Date: July 23, 2017
# Convert time duration strings like "10s" into milliseconds
module TimeUnit
UNITS_IN_MS = {
'd' => 86_400_000,
'h' => 3_600_000,
'm' => 60_000,
's' => 1_000,
'ms' => 1
}
ALLOWED_REGEX = /^(([0-9]+((\.){1}([0-9])+)*)+)(([dhms]|ms){1})$/
# Examples:
# 3000ms -> 3_000
# 3.5s -> 3_500
# 90s -> 90_000
# 1m -> 60_000
# 1.5m -> 90_000
# 2m -> 120_000
# 1h -> 3_600_000
# 1.0d -> 86_400_000
# 0 -> 0
# 0.001ms -> 0 <-- ! alert !
# 5 -> nil <-- ! alert !
# 55abc -> nil
# abc -> nil
def self.convert_to_ms(time_expr)
return 0 if time_expr.nil? || time_expr.to_s == "0"
matches = time_expr.match(ALLOWED_REGEX)
return nil unless matches
number_part = matches.captures().first
unit_part = matches.captures().last
(number_part.to_f * UNITS_IN_MS[unit_part]).to_i
end
def self.valid_expr?(time_expr)
!time_expr.nil? && (time_expr.to_s == "0" || !ALLOWED_REGEX.match(time_expr).nil?)
end
end
# Example ActiveRecord model validator:
class TimeUnitValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
unless value.nil? || TimeUnit::valid_expr?(value)
record.errors[attribute] << (options[:message] || "is not a valid time unit. Valid examples: 10s, 5ms, 1d, 2h, 3.5m")
end
end
end
# Unit tests
describe TimeUnit do
it 'converts various time expressions' do
# 3000ms -> 3_000
# 90s -> 90_000
# 1m -> 60_000
# 1.5m -> 90_000
# 2m -> 120_000
# 1h -> 3_600_000
# 1h -> 86_400_000
# 5 -> nil
# 0 -> 0
expect(TimeUnit::convert_to_ms("3000ms")).to eq 3_000
expect(TimeUnit::convert_to_ms("3.5s")).to eq 3_500
expect(TimeUnit::convert_to_ms("90s")).to eq 90_000
expect(TimeUnit::convert_to_ms("1m")).to eq 60_000
expect(TimeUnit::convert_to_ms("1.5m")).to eq 90_000
expect(TimeUnit::convert_to_ms("2m")).to eq 120_000
expect(TimeUnit::convert_to_ms("1h")).to eq 3_600_000
expect(TimeUnit::convert_to_ms("1d")).to eq 86_400_000
expect(TimeUnit::convert_to_ms("5")).to be_nil
expect(TimeUnit::convert_to_ms("56ms")).to eq 56
expect(TimeUnit::convert_to_ms("0")).to eq 0
expect(TimeUnit::convert_to_ms("0.001ms")).to eq 0
end
it 'validates incorrect time expressions' do
expect(TimeUnit::valid_expr?("1")).to eq false
expect(TimeUnit::valid_expr?("")).to eq false
expect(TimeUnit::valid_expr?(nil)).to eq false
expect(TimeUnit::valid_expr?(".1")).to eq false
expect(TimeUnit::valid_expr?(".1m")).to eq false
expect(TimeUnit::valid_expr?("1.1")).to eq false
expect(TimeUnit::valid_expr?("5x")).to eq false
expect(TimeUnit::valid_expr?("1m 1m 1m 1m")).to eq false
expect(TimeUnit::valid_expr?("1msm")).to eq false
expect(TimeUnit::valid_expr?("1.5msm")).to eq false
end
it 'validates correct time expressions' do
expect(TimeUnit::valid_expr?("0")).to eq true
expect(TimeUnit::valid_expr?("12345.12345h")).to eq true
expect(TimeUnit::valid_expr?("12345.12345m")).to eq true
expect(TimeUnit::valid_expr?("12345.12345d")).to eq true
expect(TimeUnit::valid_expr?("12345.12345s")).to eq true
expect(TimeUnit::valid_expr?("12345.12345ms")).to eq true
expect(TimeUnit::valid_expr?("12345h")).to eq true
expect(TimeUnit::valid_expr?("12345m")).to eq true
expect(TimeUnit::valid_expr?("12345d")).to eq true
expect(TimeUnit::valid_expr?("12345s")).to eq true
expect(TimeUnit::valid_expr?("12345ms")).to eq true
expect(TimeUnit::valid_expr?("0h")).to eq true
expect(TimeUnit::valid_expr?("0m")).to eq true
expect(TimeUnit::valid_expr?("0d")).to eq true
expect(TimeUnit::valid_expr?("0s")).to eq true
expect(TimeUnit::valid_expr?("0ms")).to eq true
expect(TimeUnit::valid_expr?("0.0h")).to eq true
expect(TimeUnit::valid_expr?("0.0m")).to eq true
expect(TimeUnit::valid_expr?("0.0d")).to eq true
expect(TimeUnit::valid_expr?("0.0s")).to eq true
expect(TimeUnit::valid_expr?("0.0ms")).to eq true
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment