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条回答
Explosion°爆炸
2楼-- · 2019-01-22 17:38

You didn't say what use you need to make of the value you get, but what about just dividing your hours by 24 so you're subtracting a fraction of a day?

mydatetime = DateTime.parse(formvalue)
nhoursbefore = mydatetime - n / 24.0
查看更多
该账号已被封号
3楼-- · 2019-01-22 17:46

If I'm allowed to use Time instead of DateTime (There are several ways to translate one to another):

# Just remove the number of seconds from the Time object
Time.now - (6 * 60 * 60) # 6 hours ago
查看更多
Rolldiameter
4楼-- · 2019-01-22 17:46

I like using the helpers in active_support. It makes it really clean and easy to read.

See the example below:

require 'active_support'

last_accessed = 2.hours.ago
last_accessed = 2.weeks.ago
last_accessed = 1.days.ago

There might be a way to use that kind of syntax to do what you are looking for, if the current date is used.

查看更多
Anthone
5楼-- · 2019-01-22 17:48

You could do this.

adjusted_datetime = (datetime_from_form.to_time - n.hours).to_datetime
查看更多
戒情不戒烟
6楼-- · 2019-01-22 17:48

You can use this :

Time.now.ago(n*60*60)

For example Time.now.ago(7200) will give the date and time that was before 2 hours from now.

查看更多
Lonely孤独者°
7楼-- · 2019-01-22 17:51

EDIT: Take a look at this question before you decide to use the approach I've outlined here. It seems it may not be best practice to modify the behavior of a base class in Ruby (which I can understand). So, take this answer with a grain of salt...


MattW's answer was the first thing I thought of, but I also didn't like it very much.

I suppose you could make it less ugly by patching DateTime and Fixnum to do what you want:

require 'date'

# A placeholder class for holding a set number of hours.
# Used so we can know when to change the behavior
# of DateTime#-() by recognizing when hours are explicitly passed in.

class Hours
   attr_reader :value

   def initialize(value)
      @value = value
   end
end

# Patch the #-() method to handle subtracting hours
# in addition to what it normally does

class DateTime

   alias old_subtract -

   def -(x) 
      case x
        when Hours; return DateTime.new(year, month, day, hour-x.value, min, sec)
        else;       return self.old_subtract(x)
      end
   end

end

# Add an #hours attribute to Fixnum that returns an Hours object. 
# This is for syntactic sugar, allowing you to write "someDate - 4.hours" for example

class Fixnum
   def hours
      Hours.new(self)
   end
end

Then you can write your code like this:

some_date = some_date - n.hours

where n is the number of hours you want to substract from some_date

查看更多
登录 后发表回答