Help us understand the problem. What is going on with this article?

【初心者向け・動画付き】Railsで日時をフォーマットするときはstrftimeよりも、lメソッドを使おう

はじめに:日時の表示に関してよくある問題

何も考えずにViewにcreated_atのような日付を出力すると、「あれっ?」と思うような表示になることがあります。

app/views/users/index.html.erb
<% @users.each do |user| %>
  <tr>
    <td><%= user.name %></td>
    <!-- 作成日時を表示する -->
    <td><%= user.created_at %></td>
    <td><%= link_to 'Show', user %></td>
    <td><%= link_to 'Edit', edit_user_path(user) %></td>
    <td><%= link_to 'Destroy', user, method: :delete, data: { confirm: 'Are you sure?' } %></td>
  </tr>
<% end %>

Screen Shot 2019-07-30 at 20.47.50.png

具体的には以下の2つのポイントが「あれっ?」と思う点だと思います。

  • 日本時間(JST)ではなく、世界標準時(UTC)で表示されてしまう
  • "Tue, 30 Jul 2019 00:12:19 +0000"のようなフォーマットは日本人にとって馴染みがない

この記事ではこの問題を解決する方法を紹介します。

タイムゾーンを日本時間に変更する

最初にタイムゾーンを日本時間にしましょう。
config/application.rbに以下の設定を追加し、サーバーを再起動してください。

config/application.rb
module TimeFormatSandbox
  class Application < Rails::Application
    # ...

    # タイムゾーンを日本時間に設定
    config.time_zone = 'Asia/Tokyo'
  end
end

これで画面に表示された日時が日本時間になります。

Screen Shot 2019-07-30 at 20.52.31.png

日本人が読みやすい日時フォーマットにする

続いて、日時の表示形式を日本人が読みやすいフォーマットに変更しましょう。

:warning: strftimeでも変更できるが、あまりオススメできない

ネットを検索すると以下のようにstrftimeメソッドを使って検索する方法がよく出てきます。

<%= user.created_at.strftime('%Y/%m/%d %H:%M:%S') %>

もちろんこれでも目的は達成できるのですが、他にも日時を表示するViewがあると、'%Y/%m/%d %H:%M:%S'のような書式文字列を繰り返し書かないといけないため、コードがDRYになりません。

DRYでないコードは変更に弱いコードになります。
変更に弱いコードは良くないコードです。

✅ lメソッドでDRYに書式を指定する(オススメ)

Railsにはlメソッドという便利なメソッドがあるので、これを活用しましょう。

以下はlメソッドの使用例です。

<!-- lメソッドを使って書式を指定する -->
<td><%= l user.created_at %></td>

ただし、lメソッドを使うだけでは何も変化がありません。

Screen Shot 2019-07-30 at 20.52.31.png

lメソッドを活用するには、もう少し作業が必要です。

次に行うのはロケールの設定です。
今回は日本人が読みやすい書式にするのが目的なので、アプリケーションのロケールを:jaに設定します。

config/application.rbに以下の設定を追加してください。

config/application.rb
module TimeFormatSandbox
  class Application < Rails::Application
    # ...

    # デフォルトのロケールを日本(ja)に設定
    config.i18n.default_locale = :ja
  end
end

続いて、config/locales/ja.ymlというファイルを作成し、以下のような設定を記述します。

config/locales/ja.yml
ja:
  time:
    formats:
      default: "%Y/%m/%d %H:%M:%S"

上の設定は日時(time)のデフォルトの書式を%Y/%m/%d %H:%M:%Sにするための設定です。

これでサーバーを再起動すると、日本人向けの書式で日時が表示されます。

Screen Shot 2019-07-30 at 21.33.47.png

strftimeメソッドとは異なり、l foo.created_atのような記述でどのViewでも同じ書式が得られるため、コードもDRYになります。

応用: 複数の書式を使い分ける

lメソッド、便利なんだけど、この画面だけは"07/30 09:12"みたいに短く表示したいんだよな〜 :thinking: 」というそこのあなた!
大丈夫です。formatオプションを付けると、書式を切り替えることができます。

<!-- formatオプションを指定する -->
<td><%= l user.created_at, format: :short %></td>

上の例では:shortを指定したので、ja.ymlに対応する書式を設定します。

ja.yml
ja:
  time:
    formats:
      default: "%Y/%m/%d %H:%M:%S"
      short: "%m/%d %H:%M"

ご覧のとおり、書式を切り替えることができました。
Screen Shot 2019-08-02 at 7.13.03.png

Tips: i18n_generatorsでja.ymlを自動生成する

上で作成したconfig/locales/ja.ymlは、i18n_generators gemを使って自動生成すると便利です。
このgemの使い方は以下のとおりです。

まず、Gemfileにi18n_generatorsを追加し、bundle installを実行します。

Gemfile
group :development do
  # ...

  gem 'i18n_generators'
end

次にターミナルから以下のコマンドを実行します。

rails g i18n_locale ja

config/locales/ja.ymlが生成されるので、このファイルを開いてja.time.formats.defaultの書式文字列を編集します。
デフォルトの書式文字列は "%Y年%m月%d日(%a) %H時%M分%S秒 %z" になっているので、これを要件に合わせて変更してください。

なお、i18n_generatorsが生成したja.ymlには他にも日本語ロケール向けの設定がたくさん定義されています。
i18n_generatorsに関する詳しい情報はREADMEを参照してください。

https://github.com/amatsuda/i18n_generators

Tips: View以外ではI18n.lを使う

Viewではlと書くだけでOKですが、lメソッドがヘルパーメソッドとして提供されていない場所(Modelなど)では、lだけではNoMethodErrorになります。
その場合は、lの代わりにI18n.lと書けば、日時をフォーマットすることができます。

ちなみにllocalizeのエイリアスメソッドなので、localizeと書いても構いません。

以下の記述はどれも同じ結果になります。

= l user.created_at
= I18n.l user.created_at
= localize user.created_at
= I18n.localize user.created_at

追記:Time::DATE_FORMATS[:default]を変更するのもオススメしない

日時のフォーマットを変更する方法としてもうひとつ、Time::DATE_FORMATS[:default]の設定を変えるという方法もあるようです。

config/initializers/time_formats.rb
Time::DATE_FORMATS[:default] = '%Y/%m/%d %H:%M:%S'

こうすると、lメソッドもstrftimeも使わずに書式を統一することができます。

<!-- 何もしなくても書式が'%Y/%m/%d %H:%M:%S'になる -->
<td><%= user.created_at %></td>

これだけ見ると「すごく便利じゃん!」と思うかもしれません。
ですが、アプリケーション全体のデフォルト設定が変わってしまうため、予期しない問題を引き起こすかもしれません。
実際に問題が発生する事例は以下の記事で紹介されています。

RailsのTime::DATE_FORMATS[:default]は変更しないほうがいい - Qiita

ですので、この方法もあまりオススメできません。

動画はこちら

この記事の内容はYouTube動画としてアップしています。
動画を見たい方は以下のリンクから視聴してください。

https://youtu.be/QUnWDvPONAo

参考文献

jnchito
SIer、社内SEを経て、ソニックガーデンに合流したプログラマ。 「プロを目指す人のためのRuby入門」の著者。 http://gihyo.jp/book/2017/978-4-7741-9397-7 および「Everyday Rails - RSpecによるRailsテスト入門」の翻訳者。 https://leanpub.com/everydayrailsrspec-jp
https://blog.jnito.com/
sonicgarden
「お客様に無駄遣いをさせない受託開発」と「習慣を変えるソフトウェアのサービス」に取り組んでいるソフトウェア企業
http://www.sonicgarden.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした