LoginSignup
1
0

More than 3 years have passed since last update.

当月の範囲選択で最後日が出なくてハマったこと

Last updated at Posted at 2019-08-01

言語

Ruby on Rails

問題

7月1日~7月31日のデータを表示しようとしていたが、
31日のデータだけ一覧に出てこないバグが発生していた。

※追記2:ついでに7月1日0時~8時59分までの間も出ていなかった。

↓ハマっていたコード

date = Date.today
Test.where("? <= created_at && created_at <= ?",date.beginning_of_month,date.end_of_month)

原因

発行されたSQL文を確認したところ、
7月1日0時0分0秒~7月31日0時0分0秒に該当するレコードで検索していた。

date = Date.today
Test.where("? <= created_at && created_at <= ?",date.beginning_of_month,date.end_of_month.end_of_day)
=>SELECT `tests`.* FROM `tests`  WHERE ('2019-07-01' <= exit_time && entrance_time <= '2019-07-31')

解決法

7月1日0時0分0秒~7月31日23時59分59秒に修正すると全部出た。
end_of_dayメソッド追加(その日の終わりの時刻)

date = Date.today
Test.where("? <= created_at && created_at <= ?",date.beginning_of_month,date.end_of_month.end_of_day)
=>SELECT `tests'.* FROM `tests`  WHERE ('2019-07-01' <= exit_time && entrance_time <= '2019-07-31 14:59:59')

所感

日付だけで選択すると0時0分0秒で検索することになるんですね。
意外なところでつまづいてしまい解決に時間がかかりました。

追記(Timeオブジェクトを使用する)

Timeオブジェクトを使用することで、end_of_monthのみで動作するとコメントからのご指摘がありました。ありがとうございます。

Date.today.end_of_month #=> Sat, 31 Aug 2019
Time.current.end_of_month #=> Sat, 31 Aug 2019 23:59:59 JST +09:00

追記2(7月1日0時~8時59分が出ていない)

まだバグがありました。

DBには時差を引いた時間で登録しています。(-9時間で登録)
現実の7月1日0時~8時59分は、DB上では6月30日15時0分~6月30日23時59分になるわけです。

その状況でDBに7月1日からのデータをくれと言ったら出てこないですよね。

解決法2

6月30日15時0分0秒から7月31日14時59分59秒でSQL文を発行する
beginning_of_dayメソッド追加(その日の始まりの時刻)

#発行されたSQL文
date = Date.today
Test.where("? <= created_at && created_at <= ?",date.beginning_of_month.beginning_of_day,date.end_of_month.end_of_day)
=>SELECT `tests'.* FROM `tests`  WHERE ('2019-06-30 15:00:00' <= exit_time && entrance_time <= '2019-07-31 14:59:59')

所感2

長い……長すぎる……。全然スマートじゃないし。
DateオブジェクトではなくTimeオブジェクト使った方が良いですね。
いい勉強になりました。

#発行されたSQL文
date = Date.today
Test.where("? <= created_at && created_at <= ?",date.beginning_of_month.beginning_of_day,date.end_of_month.end_of_day)
=>SELECT `tests'.* FROM `tests`  WHERE ('2019-06-30 15:00:00' <= exit_time && entrance_time <= '2019-07-31 14:59:59')

current = Time.current
Test.where("? <= dcreated_at && created_at <= ?",current.beginning_of_month,current.end_of_month)
=>SELECT `tests'.* FROM `tests`  WHERE ('2019-06-30 15:00:00' <= exit_time && entrance_time <= '2019-07-31 14:59:59')
1
0
3

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
1
0