時刻や日付を扱うメソッドの基本情報まとめ【Ruby】【Rails】

MEMO

本記事はメモ記事ですので修正・加筆する可能性が高いです。
ご了承下さい。

自分も勉強しながらなので記事はちょっとずつ整っていく予定です。


私の環境

環境

  • Windows Subsystem for Linux (Ubuntu 18.04)
  • Rails 5.2.0
  • Ruby 2.5.3

超基本事項

とりあえずこれは知ってないとマズいという事項を。
普段、そんなにいろいろ暗記する必要はないと思う、とは言っていますがこれくらいは暗記必須ですね。

Timeクラス

Time.now
 #=> 2019-02-25 21:03:19 +0900  # ENV['TZ']またはOSのTimeZoneを見ている
Time.current
 #=> Mon, 25 Feb 2019 12:03:19 UTC +00:00  # Railsのapplication.rbのconfig.time_zoneをみている

Time.new(2019,1,2,3,4,5)
 #=> 2019-01-02 03:04:05 +0900

『今』の情報がほしければ『Time.now』。これは覚えておきましょう。
『Time.current』でも今の情報が取れますがnowとは参照するタイムゾーンが異なります(タイムゾーンに関しては後述)。

特定の日時オブジェクトがほしければ『Time.new』に年、月、日、時、分、秒の順に引数を指定すればOKです。

Dateクラス

Date.today
 #=> Mon, 25 Feb 2019

Date.new(2019,1,2)
 #=> Fri, 01 Mar 2019

『今日』という情報がほしければ『Date.today』。必須ですが覚えやすいですよね。
これに関しても『Date.current』でTimeと同じようにapplication.rbの設定を参照する『今日』が取得できます。

こちらも『Date.new』に年、月、日の引数を指定すればOKです。

DateTimeクラス

DateTime.now
 #=> Mon, 25 Feb 2019 21:03:27 +0900

Dateクラスのサブクラスで時間情報も扱えるようになったもの。

時間情報があるので『DateTime.now』で今の情報が取れます。
これも『DateTime.current』は先の2つと同様です。

ここで『Timeクラスとどう違うのか』という疑問が生まれますが、多少の違いはあれど大きな差はなく『基本的にTimeクラスを使っておけばいい』らしいので、今回は難しいことを考えずDateTimeクラスはおいておくことにします。

タイムゾーンについて

タイムゾーン(TZ)という概念を知っておかなくてはいけません。

要は『時差』を考慮する方法のことですね。

コンピュータの世界では標準をUTC (協定世界時:Coordinated Universal Time)としています。これは日本よりも9時間遅い時刻、つまりUTCからみるとJST (日本標準時:Japan Standard Time) は9時間進んでいると表現することができます。

先程Time.nowで得られたオブジェクトに書かれていた2019-02-25 21:03:19 +0900の後ろについている『+0900』というのがそれを表しています(おそらく +09時間00分という意味)。

これはどこの設定を見ているかと言うと、次のようになっています。

素のRubyの場合

優先されるのは環境変数`TZ`の値。これが設定されていなければシステム (OS)の設定が利用されるようです。

というわけで.bash_profileなどに`export TZ=”Asia/Tokyo”`とか書いてsourceしておけばOKです。
(タイムゾーンの設定用IDに関してはこちらに書いてありました)

Railsの場合

config/application.rbに設定を書いておくことができます。

config.time_zone = 'Tokyo'
config.time_zone = 'Asia/Tokyo'
# どちらでもOK

上にも少し書きましたが、『Time.now』『Date.today』『DateTime.now』は環境変数またはシステムのタイムゾーン設定を、『Time.current』などのcurrentは`application.rb`に設定したタイムゾーン設定が利用されます。
つまりこれらを同じにしている場合はnowもcurrentも値は同じ、みたいなことになります。

Time.now
 #=> 2019-02-25 22:24:00 +0900
Time.current
 #=> Mon, 25 Feb 2019 13:24:00 UTC +00:00

# application.rb に config.time_zone = 'Tokyo' を設定後
Time.current
 #=> Mon, 25 Feb 2019 22:24:00 JST +09:00

各クラスのメソッド

Timeクラス

とりあえず調べたのをひたすらまとめておきますが、もちろん全部覚える必要はないので使いやすくて覚えやすい書き方をおさえておけばいいと思います。

time = Time.now

time + 10  # 10秒後

time + 10.seconds  # これも10秒後

time + 10.minutes  # 10分後

time + 10.hours  # 10時間後

time + 10.days  # 10日後

time + 10.weeks  # 10週後

time + 10.months  # 10ヶ月後

time + 10.years  # 10年後

time.tomorrow  # 翌日

time.yesterday  # 昨日

time.next_month  # 翌月

time.prev_month  # 前月

time.next_year  # 翌年

time.prev_year  # 前月

time.ago(2.months)  # 2ヶ月前

time.since(2.months)  # 2ヶ月後

time.ago(2.years)  # 2年前

time.since(2.years)  # 2年後

time.beginning_of_month  # 月初

time.end_of_month  # 月末

time.beginning_of_year  # 年初

time.end_of_year  # 年末

time.next_occurring(:wednesday)  # 次の水曜日

time.prev_occurring(:wednesday)  # 前の水曜日

time.prev_week(:monday)  # 先週の月曜日

time.next_week(:monday)  # 来週の月曜日

time.year  # 年 を取り出す

time.month  # 月 を取り出す

time.day  # 日 を取り出す

time.hour  # 時 を取り出す

time.min  # 分 を取り出す

time.sec  # 秒 を取り出す

time.wday  # 曜日 を取り出す(0:Sunday, 1:Monday, ……)

time.yday  # 1/1からの経過日数

次の○曜日、前の○曜日を取得するnext_occurring, prev_occurring はRails5.2から追加されたメソッドらしいので、現時点では新しいRailsを利用していないと使えないと思います。

単数形と複数形について

dayとdays, monthとmonths, yearとyears のような単数形、複数形はどちらを用いても同じです(aliasとなるよう設定されています)。

time.ago(2.month)
 #=> 2018-12-25 22:00:00 +0900
time.ago(2.months)
 #=> 2018-12-25 22:00:00 +0900

# これらは同じ

まぁそれでも間違えていると気持ち悪いので数字に合わせて単数か複数かは適切に使用したいですね。

Dateクラス

基本的にTimeクラスのオブジェクトに使えたメソッドが同じように使えますので重複しているものは省略します。

date = Date.now

date >> 2  # 2ヶ月後

date << 2  # 2ヶ月前

ただしこちらは時間情報を持っていないので、時分秒を取得するメソッドなどはエラーとなります。

date = Date.today

date.hour
# これはエラー

date - 1.hour
=> Mon, 25 Feb 2019 23:00:00 HST -10:00
# エラーにならない
# application.rb のTZをHSTに設定している

時間の減算はエラーになりませんでした。
1時間引いて23時になったので、おそらく0時という情報を持ってはいるのでしょう。というか加算・減算をすると時間情報が姿を表すようですね。
ちなみに

date.class
=> Date

date = date - 1.hour

date.class
=> ActiveSupport::TimeWithZone

もともとはもちろんDateクラスなのですが、減算して時間情報をもたせるとTimeWithZoneというクラスに変わっていました。やっぱりDateクラスは時間情報を持てないんですね。
TimeWithZoneについては後述します。

DateTimeクラス

さて、あまり使わなくていい気がするDateTimeクラスですが、ちょっと変わったところがあります。

# now に 2019年2月25日22時00分00秒 のTimeオブジェクトを代入
DateTime.new(2019,2,25,22,00,00)
 #=> Mon, 25 Feb 2019 22:00:00 +0000  # TimeZoneがUTCになっている!!

datetime2 = DateTime.now
 #=> Tue, 25 Feb 2019 22:00:00 +0900  # 他と一緒(システムの設定)
datetime3 = DateTime.current
 #=> Mon, 25 Feb 2019 13:00:00 +0000  # 他と一緒(application.rbの設定)

nowやcurrentでインスタンスを生んだときはTimeやDateと同じようなタイムゾーンになりますが、newで生むと必ずUTCで生まれるようです。
これに対してTimeクラスにnewしたときはシステムのタイムゾーン設定依存ですので異なります。

TimeWithZoneクラスに関して

TimeWithZoneクラスとは?

日付と時間情報を扱えるクラスです。Rails独自のクラスでTimeクラスと完全な互換性をもっています。親はObjectクラスで、Timeクラスを継承しているわけではありません。
まぁTimeクラスと大きな差はなさそうなので親戚くらいの認識でいいのでしょうか。

Time.current.class
=> ActiveSupport::TimeWithZone

Time.zone.now.class  # .zone.now は .current と同じらしい
=> ActiveSupport::TimeWithZone

date = Date.today
date.ago(1.day)
=> Mon, 25 Feb 2019 00:00:00 HST -10:00
date.ago(1.day).class
=> ActiveSupport::TimeWithZone

currentメソッドやzone.nowメソッドを使うとTimeWithZoneクラスになるようです。
また、さきほどのようにDateクラスのオブジェクトから1時間引いてみたり、.agoメソッドなどを使うとTimeWithZoneクラスになりました。

よく見るとタイムゾーンがHSTになっているのが分かりますね。今回はわかりやすくするためにapplication.rbのタイムゾーン設定をHSTにしておきました。
TimeWithZoneクラスはapplication.rbのタイムゾーン設定が利用されます。
currentメソッドを使うとapplication.rbのタイムゾーンが利用される、と前述しましたが、これはTimeWithZoneクラスになっていたからなんですね。

Timeクラスと大差ないとは思いますが、Timeクラスのタイムゾーンは環境変数(システム)依存、TimeWithZoneクラスのタイムゾーンはapplication.rb依存というのは覚えておくと良さそうですね。

メソッドのエイリアスについて

.month.monthsはエイリアスになっているということは前述しましたが、次のようなものが設定されているようです。

alias :second   :seconds
alias :minute   :minutes
alias :hour     :hours
alias :day      :days
alias :week     :weeks
alias :until    :ago
alias :from_now :since

 


追記予定:strftime, strptime, time_formats


 

参考サイト

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください