日付の操作はしょっちゅうするのですが、なんか毎回調べているにも関わらず、いっこうに頭に入ってこないのでまとめました。
それぞれの日付型の意味についてはこちらの記事を参照してみてください。
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_month
、end_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 # 今週の木曜日