【Rails】strftimeの使い方ついて徹底解説!

Rails

strftimeとは

日時データを指定したフォーマットで文字列に変換することができるメソッドです。

DateクラスとDateTimeクラスのオブジェクトを指定したフォームで文字列として取得し表示させることができるのがstrftimeメソッドです。

Dateクラスとは
リンクをコピーしました

rubyでは日付クラスであるDateクラスとDateクラスのサブクラスであるDateTimeクラスがあらかじめ定義されています。
このクラスのインスタンスは下記のように取得することができます。

ruby
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
require "date"

# 日付、日時を指定して作成
day1 = Date.new(2020, 1, 30)
day2 = DateTime.new(2020,1,30,12,00,30)

# 現在の日付、日時を作成
today = Date.today
datetime = DateTime.now

p day1
=> #<Date: 2020-01-30>

p day2
=> #<DateTime: 2020-01-30T12:00:30+00:00>

p today
=> #<Date: 2019-01-01>

p datetime
=> #<DateTime: 2019-01-01T12:00:00+09:00>

ただこのままだと「2019-01-01」の形式でしか出力されません。
これを2019年1月1日や2019/1/1など指定したフォームで表示させたいときにstrftimeメソッドを使います。

strftimeの書き方
リンクをコピーしました

strftimeメソッドは下記のように使用します。

ruby
1
2
datetime = DateTime.now
datetime.strftime("書式")

例えば「2019年01月01日」と表示させたい時は下記のように記述します。

shell
1
2
datetime.strftime("%Y年%m月%d日")
=> "2019年01月01日"

指定できる書式を確認しよう
リンクをコピーしました

指定できる書式は下記のものがあります。
それぞれを組み合わせて使うことも可能です。

個別に取得
リンクをコピーしました

※元データは「2019-01-01T12:00:00+09:00」を使用

書式 返り値 説明
%Y 2019 西暦を4桁の数で取得する※西暦1年は「0001」
%m 01 月を必ず2桁の数字で取得する(01-12)
%-m 1 月を1桁か2桁の数字で取得する(1-12)
%d 01 日付を必ず2桁で取得する(01, 02 ... )
%-d 1 日付を1桁か2桁で取得する(1, 2 ... 10, 11 ...)
%H 12 24時間制の時刻を必ず2桁で取得する(00-23)
%-H 12 24時間制の時刻を1桁か2桁で取得する(0-23)
%I 12 12時間制の時刻を1桁か2桁で取得する(1-12)
%M 00 分を取得する(00-59)
%S 00 秒を取得する(00-60)※60はうるう秒

これを使った例を見てみましょう。

shell
1
2
3
4
5
6
date = DateTime.new(2020,1,30,12,00,30)
p date
=> #<DateTime: 2020-01-30T12:00:30+00:00>

p date.strftime("%m月%d日")
=> "01月30日"

このように自分が指定した初期で文字列として取得することができました。

まとめて取得
リンクをコピーしました

※元データは「2019-01-01T12:00:00+09:00」を使用

書式 返り値 説明
%c Tue Jan 01 12:00:00 2019 日付と時刻を省略名で取得する(Sun Jan 01 12:00:00 2019)
%D 01/01/19 日付を「01/12/19」の形式で取得する※「日/時/年」の順
%F 2019-01-01 日付を「2019-07-26」の形式で取得する
%R 12:00 時刻を「12:00」の形式で取得する
%r 12:00:00 PM 時刻を「12:00:00 PM」の形式で取得する
%T 12:00:00 時刻を「12:00:00」の形式で取得する
%v 1-Jan-2019 日付を「1-Jan-2019」の形で取得する※「日/時/年」の順
%X 12:00:00 時刻を「12:00:00」の形式で取得する
%x 01/01/19 日付を「01/12/19」の形式で取得する※「日/時/年」の順

その他の書式
リンクをコピーしました

※元データは「2019-01-01T12:00:00+09:00」を使用

書式 返り値 説明
%A Tuesday 曜日の名称をフルで取得する(Sunday, Monday ... )
%a Tue 曜日の省略名を取得する(Sun, Mon ... )
%B January 月の名称をフルで取得する(January, February ... )
%b Jan 月の省略名を取得する(Jan, Feb ... )
%C 20 世紀を数字で取得する(00, 01 ...)※2020年だと20
%h Jan 月の省略名を取得する(Jan, Feb ... )
%L 000 ミリ秒(ms)を取得する(000-999)
%j 001 1月1日からの通算日を取得する(001-366)
%N 000000000 秒の小数点以下を9桁で取得する※「%6N」で6桁など指定可能
%P pm 午前か午後を小文字で取得する(am, pm)
%p PM 午前か午後を大文字で取得する(AM, PM)
%s 1546344000 1970-01-01 00:00:00 UTC から経過した秒を取得する
%U 00 1 年の週の数を取得する (00-53)※最初の日曜日が第1週の始まり
%u 2 曜日を表す数を取得する(1-7)※1が月曜日, 2が火曜日 ...
%V 01 ISO 8601形式の週の数を取得する(01-53)
%W 00 1 年の週の数を取得する (00-53)※最初の月曜日が第1週の始まり
%w 2 曜日を表す数を取得する(0-6)※0が日曜日, 1が月曜日 ...
%Z +09:00 タイムゾーン(世界標準時間と設定した国の時間の時差)を表示する(+09:00)
%z +0900 タイムゾーン(世界標準時間と設定した国の時間の時差)を表示する(+0900)

実際に使ってみよう
リンクをコピーしました

それではrailsで実際に使ってみましょう。
strftimeはDate型やDateTime型に使うので、保存する時にはdate型やdatetime型を指定する必要があります。
ですのでマイグレーションファイルでdate型やdatetime型でカラムを作成します。

ruby
1
2
t.date :カラム名
t.datetime :カラム名

そしてコントローラーやモデルでインスタンスを取得します。

ruby
1
2
3
def show
  @message = Message.find(params[:id])
end

ビューで日時を表示させます。
2019年01月11日14時15分と表示させたい時は下記のように記述します。

erb
1
<%= @message.date.strftime("%Y年%m月%d日%H時%M分") %>

2019年1月11日14時15分

ただこれだとコードが長くなるのでメソッド化するのが一般的です。
ビューで使うメソッドはモデルに記述しましょう。

ruby
1
2
3
def set_date
  strftime("%Y年%m月%d日%H時%M分")
end

ビューで使うときは下記のように記述します。

erb
1
<%= @message.date.set_date %>

だいぶスッキリしましたね!

曜日を日本語で表示させてみよう
リンクをコピーしました

用意されている書式の中には日本語表記のものがありません。
ですが曜日など日本語で表示したいですね。
ではどういった方法があるでしょうか。

この時に使う書式は「%w」です。
これは曜日を表す数を取得する書式です。
0から6までの数字が取得でき、日曜日が0、月曜日が1といった感じで取得できます。

勘のいい方ならもうわかりますね。
そうです、配列を作ってあげてそこから取得できる数字を使って日本語の曜日名を取得すればいいですね。

ただこの返り値は文字列としての数字なので、to_iメソッドを使って数値オブジェクトに変換する必要があります。

下記のようなコードになります。

shell
1
2
3
4
weeks = ["日","月","火","水","木","金","土"]
num = @message.date.strftime("%w").to_i
week = weeks[num]
=> "日"

これでweekという変数に日本語の曜日名が入りました。

またはwdayメソッド使っても同じことができます。

wdayメソッド
リンクをコピーしました

Dateクラス、DataTimeクラスのオブジェクトに使用すると曜日を0(日曜日)から6(土曜日)の整数で取得できるメソッドです。
このメソッドを使うと下記のように書くこともできます。

shell
1
2
3
weeks = ["日","月","火","水","木","金","土"]
week = weeks[@message.date.wday]
=> "日"

配列は%記法を使うともっと短く書くことができます。

shell
1
2
week = %w(日 月 火 水 木 金 土)[@message.date.wday]
=> "日"

ビューで表示させるには下記のように記述します。

erb
1
<%= @message.date.strftime("%Y年%m月%d日%H時%M分#{week}曜日") %>

time_formatsを使ってみよう
リンクをコピーしました

Dateクラスや、DateTimeクラスのオブジェクトに対してto_sメソッドを使うと日時を文字列として取得することができます。
デフォルトだと下記の形で取得できます。

shell
1
2
3
datetime = DateTime.now
datetime.to_s
=> "2019-01-10T12:00:00+09:00"

この形を変えるためstrftimeメソッドを使っていました。
time_formatsを使うとstrftimeメソッドを使わなくてもto_sメソッドで取得できる形式を指定することができます。

time_formats.rbを作成しよう
リンクをコピーしました

それでは設定の流れを確認していきましょう。
まずはconfig/initializersフォルダ内time_formats.rbを作成します。

このファイルに下記のように定義します。

ruby
1
2
3
4
Date::DATE_FORMATS[:default] = "%Y年%m月%d日"
Date::DATE_FORMATS[:date] = "%m/%d"
DateTime:DATE_FORMATS[:default] = "%Y年%m月%d日 %H時%M分"
DateTime:DATE_FORMATS[:datetime] = "%Y/%m/%d %H:%M"

[:default]とするとto_sメソッドを使った時の取得形式を変更できます。
[:名前]とするとto_s(:名前)の形で指定した形式で取得することができます。
lこの部分は好きな名前をつけることができます。
いくつでも指定が可能です。

上のように定義すると下記のように使うことができます。

shell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
date = Date.today
datetime = DateTime.now

date.to_s
=> "2019年01月10日"

date.to_s(:date)
=> "01/10"

datetime.to_s
=> "2019年01年10日 12時00分"

datetime.to_s(:datetime)
=> "2019/01/10 12:00"

strftimeメソッドと同じように使えるので、覚えておくとよいでしょう。

まとめ

・strftimeメソッドは日時データを指定したフォーマットで文字列に変換することができるメソッドです。