Reputation: 48903
I've got code that does time tracking for employees. It creates a counter to show the employee how long they have been clocked in for.
This is the current code:
start_time = Time.parse(self.settings.first_clock_in)
total_seconds = Time.now - start_time
hours = (total_seconds/ 3600).to_i
minutes = ((total_seconds % 3600) / 60).to_i
seconds = ((total_seconds % 3600) % 60).to_i
This works fine. But because Time is limited to the range of 1970 - 2038 we are trying to replace all Time uses with DateTimes. I can't figure out how to get the number of seconds between two DateTimes. Subtracting them yields a Rational which I don't know how to interpret, whereas subtracting Times yields the difference in seconds.
NOTE: Since Ruby 1.9.2, the hard limit of Time is removed. However, Time is optimized for values between 1823-11-12 and 2116-02-20.
Upvotes: 86
Views: 84212
Reputation: 4805
No need to rely on fractions or helper functions. It's much simpler than that. Time
itself is integer underneath. Here's the Ruby way:
stop.to_i - start.to_i
Example:
#!ruby
> start = Time.now
=> 2016-06-21 14:55:36 -0700
> stop = start + 5.seconds
=> 2016-06-21 14:55:41 -0700
> stop.to_i - start.to_i
=> 5
DateTime
on the other hand returns a Rational
after subtraction, which is a fraction of a day. So you can still do:
((dt2 - dt1) * 24 * 60 * 60).to_i
or
((dt2 - dt2) * 86400).to_i
By example:
#!ruby
> dt1 = DateTime.new(2024, 3, 11, 12, 0, 0)
> dt2 = DateTime.new(2024, 3, 11, 12, 30, 0)
> (dt2 - dt1)
=> (1/48)
> (dt2 - dt1).class
=> Rational
> difference_in_seconds = ((dt2 - dt1) * 24 * 60 * 60).to_i
=> 1800
Upvotes: 28
Reputation: 557
Or, more readably:
diff = datetime_1 - datetime_2
diff * 1.days # => difference in seconds; requires Ruby on Rails
Note, what you or some other searchers might really be looking for is this:
diff = datetime_1 - datetime_2
Date.day_fraction_to_time(diff) # => [h, m, s, frac_s]
Upvotes: 54
Reputation: 275
Define a Ruby function like this,
def time_diff(start_time, end_time)
seconds_diff = (start_time - end_time).to_i.abs
days = seconds_diff / 86400
seconds_diff -= days * 86400
hours = seconds_diff / 3600
seconds_diff -= hours * 3600
minutes = seconds_diff / 60
seconds_diff -= minutes * 60
seconds = seconds_diff
"#{days} Days #{hours} Hrs #{minutes} Min #{seconds} Sec"
end
And Call this function,
time_diff(Time.now, Time.now-4.days-2.hours-1.minutes-53.seconds)
Upvotes: 1
Reputation: 1510
there's a method made for that:
Time.now.minus_with_coercion(10.seconds.ago)
equals 10.
Source: http://apidock.com/rails/Time/minus_with_coercion
Hope I helped.
Upvotes: 1
Reputation: 1451
I am using ruby-2.1.4 and for me the following worked
Time.now - Time.new(2014,11,05,17,30,0)
gave me the time difference in seconds
reference: ruby doc
Upvotes: 8
Reputation: 4431
You can convert them to floats with to_f
, though this will incur the usual loss of precision associated with floats. If you're just casting to an integer for whole seconds it shouldn't be big enough to be a worry.
The results are in seconds:
>> end_time.to_f - start_time.to_f
=> 7.39954495429993
>> (end_time.to_f - start_time.to_f).to_i
=> 7
Otherwise, you could look at using to_formatted_s
on the DateTime object and seeing if you can coax the output into something the Decimal
class will accept, or just formatting it as plain Unix time as a string and calling to_i
on that.
Upvotes: 34
Reputation: 1353
Subtracting two DateTimes returns the elapsed time in days, so you could just do:
elapsed_seconds = ((end_time - start_time) * 24 * 60 * 60).to_i
Upvotes: 98