Eyes, JAPAN Blog > Aws::Recordのdatetime_attrでタイムゾーンを保持する方法

Aws::Recordのdatetime_attrでタイムゾーンを保持する方法

shimizu

こんにちは。今回は、Aws::Recordでの日時型属性の値に、タイムゾーンを持たせる方法についてご紹介します。

AWSのDynamoDBをRubyで活用するためのgemであるAws::Recordは、DynamoDB上のテーブルをRubyオブジェクトにマッピングして扱えるという大変便利なライブラリーです。O/Rマッパーとして機能し、MySQLをActiveRecordで読み書きするような感覚で使うことができます。

例えば、テーブルの構造に合わせて以下のようにプロパティーを定義すると、モデルクラスが作成されます。

class MyModel
  include Aws::Record
  string_attr     :name, hash_key: true
  integer_attr    :post_id
  boolean_attr    :is_active
  datetime_attr   :created_at
end

ここで一つ落とし穴があります。このプロパティーを見てください。

  datetime_attr   :created_at

ご推察の通り、これは日時型の属性を表します。ということで、何気なく日時を代入して保存してから再度読み込んでみます。

item = MyModel.new(
  name: "item01",
  created_at: Time.zone.local(2018, 3, 12, 9, 0)
)
p item.created_at #=> "2018-03-12T09:00:00+09:00"
item.save!

item = MyModel.find(name: "item01")
p item.created_at #=> "2018-03-12T00:00:00+00:00"

おや、午前9時として保存したはずが、読み込み直すと時刻が午前0時になってしまいました。よく見るとタイムゾーンが「+09:00」(JST)から「+00:00」(UTC)に変わっています。指している時刻は保存の前後で同一ですが、指定したローカルタイムゾーンに関係なくUTCの値で保存されてしまうようです。ちょっと直感的ではないですね。

この挙動を修正するには、プロパティー定義の際にオプションとして「use_local_time: true」を指定します。

class MyModel
  include Aws::Record
  string_attr     :name, hash_key: true
  integer_attr    :post_id
  boolean_attr    :is_active
  datetime_attr   :created_at, use_local_time: true
end

こうすることで、指定したタイムゾーンを保持したまま値を保存することができます。

このオプション、記事公開時点では公式のドキュメントに記載がなく、ハマりやすそうなポイントです。実際の開発作業において問題となりました(汗)。いろいろ解決方法を探る中、ライブラリの内部処理用クラスの項目に載っているソースコードにそれとなく記述があることから判明しました。ご参考になれば幸いです!

  • このエントリーをはてなブックマークに追加

コメントは受け付けていません。