1

私は、ユーザーが1日に最大2つの投稿を非常に簡単に作成できるRailsアプリケーションに取り組んでいます。

私の問題は、さまざまなユーザーが住んでいるさまざまなタイムゾーンをどのように管理するかです。たとえば、私がロンドンに住んでいて、投稿数00.00で開始および終了する日はでリセットされますが、ニューヨークに住んでいる別のユーザーの場合、カウンターは別の時間にリセットされます。(ではありません)この状況をどのように管理できますか?23.5900.0000.00

私は自分自身を説明したいと思います。

更新1

@集まる

コードの問題はtime_zone.utc_offset、間違った時間デルタを与えることです。

1.9.3p194 :123 > time_zone = ActiveSupport::TimeZone.new("Prague")
 => (GMT+01:00) Prague 
1.9.3p194 :124 > DateTime.now.utc.midnight - time_zone.utc_offset
 => Thu, 10 Apr 2003 00:00:00 +0000 

どうして?

その代わりに、私はこのコードが便利だと思いました:

User.posts.where(:created_at => DateTime.now.in_time_zone(time_zone).beginning_of_day..DateTime.now.in_time_zone(time_zone).end_of_day).count

ユーザーの日(ユーザーのタイムゾーンを含む)の間に正しい数のメッセージを取得しているようです。どう思いますか?

更新2

@集まる

違いは何ですか:

User.posts.where(:created_at => DateTime.now.in_time_zone(utc_time_zone).beginning_of_day..DateTime.now.in_time_zone(utc_time_zone).end_of_day).count

とあなたの:

1.9.3p327 :015 > time_zone = ActiveSupport::TimeZone.new("Prague")
 => (GMT+01:00) Prague 
1.9.3p327 :016 > Time.zone.now.utc.midnight - time_zone.utc_offset
 => 2013-02-15 23:00:00 UTC

パフォーマンスとやり方の面で?

更新3

実際、あなたの例のコードは機能しません。ここを見てください:

# WRONG
1.9.3p194 :096 > user.posts.where('created_at > ?', Time.zone.now.utc.midnight - my_time_zone.utc_offset).count
   (0.2ms)  SELECT COUNT(*) FROM "messages" WHERE "messages"."sender_id" = 5 AND (created_at > '2013-02-15 23:00:00.000000')
 => 4 

# CORRECT
1.9.3p194 :098 > users.posts.where(:created_at => DateTime.now.in_time_zone(my_time_zone).beginning_of_day..DateTime.now.in_time_zone(my_time_zone).end_of_day).count
   (0.3ms)  SELECT COUNT(*) FROM "messages" WHERE "messages"."sender_id" = 5 AND ("messages"."created_at" BETWEEN '2013-02-16 23:00:00.000000' AND '2013-02-17 22:59:59.000000')
 => 0
4

2 に答える 2

4

正確にどのように機能させたいかに応じて、2つの解決策を考えることができます。

まず、ユーザーが24時間に2回投稿できるようにすることで、タイムゾーンに依存しないという利点があります。

User.posts.where('created_at > ?', 24.hours.ago).count

それが2を返す場合は、投稿させないでください。

本当に1日に2つ以下の投稿があることを確認したい場合は、次のようにします。

time_zone = ActiveSupport::TimeZone.new(current_user.time_zone)
Users.posts.where('created_at > ?', Time.zone.now.utc.midnight - time_zone.utc_offset).count

User#time_zoneは、Railsによって認識される有効なタイムゾーンを保持する必要があります。

データベースの日時(created_at)はすでにUTCであるため、最初にサーバーの時刻をutcに正規化し、次に時刻を深夜に設定して、タイムゾーンにutcオフセットを適用します。したがって、-7タイムゾーンの人がいる場合は、0700 UTC以降の投稿を検索し、+ 3タイムゾーンの人の場合は、2100UTC以降の投稿を検索します。

ActiveSupport :: TimeZone

2つの違いを明確にするために、いくつかの例を使用します。

最初の例は、月曜日の1200に投稿し、次に1800に投稿するユーザーです。

最初のコードでは、ユーザーは火曜日の0600以降まで再度投稿することはできません。2番目のコードを使用すると、火曜日の0000(深夜以降)に再度投稿できるようになります。

2番目の例は、ユーザーが月曜日の2330に投稿し、次に2350に投稿することです。繰り返しますが、最初の例では、火曜日の2330が過ぎるまで再投稿できませんが、2番目の例では、深夜に再度投稿できるため、0010と0020に投稿でき、50分で4つの投稿が可能になります。

それは本当に投稿制限の目的が何のためであるかに依存します。最初の例は、タイムゾーンに関係なく機能するため、使用と実装がはるかに簡単になります。

FBからタイムゾーン情報を取得する場合は、そのタイムゾーン情報がどの形式であるかを確認してください。これは、ActiveSupport::TimeZone受け入れる有効な文字列ではないと思います。たとえば"Mountain Time (US & Canada)"、MST(-0700)が必要です。FBがMSTの場合は-7または-25200(秒単位で-7時間)のようなものを返している場合は、AS:TZをいじくり回すことなくそれらを使用できます。

RE:アップデート1

これは、DateTimeの代わりにTime.zoneを使用した出力です。

1.9.3p327 :015 > time_zone = ActiveSupport::TimeZone.new("Prague")
 => (GMT+01:00) Prague 
1.9.3p327 :016 > Time.zone.now.utc.midnight - time_zone.utc_offset
 => 2013-02-15 23:00:00 UTC
于 2013-02-16T20:06:14.560 に答える
0

すべての人にUTCタイムゾーンを使用することを検討してください。つまり、StackOverflowは投票にそのアプローチを使用し、正常に機能します。

于 2013-02-16T19:12:49.543 に答える