在Ruby中从DateTime减去n个小时

我有一个从窗体填充的Ruby DateTime。 另外我也有从表格n小时。 我想从前一个DateTime中减去那n个小时。 (要获得时间范围)。

date时间有两个方法“ – ”和“<<”减去日和月,但不是小时。 ( API )。 任何build议我怎么能做到这一点?

你可以做到这一点。

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

你可以减去不到一整天:

 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或其他一些安全算术工具。

先进的方法是很好的,如果你想更像这样的行为更加明确。

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

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 

你只需要脱掉一天中的一小部分。

 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秒

如果我可以使用Time而不是DateTime Time (有几种方法可以将一个翻译成另一个 ):

 # Just remove the number of seconds from the Time object Time.now - (6 * 60 * 60) # 6 hours ago 

你没有说出你需要怎样的价值来得到你的价值,但是把你的小时数除以24就可以减去一小部分的时间呢?

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

编辑 :看看这个问题,然后再决定使用我在这里概述的方法。 看来这可能不是最好的做法来修改Ruby中的基类的行为(我可以理解)。 所以,用一粒盐来回答这个问题


MattW的回答是我想到的第一件事,但我也不太喜欢它。

我想你可以通过修补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减去的小时数

DateTime Time不能做到这一点,但Time可以:

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

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

如果你必须使用DateTime

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

可能工作,但是很难看。 文档说DateTime是不可变的,所以我甚-不知道-<<

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

看下面的例子:

 require 'active_support' last_accessed = 2.hours.ago last_accessed = 2.weeks.ago last_accessed = 1.days.ago 

如果使用当前date,可能有一种方法可以使用这种语法来做你正在寻找的东西。

你可以使用这个:

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

例如Time.now.ago(7200)将给出从现在开始2小时之前的date和时间。

Interesting Posts