Is there a gem or something to parse strings like \"4h 30m\" \"1d 4h\" -- sort of like the estimates in JIRA or task planners, maybe, with internationalization?
Posting a 2nd answer, as chronic (which my original answer suggested) doesn't give you timespans but timestamps.
Here's my go on a parser.
class TimeParser
TOKENS = {
"m" => (60),
"h" => (60 * 60),
"d" => (60 * 60 * 24)
}
attr_reader :time
def initialize(input)
@input = input
@time = 0
parse
end
def parse
@input.scan(/(\d+)(\w)/).each do |amount, measure|
@time += amount.to_i * TOKENS[measure]
end
end
end
The strategy is fairly simple. Split "5h"
into ["5", "h"]
, define how many seconds "h"
represents (TOKENS
), and add that amount to @time
.
TimeParser.new("1m").time
# => 60
TimeParser.new("1m wtf lol").time
# => 60
TimeParser.new("4h 30m").time
# => 16200
TimeParser.new("1d 4h").time
# => 100800
It shouldn't be too hard making it handle "1.5h"
either, seeing the codebase is as simple as it is.
You can use chronic. It can parse pretty much everything you trhow at it, including "yesterday", "last week" etc.
Update: As the OP points out in the comment, Chronic is for dates, not timespans. See my other answer.
Parse into what though?
This will parse into a Hash:
"4h 30m".split(/\s/).each{|i| h[i.gsub(/\d+/,"")] = i.gsub(/\w/,"")}
Sorry. not familiar with JIRA....
I wrote this method that does it pretty well
def parse_duration(dur)
duration = 0
number_tokens = dur.gsub(/[a-z]/i,"").split
times = dur.gsub(/[\.0-9]/,"").split
if number_tokens.size != times.size
raise "unrecognised duration!"
else
dur_tokens = number_tokens.zip(times)
for d in dur_tokens
number_part = d[0].to_f
time_part = d[1]
case time_part.downcase
when "h","hour","hours"
duration += number_part.hours
when "m","minute","minutes","min","mins"
duration += number_part.minutes
when "d","day","days"
duration += number_part.days
when "w","week","weeks"
duration += number_part.weeks
when "month", "months"
duration += number_part.months
when "y", "year", "years"
duration += number_part.years
else
raise "unrecognised duration!"
end
end
end
duration
end
chronic_duration does this.