5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Railsでdatetimeのミリ秒でハマった話

Last updated at Posted at 2022-12-23

はじめに

仕事でコード書いていると、年に1回ぐらい日付関係の処理ではまるので、備忘録に記事を、まとめてました。

前提

DynamoDBを使用し、モデルは以下のように設定しています。

class Notification
  include Dynamoid::Document
  include Draper::Decoratable

  table name: :notification, key: :notification_id
  range :notified_at, :datetime

  field :name, :string

  private

  def create_attrs(notification_id, name)
      base = { id: id, notified_at: Time.zone.now, name: name }
  end
end

まず、何にハマったかですが、notification_idとnotified_atでユニークな値を取得できる様にしたのですが、なぜか取得できない。。。

1つデータを作ったものとします。

Notification.find('1', range_key: Notification.last.notified_at)

=> #<Notification:0x00000040hogehoge>が取得できる

実際にブラウザ側からパラメーターを送って取得する場合
DateTime型で送られてもparamsで一旦文字列に変換され、datetimeに戻す必要があるので、下記の様に取得してみる

Notification.find('1', range_key: Notification.last.notified_at.to_s.to_datetime)
=> Dynamoid::Errors::RecordNotFound

なんで?!となった

結論

DiteTime型をStringに変換した際、ミリ秒部分がなくなり、再びDateTime型にしても、ミリ秒部分がなくなってしまうためであった。

説明

Notification.last.notified_at
=> Mon, 12 Dec 2022 07:38:49 +0000

Notification.last.notified_at.to_s.to_datetime
=> Mon, 12 Dec 2022 07:38:49 +0000

上記の様に見ると同じ値である様に見える。
しかし

Notification.last.notified_at == Notification.last.notified_at.to_s.to_datetime

=> false

これはDateTime型だと、ミリ秒までが表示されていないだけで、実際はミリ秒の値まであるため、falseとなっている。
この違いがTime型に変換してみるとよくわかった。

Notification.last.notified_at.to_time
=> 2022-12-12 07:38:49.997983757 +0000

Notification.last.notified_at.to_s.to_datetime.to_time
=> 2022-12-12 07:38:49 +0000

ではどうすれば、

Notification.last.notified_at

=> Mon, 12 Dec 2022 07:38:49 +0000

Notification.last.notified_at.iso8601(9).to_s.to_datetime
=> Mon, 12 Dec 2022 07:38:49 +0000

Notification.last.notified_at == Notification.last.notified_at.iso8601(9).to_s.to_datetime
=> true
Notification.find('1', range_key: Notification.last.notified_at.iso8601(9).to_s.to_datetime)
=> #<Notification:0x00000040hogehoge>

取得できました。

終わりに

今回、ハマってしまったポイントとしては、DateTime型では表示されないだけで、ミリ秒の値も持っているということを認識してなかった点にあったと思います。
私だけかもしれませんが、つい表示されないとないものと思い込んでしまうことがあるので、備忘録として記事を残したいと思いました。

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?