2008-10-26 97 views
39

我有一個從窗體填充的Ruby DateTime。此外,我還有n小時的表格。我想從前一個DateTime中減去這n個小時。 (要獲得時間範圍)。從Ruby中的日期時間減去n小時

DateTime有兩種方法「 - 」和「< <」來減去日和月,但不是小時。 (API)。任何建議如何我可以做到這一點?

回答

46

你可以這樣做。

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

請記住,這隻適用於Rails環境。 hours()方法來自Rails中的日期幫助程序之一,而不是來自Ruby標準庫。 – 2011-11-18 16:41:35

+43

令人沮喪的是,有那麼多人認爲Ruby = Rails – 2014-01-11 03:04:38

3

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是不變的,所以我甚至不能肯定-<<

+0

是的,「DateTime對象一旦創建就是不可變的。」 - 它就像Java中的String類。儘管如此:**方法「 - 」:**「如果x是一個數值,則創建一個比當前時間早x天的新Date對象。」,所以我們可以使用它。我也想過你的想法,但我不確定ruby如何將「小時x」的負值轉換成負值。這是什麼讓你醜陋?那麼,我試試看。讓我們來看看DateTime類的功能;) – 2008-10-26 21:56:16

3

編輯:在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

+0

這是一個完整的解決方案。我不知道這個問題是真的被問到,還是他沒有發現新操作員是 「h,min和sec的負值被認爲是從下一個更大單位的末尾向後倒數」 – Jonke 2008-10-27 00:10:45

3

你沒有說你需要做什麼用的VA假如你得到了,那麼把你的小時數除以24就可以減去一小部分時間呢?

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

我喜歡在active_support中使用助手。它使它非常乾淨,易於閱讀。

見下面的例子:

require 'active_support' 

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

有可能是使用那種語法,做你所尋找的,如果使用當前日期的方式。

26

你可以只減去小於一整天:

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

+3

請注意,這會導致意外的結果,因爲浮點算術不準確...... – JtR 2010-11-21 19:44:48

+2

在這種情況下,Rational類是一種解決方案^^ – Smar 2015-03-11 15:32:59

10

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 

你可以,但是,使用,而不是理性類:

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

也不是核心Ruby。 – dfrankow 2012-02-17 15:47:54

20

先遣方法是好的,如果你想對此類行爲更明確。

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

您可以使用此:

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

例如Time.now.ago(7200)會給那是前2小時內從現在的日期和時間。

10

你只需要脫下一天的部分。

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