48

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

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

4

11 回答 11

61

你可以这样做。

adjusted_datetime = (datetime_from_form.to_time - n.hours).to_datetime
于 2008-10-27T04:57:57.993 回答
38

你可以减去不到一整天:

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或其他一些安全的算术实用程序。

于 2008-12-05T13:40:17.163 回答
21

如果您想更明确地了解此类行为,advance 方法很好。

adjusted = time_from_form.advance(:hours => -n)
于 2011-05-16T00:14:49.373 回答
19

你只需要离开一天的一小部分。

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 秒
于 2015-07-16T07:03:04.603 回答
12

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
于 2009-08-13T20:30:53.163 回答
6

如果您在Rails中工作,则存在以下超级直观的可能性:

> Time.now - 12.hours
=> 2019-08-19 05:50:43 +0200

(这也适用于secondsminutesdaysyears

如果您只使用 Ruby,DateTime则不能这样做,但Time可以:

t = Time.now
t = t - (hours*60**2)

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

如果您必须与DateTime

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

可能有效,但很难看。医生说DateTime是不可变的,所以我什至不确定-<<

于 2008-10-26T21:52:36.947 回答
5

你没有说你需要如何利用你获得的价值,但是将你的小时数除以 24 这样你就减去了一天的一小部分呢?

mydatetime = DateTime.parse(formvalue)
nhoursbefore = mydatetime - n / 24.0
于 2008-10-27T00:00:23.333 回答
4

编辑:在您决定使用我在这里概述的方法之前,请先看看这个问题。在 Ruby 中修改基类的行为似乎不是最佳实践(我可以理解)。所以,对这个答案持保留态度......


MattW的回答是我最先想到的,但我也不是很喜欢。

DateTime我想你可以通过修补和Fixnum做你想做的事来让它变得不那么难看:

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

于 2008-10-26T22:27:21.870 回答
4

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

# Just remove the number of seconds from the Time object
Time.now - (6 * 60 * 60) # 6 hours ago
于 2014-08-14T14:52:23.043 回答
2

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

请参见下面的示例:

require 'active_support'

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

如果使用当前日期,则可能有一种方法可以使用这种语法来完成您正在寻找的事情。

于 2008-10-30T21:22:45.757 回答
-3

你可以使用这个:

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

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

于 2011-12-20T11:00:53.443 回答