0

最終的にすべてがまとまる前に、私はこれに1日半頭を打ちました。これは、物事がどのように機能するかを想定していたために、いくつかのことを根本的に誤解していたためです。図書館では物事がひどく壊れているに違いないと私は考え始めていました。彼らはそうではありませんでした。

このスレッドは、私の質問と何がうまくいったかを共有するためのものです。これは、日時レコードをその場所の現地時間に関連付ける必要があるように思われる場合や、アプリケーションがタイムゾーンの変更に関して奇妙に動作する場合が多いためです。彼らがそうしないからだと思います。その方法は次のとおりです。

簡単な部分は、ここで説明するように、TimeZone gemを使用して場所のタイムゾーンを取得することでした(GMaps4Rails gemを使用して緯度/経度をすでに取得しています): 場所のタイムゾーンを見つけるためのRuby gem

当初は、各イベントのローカルタイムゾーンのみを考慮しているため、DBから保存および取得した後でも、各日時に固有の永続的なタイムゾーンを設定できることを望んでいました。ローカルゾーン以外で日時が必要になるという珍しいまれなケースでは、変換することができました。しかし、MySQLには日時を含むタイムゾーンの概念がなく、すべてを単純な古い日時として格納しているため、これは存在しないと思います。

だから、それは問題ありません-DBはUTCに保存し、私は各方向に変換を行う必要があります。

どのように?(下記参照。)

4

1 に答える 1

0

ユーザーは、イベントの場所に適した現地時間で日時(年、月、日、時、分、秒)を入力します。これを正しいUTC時刻としてDBに保存し、後で取得して正しいタイムゾーンで使用するには、次のレシピを使用します。

  1. 最初に設定する必要がありますTime.zone = timezone-ここで、timezoneは、"America/Toronto"(GeoKit / TimeZoneスタイル)や"Eastern Time (US & Canada)"(Rails 3スタイル)のような名前付きのタイムゾーン文字列です。

    1.9.3p200 :001 > Time.zone = "America/Toronto"
     => "America/Toronto"
    

    GeoKit/TimeZoneスタイルとRails3スタイルの間でマッピングするのは簡単ではないことに注意してください。これにはある程度のサポートがありますが、GeoKitが返すマッピングの多くはRailsマッピングに含まれていないため、GeoKit / TimeZoneの名前は問題なく機能しているように見え、ユーザーが選択できる必要はありません。タイムゾーンは、場所を使用するユーザーのためにすべてを自動的に処理しているためです。

  2. これで、を使用して日時変数を解析および保存でき、パラメーターActiveSupport::TimeWithZoneを使用して適切にエンコードされます。Time.zone

    1.9.3p200 :002 > t = Time.zone.local( 2012, 8, 1, 12, 0, 0 )
     => Wed, 01 Aug 2012 12:00:00 EDT -04:00 
    

    つまり、私の場合、インスタンスを使用したEventモデルの場合event

    event.start = Time.zone.local( year, month, day, hour, min, sec )
    event.save
    

    データがDBに保存されるとき、それはUTCにあります: 2012-08-01 16:00:00.000000

    (以下への呼び出しでシミュレートt.utc

    1.9.3p200 :003 > t = t.utc
     => 2012-08-01 16:00:00 UTC
    
    1.9.3p200 :004 > t.zone
     => "UTC" 
    
  3. これで、DBから読み戻すときに、TimeWithZoneサポートを再度使用して、それがどのタイムゾーンにあるかをDateTimeに通知する必要があります。

    このin_time_zone関数は、基になる日時変数のタイムゾーンを変更しないことに注意してください。

    1.9.3p200 :005 > t.in_time_zone( "America/Toronto" )
     => Wed, 01 Aug 2012 12:00:00 EDT -04:00 
    
    1.9.3p200 :006 > t
     => 2012-08-01 16:00:00 UTC 
    
    1.9.3p200 :007 > t.zone
     => "UTC" 
    

    したがって、関数の出力を日時変数に割り当てる必要があります。

    1.9.3p200 :008 > t = t.in_time_zone( "America/Toronto" )
     => Wed, 01 Aug 2012 12:00:00 EDT -04:00 
    
    1.9.3p200 :009 > t
     => Wed, 01 Aug 2012 12:00:00 EDT -04:00 
    
    1.9.3p200 :010 > t.zone
     => "EDT" 
    
  4. 最後に、警告-使用しないでくださいt.time!その出力は完全に役に立たず、不合理であり、時間とタイムゾーンが同期していません。

    1.9.3p200 :011 > t.time
     => 2012-08-01 12:00:00 UTC 
    
于 2012-08-11T00:58:40.870 に答える