Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Ruby中,从日期时间中减去n小时_Ruby_Datetime_Subtraction_Hour - Fatal编程技术网

在Ruby中,从日期时间中减去n小时

在Ruby中,从日期时间中减去n小时,ruby,datetime,subtraction,hour,Ruby,Datetime,Subtraction,Hour,我有一个Ruby DateTime,它是通过表单填写的。此外,我还有n个小时的表格。我想从之前的日期时间中减去这n个小时。(以获取时间范围) DateTime有两种方法“-”和“如果您在Rails中工作,则存在以下超级直观的可能性: > Time.now - 12.hours => 2019-08-19 05:50:43 +0200 (这也适用于秒、分、日和年) 如果您只使用Ruby,DateTime无法做到这一点,但是Time可以: t = Time.now t = t - (h

我有一个Ruby DateTime,它是通过表单填写的。此外,我还有n个小时的表格。我想从之前的日期时间中减去这n个小时。(以获取时间范围)

DateTime有两种方法“-”和“如果您在Rails中工作,则存在以下超级直观的可能性:

> Time.now - 12.hours
=> 2019-08-19 05:50:43 +0200
(这也适用于秒、分、日和年)

如果您只使用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
是不可变的,所以我甚至不确定
-
编辑:在决定使用我在这里概述的方法之前,先看一看。在Ruby中修改基类的行为似乎不是最好的做法(我可以理解).所以,对这个答案持保留态度


这是我想到的第一件事,但我也不太喜欢

我想你可以通过修补
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
是你想从某个日期中减去的小时数

你没有说你需要如何利用你得到的值,但是把你的小时数除以24,这样你就减去了一天的一小部分,怎么样

mydatetime = DateTime.parse(formvalue)
nhoursbefore = mydatetime - n / 24.0
你可以这样做

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

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

请参见下面的示例:

require 'active_support'

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

如果使用当前日期,可能有一种方法可以使用这种语法来完成您要查找的任务。

您只需减去不到一整天的时间:

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)>
hours=10
分钟=5
秒=64
小时=DateTime.now-(小时/24.0)#
分钟=DateTime.now-(分钟/1440.0)#
秒=DateTime.now-(秒/86400.0)#

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

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

如果您想更明确地了解这样的行为,那么advance方法很好

adjusted = time_from_form.advance(:hours => -n)
您可以使用以下选项:

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

例如
Time.now.ago(7200)
将给出2小时前的日期和时间。

如果允许我使用
Time
而不是
DateTime
(有):


你只需要减去一天的零头

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秒

这是一个完整的解决方案。我不知道问题是否真的问到了这个问题,或者他是否没有发现新的运算符是“h、min和sec的负值被视为从下一个较大单位的末尾向后计数“注意,这会导致意外的结果,因为浮点运算不准确……在这种情况下,Rational类是一种解决方案^^^是的,“DateTime对象一旦创建就不可变。”-这就像Java中的String类。但是:方法“-”:如果x是一个数值,那么创建一个比当前日期早x天的新日期对象,这样我们就可以使用它了。我也考虑过你的想法,但我不确定ruby如何将“hour-x”转换为负值。这就是你觉得它难看的原因吗?嗯,我试试看。让我们看看DateTime类做什么;)不应该是t=t小时*60*60?Thx,固定(并以目前存在的最优雅的可能性进行了更新。对于任何尝试此功能的人来说:它不在stdlib中,而是由ActiveSupport提供的。请参见此处:。谢谢jkp。我对所有这些无法在纯ole irb中工作的示例感到失望。请记住,这仅在Rails上下文中有效。小时()方法来自Rails中的一个日期助手,而不是Ruby标准库。此解决方案需要
要求“活动\u支持/all”
(或者简单地说
Rails
)。这个问题是关于Ruby的,而不是Ruby on Rails。我的意思是:我相信“步骤”不是核心Ruby。但是,你可以像在其他一些答案中一样使用直接减法的Rational策略。1)
步骤
只是为了说明这一点2)
步骤
在标准库中:+1,因为这可能是对DateTime对象执行日期算术的唯一正确方法。我不确定你会如何处理“闰秒”
two_hours_ago = DateTime.now - (2.0/24)