LoginSignup
141
146

More than 5 years have passed since last update.

すぐ忘れるので、RubyとRailsの日付操作周りについてまとめました

Posted at

日付の操作はしょっちゅうするのですが、なんか毎回調べているにも関わらず、いっこうに頭に入ってこないのでまとめました。

それぞれの日付型の意味についてはこちらの記事を参照してみてください。
RubyとRailsにおけるTime, Date, DateTime, TimeWithZoneの違い

x日前

ruby

Date型なら -1 するだけです

require "date"
d = Date.today
p d
p d-1

#<Date: 2017-09-07 ((2458004j,0s,0n),+0s,2299161j)>
#<Date: 2017-09-06 ((2458003j,0s,0n),+0s,2299161j)>

DateTimeも -1でいけるよ

require "date"
d = DateTime.now
p d
p d-1

#<DateTime: 2017-09-15T17:52:04+09:00 ((2458012j,31924s,725447000n),+32400s,2299161j)>
#<DateTime: 2017-09-14T17:52:04+09:00 ((2458011j,31924s,725447000n),+32400s,2299161j)>

Timeは1秒マイナスするだけや

now = Time.now
p now
p now -1

# 2017-09-07 17:52:54 +0900
# 2017-09-07 17:52:53 +0900

rails(ActiveSupport)

-1.days

[2] pry(main)> Time.current
=> Fri, 18 Aug 2017 18:12:21 JST +09:00
[3] pry(main)> Time.current - 1.days
=> Thu, 17 Aug 2017 18:12:26 JST +09:00

x月前

ruby

<<演算子で前の月の日付オブジェクトを返します


require "date"
d = Date.new(2017,9,7)
p d
p d << 2
# d.prev_month(2)でも同じ

#<Date: 2017-09-07 ((2458004j,0s,0n),+0s,2299161j)>
#<Date: 2017-07-07 ((2457973j,0s,0n),+0s,2299161j)>

rails(ActiveSupport)

Time.current-2.month

[1] pry(main)> Time.current
=> Fri, 15 Sep 2017 18:22:33 JST +09:00
[2] pry(main)> Time.current-2.month
=> Tue, 15 Aug 2017 18:22:42 JST +09:00

x時間、x分、x秒後

俺は15分後が何時何分何秒か知りたいのだ、そんな時に。

require "date"
d =  DateTime.new(2017,4,1,0,0,0)

p d + Rational(1,24)
p d + Rational(1,24*60)
p d + Rational(1,24*60*60)

#<DateTime: 2017-04-01T01:00:00+00:00 ((2457845j,3600s,0n),+0s,2299161j)>
#<DateTime: 2017-04-01T00:01:00+00:00 ((2457845j,60s,0n),+0s,2299161j)>
#<DateTime: 2017-04-01T00:00:01+00:00 ((2457845j,1s,0n),+0s,2299161j)>

フォーマットの変更(日付型→文字列型)

よく使うやつ

strftime

Date.new(2017,9,7).strftime("%Y-%m-%d")
Time.new(2017,9,1).strftime("%Y-%m-%d")

rails

config/initializers/time_formats.rbを作成

Time::DATE_FORMATS[:ja] = "%Y年%m月%d日 %H時%M分"
Time::DATE_FORMATS[:ymd] = "%Y%m%d"

みたいな感じで好きにフォーマットつくれます。

使い方

Time.new(2017,9,1).to_s(:ja)

デフォルトで用意されているフォーマット

Time.new(2017,9,1).to_s(:default)=> "2017-09-01 00:00:00 +0900"
Time.new(2017,9,1).to_s(:long)=> "September 01, 2017 00:00"
Time.new(2017,9,1).to_s(:short)=> "01 Sep 00:00"
Time.new(2017,9,1).to_s(:db)=> "2017-09-01 00:00:00"

※defaultフォーマットを上書きすることで、デフォルトを変えることも可能

ja.ymlを使う

config/initializers/locale.rbを作成

I18n.default_locale = :ja

config/locales/ja.ymlを作成
https://github.com/svenfuchs/rails-i18n/blob/master/rails/locale/ja.yml
を流用させていただきます

irb(main):001:0> I18n.l(Time.current, format: :long)
=> "2017年09月20日(水) 19時46分15秒 +0900"

文字列を日付型に変換

strptime

date = Date.strptime('2017年9月1日','%Y年%m月%d日')
p date

#<Date: 2017-09-01 ((2457998j,0s,0n),+0s,2299161j)>

ハイフン区切り、スラッシュ区切りの日付なら、parseでいけます。

date = Date.parse('2017-9-7')
p date

#<Date: 2017-09-01 ((2457998j,0s,0n),+0s,2299161j)>

_strptimeとか_parse

Dateクラスには通常のメソッドにアンダースコア(_)が先頭についたメソッドがいくつかありまして、要素をハッシュで返してくれるようになります。

date = Date._strptime('2017年9月1日','%Y年%m月%d日')
p date
# {:year=>2017, :mon=>9, :mday=>1}

日付の差分

Date型は、ただ引くだけ

d = Date.new(2017,9,7)
d2 = Date.new(2017,10,11)

p d2-d
# (34/1)

# Rational型で返るので分子の値だけを取れば日付の差分が取得できます
p (d2-d).numerator
# 34

Timeでやると、秒数で出ちゃうので割ります

t  = Time.new(2017,9,7)
t2 = Time.new(2017,10,11)
p t2-t
p (t2-t)/24/60/60
# 2937600.0
# 34

月末、月初

ruby

月末はDateオブジェクトを作る時に日付の値に-1をいれてあげよう。

require "date"
d = Date.new(2017,9,-1)
p d
#<Date: 2017-09-30 ((2458027j,0s,0n),+0s,2299161j)>

dt = DateTime.new(2017,9,-1)
p dt
#<DateTime: 2017-09-30T00:00:00+00:00 ((2458027j,0s,0n),+0s,2299161j)>

t = Time.new(2017,9,-1)
p t
# /tmp/sample.rb:6:in `initialize': argument out of range (ArgumentError)
# Timeはエラー

rails(ActiveSupport)

rails使う場合は月末、月初を出すメソッドあります。
beginning_of_monthend_of_month

t = Time.new(2017,9.7)
# => 2017-09-01 00:00:00 +0900
t.beginning_of_month
# => 2017-09-01 00:00:00 +0900
t.end_of_month
# => 2017-09-30 23:59:59 +0900

23:59:59で出してくれるので助かるー

指定した日付の曜日を出す

require "date"
d = Date.new(2017,9,7)
p %w(日 月 火 水 木 金 土)[d.wday]

今週(来週)のhoge曜日の日付を出す

require "date"
this_day = Date.today
this_monday    = this_day - (this_day.wday - 1) # 今週
this_tuesday   = this_day - (this_day.wday - 2) # 今週
this_wednesday = this_day - (this_day.wday - 3) # 今週
next_wednesday = this_day - (this_day.wday - 3) + 7 # 来週

rails(activesupport)

t = Time.current
t.prev_week(:friday) # 先週の金曜日
t.next_week(:friday) # 来週の金曜日

t + (5 - t.wday).days # 今週の金曜日
t + (4 - t.wday).days # 今週の木曜日
141
146
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
141
146