Last active
July 24, 2017 02:46
-
-
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
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
# 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