質問

フォームから入力されるRuby DateTimeがあります。さらに、フォームからn時間もあります。これらのn時間を前のDateTimeから差し引きたいです。 (時間範囲を取得するには)。

DateTimeには2つのメソッド<!> quot;-<!> quot;があります。および<!> quot; <!> lt; <!> lt; <!> quot;日と月を減算しますが、時間は減算しません。 ( API )。どのようにそれを行うことができますか?

役に立ちましたか?

解決

これを行うことができます。

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

他のヒント

1日未満を差し引くことができます:

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)

1日のほんの一部を外すだけです。

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秒

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

取得した値をどのように使用する必要があるかは言わなかったが、1日の端数を差し引くために時間を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は次のことができます。

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

-には日付情報も格納されていることに注意してください。これは少し奇妙です。

<<

で作業する必要がある場合
DateTime.commercial(date.year,date.month,date.day,date.hour-x,date.minute,date.second)

動作する可能性がありますが、isいです。ドキュメントには、<=>は不変であると書かれているため、<=>および<=>

についてもわかりません。

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時間前の日時を示します。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top