19
21

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

RailsのTimeWithZoneで時間操作するときによく使うメソッド集

Last updated at Posted at 2020-06-07

Railsのアプリで特定の期間の料金計算をしたり、そのテストをする際に時間をいじって検証することが多かったのですが、かなり簡単に欲しい時刻を取得できることに感動したので、そのとき使った時間操作系のメソッドを備忘録代わりにまとめました。

そもそもTimeとかTimeWithZoneとか何なのか?

下記の記事に詳しく書かれていたので紹介させていただきます。結論、Railsで使うときはTimeWithZoneを使うと色々捗ります。この記事ではこのクラスを使うことを前提に書かせていただきます。
RubyとRailsにおけるTime, Date, DateTime, TimeWithZoneの違い - Qiita

現在時刻の取得する

超基本の時刻取得系。とりあえず基本ということで。これをベースにいろんな形に変換したりしていくことが多いかと思います。

# 現在時刻を取得する
Time.current
=> Wed, 15 Jan 2020 13:18:07 UTC +00:00

# classを確認する
Time.current.class
=> ActiveSupport::TimeWithZone

# string型に変換
Time.current.strftime("%F")
=> "2020-01-15"

Tips: Time.nowとの違い

Time.nowを使っても現在時刻は取得できますが、こちらの場合は下記のような違いがあります。

  • Timeクラスなので、TimeWithZoneのメソッド(今回紹介しているものなど)が使えない。
  • TimeWithZoneはconfig/application.rbに設定しているタイムゾーンをもとに取得してくるのに対して、環境変数、もしくはシステムのタイムゾーンをもとに現在時刻を取得するため、時刻が大きくずれてしまうという懸念がある。

TimeWizhZoneクラスのメソッドが使えることからも、こちらで取得するのが良さそうです。

前日や翌日を取得する

昨日のデータ、翌月のデータを取得したい〜と思うのですがこのレベルであれば下記のように一発で持ってこれるので便利です。

# 昨日
Time.current.yesterday

# 翌日
Time.current.tomorrow

# 前月
Time.current.prev_month

# 翌月
Time.current.next_month

# 月初 
Time.current.beginning_of_month

# 月末
Time.current.end_of_month

# 前年
Time.current.prev_year

# 翌年
Time.current.next_year

N日、Nヶ月、N年前の時刻を取得する

任意の日付や月で変更したい場合は下記のように書くことで取得することが可能です。

# 3日前 / 3日後
Time.current.ago(3.days)
Time.current.since(3.days)

# 3ヶ月前 / 3ヶ月後
Time.current.ago(3.month)
Time.current.since(3.month)

# 3年前 / 3年後
Time.current.ago(3.years)
Time.current.since(3.years)

年月日や曜日を取得する

日数の計算などする際は下記のように書くことでそれぞれの数字が持ってこられます。この時の型は基本int型です。

# 年
Time.current.year
=> 2020

# 月
Time.current.month
=> 6

# 日付
Time.current.day
=> 7

時刻の差分

TimeWithZoneを引算すると、UNIXTIME(秒数)が返ってきます。これをTime.zone.atを使って変換することで、2つの日時の差分から日付などを取得したいときに使えます。

# 時刻を設定からTimeWithZoneに変換する
time1 = Time.zone.parse('2020-01-05 12:00:00')
time2 = Time.zone.parse('2020-01-01 10:00:00')

# 引算してUNIXTIME(秒数) を取得する
time1 - time2
=> 352800.0

# 秒数をTimeWithZoneに変換する
Time.zone.at(time1 - time2)

任意の時間を取得する

テストなどで特定の日付に生成したデータなどを取得したい場合などに使います。

Time.zone.parse('2020-01-01')
=> Wed, 01 Jan 2020 00:00:00 UTC +00:00

Time.zone.parse('2020-01-01 12:00:00')
=> Wed, 01 Jan 2020 12:00:00 UTC +00:00

# 現在時刻をもとに新しいTimeWithZoneを作成する
Time.zone.parse("#{Time.current.strftime('%F')} #{Time.current.hour}:00:00")
=> Wed, 15 Jan 2020 13:00:00 UTC +00:00

まとめ

時刻操作などは触る前は少し苦手意識がありましたが、こうして触ってみて学びも増えました。他にもできることが便利な操作法があれば追加していこうと思います。

参考にさせていただいた記事

19
21
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
19
21

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?