LoginSignup
5
4

More than 5 years have passed since last update.

Rails PostgresqlでDate/Datetime型のカラムから"年・月・日"などでデータを抽出する

Posted at

経緯

誕生日情報を持ったDBより"今月が誕生日のユーザー"を抽出したくて調べた際の忘備録です。

環境

Ruby 2.3.0
Rails 5.0.4
Database Postgresql

参考

stackoverflow: ActiveRecord Find By Year, Day or Month on a Date field


schema.rb
create_table "users", force: :cascade do |t|
  t.string   "name"
  t.datetime "birthday"
end

↑こんな感じのDBから今月の誕生日のユーザーの一覧を表示したいという感じです。

SQL関数を利用して抽出する

SQLの日付関数の"EXTRACT"関数を利用して抽出できました。

EXTRACT

EXTRACT(日付 FROM 日付)

日付データからその一部分、たとえば「年」や「月」、または「時間」や「秒」だけを切り出す場合に使用。戻り値は日付型ではなく数値型になる。


※SQLの日付関数はDBMSによって実装がバラバラらしいので利用しているDatabaseによってはうまく抽出できないかもしれません。
EXTRACT関数は"Postgresql"と"Mysql"では利用可能な様子です。

SQLで書くと下記のような感じです。

SELECT CURRENT_TIMESTAMP,
    EXTRACT(YEAR   FROM CURRENT_TIMESTAMP) AS year,
    EXTRACT(MONTH  FROM CURRENT_TIMESTAMP) AS month,
    EXTRACT(DAY    FROM CURRENT_TIMESTAMP) AS day,
    EXTRACT(HOUR   FROM CURRENT_TIMESTAMP) AS hour,
    EXTRACT(MINUTE FROM CURRENT_TIMESTAMP) AS minute,
    EXTRACT(SECOND FROM CURRENT_TIMESTAMP) AS second;
実行結果
now year month day hour minute second
2017-12-07 09:45:33.987+09 2017 12 7 9 45 33.987

Railsでは、上記を参考にしてActiveRecordのwhereメソッドを利用して誕生日月のユーザーを抽出します。

controllers/users_controller.rb
class UsersController < ApplicationController
  def index
    // 現在の日時の月
    now_month = Time.now.month

    @birtyday_users = User.where('extract(month from birthday) = ?', now_month)
  end
end

画面に描画します。

views/users/index.html.erb
<h1>今月誕生日のユーザー</h1>

<% if @birtday_users.any? %>
  <dl>
    <% @birthday_users.each do |user| %>
      <!-- 見やすいように表示を整えてます -->
      <dt><%= user.birthday.strftime('%m月%d日') %></dt>
      <dd><%= user.name %></dd>
    <% end %>
  </dl>
<% end %>

こんな感じで今月の誕生日のユーザーの一覧を描画できました。
EXTRACT関数を使用すれば用途に応じて"年"や"日"毎でデータを抽出して利用できそうです。

5
4
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
4