こんにちは!フリーエンジニアの長瀬です。みなさん、Rubyの勉強は進んでいますか?
RubyのTimeには実用的で細かい表現がたくさんあります。Timeを使いこなせば、今後時間の計算に悩むことはなくなるでしょう。この記事では、RubyのTimeの使い方について
- 日時を指定する
- 時間の要素を取り出す
- 時間の演算方法
- 文字列を変換
- formatの指定
- active_supportで使えるメソッドを増やす
というように、基本的な内容から、一歩進んだ内容まで解説していきます。
基本的なTimeの使い方
日時を指定する
それでは、まずは日時を表現する方法を学んでいきましょう。日時を指定する方法には以下のように様々な指定方法があります。
[Timeで日時を指定する方法]
p "Time.now:#{Time.now}" #現在の日時を指定する p "Time.local:#{Time.local(2015,3,14,12,33,12) }" #任意に時刻を指定する p "Time.at:#{Time.at(1343234526)}" #Unixエポックから何秒経過したかて日時を指定する p "Time.mktime:#{Time.mktime(2015,3,14,12,33,12)}" #Time.localと同じ
[実行結果]
"Time.now:2017-07-24 16:32:56 +0900" "Time.local:2015-03-14 12:33:12 +0900" "Time.at:2012-07-26 01:42:06 +0900" "Time.mktime:2015-03-14 12:33:12 +0900"
Time.nowは現在時刻を取得、Time.localまたはTime.mktimeは任意時刻を指定、Time.atはunixエポック(1970年1月1日)から何秒経過したかで日時を指定します。基本的に、現在時刻を取得したいときはTime.nowで、任意の時刻を指定したい時はTime.localを使います。
時間の要素を取り出す
Rubyでは、指定した時刻から年、月、日などの情報を取り出せます。
[指定した時刻から時間要素を取り出す]
time = Time.new p time p time.year #年 p time.month #月 p time.day #日 p time.hour #時 p time.min #分 p time.sec #秒 p "曜日番号:#{time.wday}" #日曜日を0とした曜日番号 p "timeの年の1月1日から何日経過したか:#{time.yday}" #timeの年の1月1日から何日経過したか p "タイムゾーンの確認:#{time.zone}" #タイムゾーンの確認
[実行結果]
2017-07-24 16:47:04 +0900 2017 7 24 16 47 4 "曜日番号:1" "timeの年の1月1日から何日経過したか:205" "タイムゾーンの確認:JST"
このようにRubyのTimeでは年、月、日、分、秒の要素を取り出すだけでなく、曜日番号、指定した日時の年の初めから何日経過したのか、タイムゾーンの確認と様々な情報を取り出せます。
時間の演算方法
rubyのTimeでは秒単位で、時間の加算ができます。また、指定時間同士を秒単位で演算することもできます。
[指定時間の加算、指定時間同士を演算する]
time1= Time.local(2016,7,5,12,00,00) #2016年7月5日12時0分0秒 time2 = Time.now p time1 + 13 #13秒後 p time1 + 24*60*60*3 #3日後 p time1 - 24*60*60*3 #3日前 p time1 + 24*60*60*7 #一週間後 p time1 + 24*60*60*365 #一年後(うるう年ではない) p time2 - time1 #指定日時の差分を秒単位で計算する p (time2-time1)/(24*60*60) #秒単位から日単位に変換する
[実行結果]
2016-07-05 12:00:13 +0900 2016-07-08 12:00:00 +0900 2016-07-02 12:00:00 +0900 2016-07-12 12:00:00 +0900 2017-07-05 12:00:00 +0900 33195982.648783 384.2127621386921
このように、時間を加算したり、指定した時間同士を演算できることを確認できました。サンプルコードのように、24*60*60と秒を日に変換する工夫をすれば、日数を演算できます。
また、後半で説明するactive_supportというgemを使用すれば、さらに同様の計算を簡略化できて便利です。
次に、時間を比べてみましょう。>や<の記号を使うことで、時間軸に沿って大小関係を計算できます。
[指定した日時同士の大小関係を調べる]
time1= Time.local(2016,7,5,12,00,00) time2 = Time.now p time1 > time2 p time1 < time2
[実行結果]
false true
このように、結果は論理値として返されます。time1 > time2では現在時刻のtime2の方が大きいので、falseになっています。
応用的なTimeの使い方
文字列を変換
Rubyでは時間だと判断できるものを自動的にTimeオブジェクトに変換してくれるparseという便利なメソッドがあります。
[parseを使って、Timeオブジェクトに変換する]
require 'time' p Time.parse("2017/4/21 20:13") p Time.parse("03/01/2015") p Time.parse("2017-4-21")
[実行結果]
2017-04-21 20:13:00 +0900 2015-01-03 00:00:00 +0900 2017-04-21 00:00:00 +0900
このように、時間と判別できるものはTimeクラスで扱える形式に変換できます。また、parseを使用するにはrequire ‘time’を先頭に記述して、有効にする必要があります。
formatの指定
Timeではstftimeを使って、formatを指定することもできます。
[strtimeを使って、formatを指定する]
time = Time.now p time p time.strftime("[1]ただいまの時刻は%Y年%m月%d日%H時%M分%S秒です。") p time.strftime("[2]ただいまの時刻は%X") p time.strftime("[3]西暦%Y年、その下二桁は%yです。") p time.strftime("[4]%p%l時、それはつまり%H時") p time.strftime("[5]今日の曜日は%A、略して%a") p time.strftime("[6]今月は%B、略して%b、つまり%m月です。") p time.strftime("[7]今日は%m月%d日です。") p time.strftime("[8]今日の日付と時刻は%xです。") p time.strftime("[9]さらに詳しく言うと、%cです。") p time.strftime("[10]今日は今年の1月1日から%j日目です。") p time.strftime("[11]今週は最初月曜日を一週間の始まりとして%W週目です。") p time.strftime("[12]今週は最初日曜日を一週間の始まりとして%U週目です。") p time.strftime("[13]タイムゾーンは%Z")
[実行結果]
2017-07-24 20:50:08 +0900 "[1]ただいまの時刻は2017年07月24日20時50分08秒です。" "[2]ただいまの時刻は20:50:08" "[3]西暦2017年、その下二桁は17です。" "[4]PM 8時、それはつまり20時" "[5]今日の曜日はMonday、略してMon" "[6]今月はJuly、略してJul、つまり07月です。" "[7]今日は07月24日です。" "[8]今日の日付と時刻は07/24/17です。" "[9]さらに詳しく言うと、Mon Jul 24 20:50:08 2017です。" "[10]今日は今年の1月1日から205日目です。" "[11]今週は最初月曜日を一週間の始まりとして30週目です。" "[12]今週は最初日曜日を一週間の始まりとして30週目です。" "[13]タイムゾーンはJST"
%+特定の文字で、timeで指定した要素を取り出すことができます。また、混同しやすい点として、小文字の%mは月で、大文字の%Mは分です。
入力と出力が比べやすいように番号を振ってありますので、どの要素がどの出力と対応しているかよく確認しておいてください。
active_supportで使えるメソッドを増やす
active_suportをインストールすれば、Timeオブジェクトで使えるメソッドを拡張できます。まだ、active_supportのgemをインストールしていない方は以下のコードを入力してインストールしてください。
gem install activesupport
active_supportにはたくさんのメソッドがあります。まず、何分前、何分後のように時間の前後を計算したい場合には次のようにします。
[時間の前後を計算する]
require 'active_support/time' time = Time.now p time - 3.hour #3時間前 p time + 3.hour #3時間後 p time - 5.days #5日前 p time + 5.days #5日後 p time - 7.week #7週間前 p time + 7.week #7週間後 p time - 11.month #11ヶ月前 p time + 11.month #11ヶ月後 p time - 13.years #13年前 p time + 13.years #13年後
また、計算ではなく定義されたメソッドで同様の計算する場合は次のようにしてください。
[メソッドを使って時間の前後を計算する]
require 'active_support/time' time = Time.now p 3.hour.ago #3時間前 p 3.hour.since #3時間後 p 5.days.ago #5日前 p 5.days.since #5日後 p 7.week.ago #7週間前 p 7.week.since #7週間後 p 9.month.ago #9ヶ月前 p 9.month.since #9ヶ月後 p 11.years.ago #11年前 p 11.years.since #11年後
これらのメソッドを使えば、前半で紹介した時間の演算を書き換えられます。次に日、週、月、年の単位ごとに時間を調整するには次のようにしてください。
[日、週、月、年の単位ごとに時間を調整する]
require 'active_support/time' time = Time.now p time.yesterday #昨日 p time.tomorrow #明日 p time.prev_week #先週 p time.next_week #来週 p time.prev_month #先月 p time.next_month #来月 p time.prev_year #去年 p time.next_year #来年
そして、日、週、月、年、四半期の始め、終わりの日時を計算するには次のようにしてください。
[始め、終わりの日時を計算する]
require 'active_support/time' time = Time.now p time.beginning_of_day #日の初めの日時 p time.end_of_day #日の終わりの日時 p time.beginning_of_week #週の初めの日時 p time.end_of_week #週の終わり日時 p time.beginning_of_month #月の初めの日時 p time.end_of_month #月の終わりの日時 p time.beginning_of_year #年の初めの日時 p time.end_of_year #年の終わりの日時 p time.beginning_of_quarter #四半期の初めの日時 p time.end_of_quarter #四半期の終わりの日時
最後に月、年、四半期の範囲を出力する場合は以下の通りです。
[範囲を出力する]
p time.all_month #今月の範囲 p time.all_quarter #四半期の範囲 p time.all_year #今年の範囲
またactive_supportのメソッドはソースが公開されていますので、こちらを確認してください。
このように、active_supportには非常にたくさんの便利なメソッドが用意されています。一つ一つ、使える場面では使えるようにしておきましょう。
まとめ
いかがでしたか?この記事では、Timeの使い方を解説しました。日時を指定、またはparseを使ってTimeオブジェクトを作成した後は、active_supportの便利なメソッドを使用して、自分好みの時間の出力を試してみてください。
また、作成した時間にformatを指定してあげることで、出力をカスタマイズできます。
Timeには非常に多くのメソッドがあります。なので、もしTimeの使い方について忘れてしまったらこの記事を確認してくださいね!