Subtract n hours from a DateTime in Ruby

2019-01-22 16:58发布

I have a Ruby DateTime which gets filled from a form. Additionally I have n hours from the form as well. I'd like to subtract those n hours from the previous DateTime. (To get a time range).

DateTime has two methods "-" and "<<" to subtract day and month, but not hour. (API). Any suggestions how I can do that?

11条回答
老娘就宠你
2楼-- · 2019-01-22 17:54

The advance method is nice if you want to be more explicit about behavior like this.

adjusted = time_from_form.advance(:hours => -n)
查看更多
Melony?
3楼-- · 2019-01-22 17:59

You just need to take off fractions of a day.

two_hours_ago = DateTime.now - (2.0/24)
  • 1.0 = one day
  • 1.0/24 = 1 hour
  • 1.0/(24*60) = 1 minute
  • 1.0/(24*60*60) = 1 second
查看更多
▲ chillily
4楼-- · 2019-01-22 18:00

n/24.0 trick won't work properly as floats are eventually rounded:

>> DateTime.parse('2009-06-04 02:00:00').step(DateTime.parse('2009-06-04 05:00:00'),1.0/24){|d| puts d}
2009-06-04T02:00:00+00:00
2009-06-04T03:00:00+00:00
2009-06-04T03:59:59+00:00
2009-06-04T04:59:59+00:00

You can, however, use Rational class instead:

>> DateTime.parse('2009-06-04 02:00:00').step(DateTime.parse('2009-06-04 05:00:00'),Rational(1,24)){|d| puts d}
2009-06-04T02:00:00+00:00
2009-06-04T03:00:00+00:00
2009-06-04T04:00:00+00:00
2009-06-04T05:00:00+00:00
查看更多
Fickle 薄情
5楼-- · 2019-01-22 18:03

DateTime can't do this, but Time can:

t = Time.now
t = t-hours*60

Note that Time also stores date information, it's all a little strange.

If you have to work with DateTime

DateTime.commercial(date.year,date.month,date.day,date.hour-x,date.minute,date.second)

might work, but is ugly. The doc says DateTime is immutable, so I'm not even sure about - and <<

查看更多
一夜七次
6楼-- · 2019-01-22 18:04

You can just subtract less than one whole day:

two_hours_ago = DateTime.now - (2/24.0)

This works for minutes and anything else too:

hours = 10
minutes = 5
seconds = 64

hours = DateTime.now - (hours/24.0) #<DateTime: 2015-03-11T07:27:17+02:00 ((2457093j,19637s,608393383n),+7200s,2299161j)>
minutes = DateTime.now - (minutes/1440.0) #<DateTime: 2015-03-11T17:22:17+02:00 ((2457093j,55337s,614303598n),+7200s,2299161j)>
seconds = DateTime.now - (seconds/86400.0) #<DateTime: 2015-03-11T17:26:14+02:00 ((2457093j,55574s,785701811n),+7200s,2299161j)>

If floating point arithmetic inaccuracies are a problem, you can use Rational or some other safe arithmetic utility.

查看更多
登录 后发表回答