Ruby (With Rails) Convert a String of Time into Seconds

Ruby (with Rails) convert a string of time into seconds?

What you're asking Ruby to do with Time.parse is determine a time of day. That's not what you are wanting. All of the libraries I can think of are similar in this aspect: they are interested in absolute times, not lengths of time.

To convert your strings into time formats that we can work with, I recommend using Chronic (gem install chronic). To convert to seconds, we can do everything relative to the current time, then subtract that time to get the absolute number of seconds, as desired.

def seconds_in(time)
now = Time.now
Chronic.parse("#{time} from now", :now => now) - now
end

seconds_in '48 hours' # => 172,800.0
seconds_in '15 minutes' # => 900.0
seconds_in 'a lifetime' # NoMethodError, not 42 ;)

A couple quick notes:

  • The from now is is why Chronic is needed — it handles natural language input.
  • We're specifying now to be safe from a case where Time.now changes from the time that Chronic does it's magic and the time we subtract it from the result. It might not occur ever, but better safe than sorry here I think.

How to convert raw string of time in Rails?

module DurationParser
class ParseError < StandardError; end
# This is an example of how to extend it with aliases
ALAISES = {
hours: [:h, :hr],
minutes: [:m, :min],
seconds: [:s, :sec]
}
EXP = /^(?<value>[\d*|\.]*)\s*(?<token>\w*)?$/.freeze

# Parses a human readable string into a duration
# @example
# DurationParser.parse('2 hours, 1 minute')
# @return [ActiveSupport::Duration]
def self.parse(string)
string.split(/and|,/).map(&:strip).map do |pair|
matches = pair.match(EXP)
method = token_to_method(matches[:token])
raise ParseError unless method
(matches[:value].to_i).send(method)
end.reduce(&:+)
end

private
def self.token_to_method(token)
ActiveSupport::Duration::PARTS.find do |p|
p == token.downcase.pluralize.to_sym
end || ALAISES.find do |k,v|
v.include?(token.downcase.to_sym)
end&.first
end
end

And a passing spec:

require 'rails_helper'

RSpec.describe DurationParser do
describe '.parse' do
it "handles hours" do
expect(DurationParser.parse('1 h')).to eq 1.hour;
expect(DurationParser.parse('1 hr')).to eq 1.hour;
expect(DurationParser.parse('1 hour')).to eq 1.hour;
expect(DurationParser.parse('3 hours')).to eq 3.hours;
end
it "handles minutes" do
expect(DurationParser.parse('1 m')).to eq 1.minute;
expect(DurationParser.parse('1 min')).to eq 1.minute;
expect(DurationParser.parse('1 minute')).to eq 1.minute;
expect(DurationParser.parse('2 minutes')).to eq 2.minutes;
end
it "handles seconds" do
expect(DurationParser.parse('1 s')).to eq 1.second;
expect(DurationParser.parse('1 sec')).to eq 1.second;
expect(DurationParser.parse('1 second')).to eq 1.second;
expect(DurationParser.parse('15 seconds')).to eq 15.seconds;
end
it "handles comma delimeted strings" do
expect(DurationParser.parse('1 hour, 3 minutes, 15 seconds')).to eq(
1.hour + 3.minutes + 15.seconds
)
end
it "handles 'and' delimeted strings" do
expect(DurationParser.parse('1 hour and 3 minutes and 15 seconds')).to eq(
1.hour + 3.minutes + 15.seconds
)
end
it "handles mixed delimeter strings" do
expect(DurationParser.parse('1 hour and 3 minutes, 15 seconds')).to eq(
1.hour + 3.minutes + 15.seconds
)
end
it "raises when a bad token is passed" do
expect { DurationParser.parse('25 sols') }.to raise_error(DurationParser::ParseError)
end
end
end

Of course if you want something reliably machine readable you want to use ISO8601 durations and not a wonky string parser.

Ruby: Convert time to seconds?

You can use DateTime#parse to turn a string into a DateTime object, and then multiply the hour by 3600 and the minute by 60 to get the number of seconds:

require 'date'

# DateTime.parse throws ArgumentError if it can't parse the string
if dt = DateTime.parse("10:30") rescue false
seconds = dt.hour * 3600 + dt.min * 60 #=> 37800
end

As jleedev pointed out in the comments, you could also use Time#seconds_since_midnight if you have ActiveSupport:

require 'active_support'
Time.parse("10:30").seconds_since_midnight #=> 37800.0

How to convert a time string to number of seconds in Ruby

To convert your string to a time use

new_time = Time.parse(time_string)

This will return a Time object. Then you can just subtract the time at midnight from your given time like so:

midnight = Time.local(2010,2,13,0,0,0)
seconds = (new_time - midnight).to_i # Number of seconds as an integer, .to_f works too

Of course, for Time.local, you should use today's date, not the hardcoded values as above.

Convert from format date string to unix (epoch) time value

To convert the string into an array of integers, look into split('/'), to turn that into a unix time stamp look here (you probably want to_i but be warned that it incorporates your local time zone).



Related Topics



Leave a reply



Submit