从Ruby中的DateTime减去n小时

时间:2008-10-26 21:46:26

标签: ruby datetime subtraction hour

我有一个从表单填充的Ruby DateTime。此外,我还有n小时的表格。我想从之前的DateTime中减去这n小时。 (获得时间范围)。

DateTime有两种方法“ - ”和“<<”减去日和月,但不是小时。 (API)。有什么建议我怎么做?

11 个答案:

答案 0 :(得分:52)

你可以这样做。

adjusted_datetime = (datetime_from_form.to_time - n.hours).to_datetime

答案 1 :(得分:33)

你可以减去不到一整天:

two_hours_ago = DateTime.now - (2/24.0)

这适用于分钟和其他任何事情:

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)>

如果浮点算术不准确是一个问题,您可以使用Rational或其他一些安全算术实用程序。

答案 2 :(得分:20)

如果你想对这样的行为更加明确,那么advance方法很好。

adjusted = time_from_form.advance(:hours => -n)

答案 3 :(得分:15)

你只需要脱掉一天的时间。

two_hours_ago = DateTime.now - (2.0/24)
  • 1.0 =一天
  • 1.0 / 24 = 1小时
  • 1.0 /(24 * 60)= 1分钟
  • 1.0 /(24 * 60 * 60)= 1秒

答案 4 :(得分:9)

n/24.0技巧无法正常工作,因为浮点数最终会被舍入:

>> 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

但是,您可以使用Rational类:

>> 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

答案 5 :(得分:4)

DateTime无法执行此操作,但Time可以:

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

请注意Time也存储日期信息,这有点奇怪。

如果您必须使用DateTime

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

可能有用,但很难看。该文档说DateTime是不可变的,所以我甚至不确定-<<

答案 6 :(得分:4)

编辑:在您决定使用我在此处列出的方法之前,请先查看this question。似乎在Ruby中修改基类的行为可能不是最佳实践(我可以理解)。所以,请耐心等待这个答案......


MattW's answer是我想到的第一件事,但我也不太喜欢它。

我认为你可以通过修补DateTimeFixnum来做你想要的事情来减少丑陋:

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

然后你可以这样编写你的代码:

some_date = some_date - n.hours

其中n是您希望从some_date

减去的小时数

答案 7 :(得分:4)

你没有说明你需要用什么方法来获得你所获得的价值,但是如何将你的小时数除以24以便减去一天中的一小部分呢?

mydatetime = DateTime.parse(formvalue)
nhoursbefore = mydatetime - n / 24.0

答案 8 :(得分:3)

如果我允许使用Time代替DateTime(有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

答案 9 :(得分:2)

我喜欢在active_support中使用帮助程序。它使它非常干净,易于阅读。

请参阅以下示例:

require 'active_support'

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

如果使用当前日期,可能有一种方法可以使用这种语法来执行您要查找的内容。

答案 10 :(得分:-3)

您可以使用:

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

例如Time.now.ago(7200)将提供从现在起2小时之前的日期和时间。