1

Railsでは、最初はactiverecord用に以下の設定があります。

config.active_record.default_timezone = :utc

ここで、ローカルタイムゾーンを使用したいので、次のように変更しました。

config.active_record.default_timezone = :local

問題は、date/datetime列の既存のすべてのデータをローカルタイムゾーンにシフトする必要があることです。これを達成するための最良の方法は何ですか?


これを行う必要があるのは、ローカルタイムゾーンで集計を行う必要があるためです。たとえば、:group =>'DATE(created_at)'、GROUP BY DATE(created_at)はUTCに基づいていますが、集計したいローカルタイムゾーンで1日。

特定の日時列を移行するための移行ファイルの作成方法を知っていました。しかし、そのようなコラムはたくさんあるので、私はより良い解決策を探しています。

4

4 に答える 4

3

これは危険ですが、移行で行うことは次のとおりです。

class MigrateDateTimesFromUTCToLocal < ActiveRecord::Migration

  def self.up
    # Eager load the application, in order to find all the models
    # Check your application.rb's load_paths is minimal and doesn't do anything adverse
    Rails.application.eager_load!

    # Now all the models are loaded. Let's loop through them
    # But first, Rails can have multiple models inheriting the same table
    # Let's get the unique tables
    uniq_models = ActiveRecord::Base.models.uniq_by{ |model| model.table_name }

    begin
      # Now let's loop
      uniq_models.each do |model|
        # Since we may be in the middle of many migrations,
        # Let's refresh the latest schema for that model
        model.reset_column_information

        # Filter only the date/time columns
        datetime_columns = model.columns.select{ |column| [ :datetime, :date, :time].include? column.type }

        # Process them
        # Remember *not* to loop through model.all.each, or something like that
        # Use plain SQL, since the migrations for many columns in that model may not have run yet
        datetime_columns.each do |column|
          execute <<-SQL
            UPDATE #{model.table_name} SET #{column.name} = /* DB-specific date/time conversion */
          SQL
        end

      rescue
        # Probably time to think about your rescue strategy
        # If you have tested the code properly in Test/Staging environments
        # Then it should run fine in Production
        # So if an exception happens, better re-throw it and handle it manually
      end

    end
  end
end
于 2013-05-05T16:30:34.497 に答える
1

私の最初のアドバイスは、これをしないように強く勧めることです。あなたは傷ついた世界に自分自身を開いています。そうは言っても、これがあなたが望むものです:

class ShootMyFutureSelfInTheFootMigration
  def up
    Walrus.find_each do |walrus|
      married_at_utc = walrus.married_at
      walrus.update_column(:married_at, married_at_utc.in_time_zone)
    end
  end

  def down
    Walrus.find_each do |walrus|
      married_at_local = walrus.married_at
      walrus.update_column(:married_at, married_at_local.utc)
    end
  end
end

次のように、希望するタイムゾーンをDateTime#in_time_zoneに渡すことができます。

central_time_zone = ActiveSupport::TimeZone.new("Central Time (US & Canada)")
walrus.update_column(:married_at, married_at_utc.in_time_zone(central_time_zone))

または、そのままにしておくと、Railsは現在のタイムゾーンを使用します。これはあなたがいる場所ではなく、あなたのサーバーがある場所であることに注意してください。したがって、アイスランドと上海にユーザーがいて、サーバーがカリフォルニアにある場合、すべての「ローカル」タイムゾーンは米国太平洋時間になります。

于 2013-04-30T17:53:34.910 に答える
0

データベースのデータを変更する必要がありますか?代わりに、ローカルタイムゾーンで日付を表示できますか。これは役に立ちますか:Rails3でUTCを現地時間に変換します

于 2013-02-28T02:14:52.590 に答える
0

他の多くの人が言ったように、あなたはおそらくこれをしたくないでしょう。

グループ化する前に、すべてデータベース内で時間を別のゾーンに変換できます。たとえば、postgresでは、山岳部標準時に変換します。

SELECT COUNT(id), DATE(created_at AT TIME ZONE 'MST') AS created_at_in_mst
FROM users GROUP BY created_at_in_mst;
于 2013-05-04T17:29:25.190 に答える