从 Ruby 中的日期时间减去 n 小时
-
04-07-2019 - |
题
我有一个 Ruby DateTime,它是从表单中填充的。另外,我还有 n 个小时的时间填写表格。我想从之前的 DateTime 中减去这 n 小时。(获得时间范围)。
DateTime有两个方法“-”和“<<”可以减去日和月,但不能减去小时。(应用程序编程接口)。有什么建议我可以如何做到这一点吗?
解决方案
你可以这样做。
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
或其他一些安全算术实用程序。
如果你想对这样的行为更加明确,那么advance方法很好。
adjusted = time_from_form.advance(:hours => -n)
您只需要休息一天的一小部分即可。
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 秒
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
你没有说明你需要用什么方法来获得你所获得的价值,但是如何将你的小时数除以24以便减去一天中的一小部分呢?
mydatetime = DateTime.parse(formvalue)
nhoursbefore = mydatetime - n / 24.0
编辑:看看这个问题在您决定使用我在此概述的方法之前。似乎在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
DateTime
不能这样做,但Time
可以:
t = Time.now
t = t-hours*60
请注意-
还会存储日期信息,这有点奇怪。
如果您必须使用<<
DateTime.commercial(date.year,date.month,date.day,date.hour-x,date.minute,date.second)
可能有用,但很难看。文档说<=>是不可变的,所以我甚至不确定<=>和<=>
如果我被允许使用Time
而不是DateTime
(有将一种翻译成另一种方式的几种方法):
# Just remove the number of seconds from the Time object
Time.now - (6 * 60 * 60) # 6 hours ago
我喜欢在active_support中使用帮助程序。它使它非常干净,易于阅读。
请参阅以下示例:
require 'active_support'
last_accessed = 2.hours.ago
last_accessed = 2.weeks.ago
last_accessed = 1.days.ago
如果使用当前日期,可能有一种方法可以使用这种语法来执行您要查找的内容。
您可以使用:
Time.now.ago(n*60*60)
例如Time.now.ago(7200)
将提供从现在起2小时之前的日期和时间。