0

when属性とを持つタスク モデルがありますduration

create_table "tasks", force: true do |t|
  ...
  t.datetime "when"
  t.integer  "duration"
  ...
end

タスクがアクティブかどうかを確認するメソッドを作成して、ページに表示できるようにしました。これはアクティブな方法です:

  def active?
    if (self.when + self.duration) > Time.now
      true
    end
  end

オブジェクトを検査するためにコンソールで試しました:

t.when + t.duration
=> Sun, 08 Sep 2013 01:01:00 UTC +00:00
DateTime.now
=> Sun, 08 Sep 2013 01:57:13 +0200
t.active?
=> true

しかし、私trueは 1:00 時間と 1 分を入力しましたduration

whenデータベースの列が正しいタイム ゾーンで保存されていないようで、誤った結果が得られます。この問題を解決するには?

4

2 に答える 2

1

データベースの列が正しいタイムゾーンで保存されていないようです

1) Rails は時間をデータベースに挿入する前に自動的に UTC 時間に変換します (これは良いことです)。つまり、時間には "+0000" のオフセットがあります。つまり、データベースに午後 8 時の時刻を保存し、サーバーが「+0600」のオフセットを持つタイムゾーンにある場合、同等の UTC 時刻は午後 2 時であるため、データベースには午後 2 時が保存されます。つまり、ローカル サーバーの時刻は UTC 時刻より 6 時間進んでいます。つまり、サーバーのタイム ゾーンで午後 8 時が UTC タイム ゾーンで午後 2 時であることを意味します。

2)日付を比較するとき、ruby はタイムゾーンのオフセットを考慮します。つまり、ruby はすべての時間を同じタイムゾーンに変換してから時間を比較します。次に例を示します。

2.0.0p247 :086 > x = DateTime.strptime('28-01-2013 08:00:00 PM +6', '%d-%m-%Y %I:%M:%S %p %z')
 => Mon, 28 Jan 2013 20:00:00 +0600 
2.0.0p247 :087 > y = DateTime.strptime('28-01-2013 08:20:00 PM +7', '%d-%m-%Y %I:%M:%S %p %z')
 => Mon, 28 Jan 2013 20:20:00 +0700 
2.0.0p247 :088 > x < y
 => false 

2 つの Datetime オブジェクトの時間を単純に比較すると、x は y より小さくなります。ただし、y の時間は、オフセットが +7 のタイムゾーンで午後 8 時 20 分です。これは、オフセットが +6 のタイムゾーンで午後 7 時 20 分に相当します。したがって、y は実際には x より小さくなります。つまり、Ruby/Rails が生成するのと同じ結果を得るには、同じタイムゾーンに変換された時間を頭の中で比較する必要があります。

3) Rails utc() メソッドを使用して Time.now を UTC 時間に変換できます。

2.0.0p247 :089 > x = Time.now
 => 2013-09-07 8:00:00 +0600 
2.0.0p247 :090 > x.utc
 => 2013-09-07 02:00:00 UTC 

これが、Ruby が Time.now と比較する前に行うことです。task.when + task.duration

4)使用したい時刻で DateTime オブジェクトを作成する方が便利な場合があります。

DateTime.strptime('28-01-2013 08:00:00 PM +0', '%d-%m-%Y %I:%M:%S %p %z'

オフセットをゼロとして指定できるため、UTC 時間への変換を予測する時間を作成する必要はありません。

または、change() メソッドを使用して、時間を変換せずに offset() を変更することもできます。

2.0.0p247 :011 > x = DateTime.now
 => Sun, 08 Sep 2013 00:34:08 +0600 
2.0.0p247 :012 > x.change offset: "+0000"
 => Sun, 08 Sep 2013 00:34:08 +0000 
于 2013-09-08T00:59:06.860 に答える
0

デフォルトでは、ActiveRecord はタイムスタンプを UTC で保存します。RailsでActive Recordのデフォルトのタイムゾーンを変更する方法を参照してください。デフォルトのタイムゾーンを変更するため。

Time#in_time_zone を使用して t.when をタイムゾーンに変換することもできます。 http://api.rubyonrails.org/classes/ActiveSupport/TimeWithZone.htmlを参照してください。

于 2013-09-08T00:45:05.153 に答える