Rubyにおける二重山括弧「<<」「>>」についてのメモ。
(環境は Ruby 2.0.0 + Rails 4.2.4)
「<<」は文字列の場合は連結、配列の場合は追加となるが、
日付の場合、結論としては月単位の操作を行っていることがわかったが、
どういう理屈で以下の挙動をしているのかよくわからなかった。
ruby
require 'date'
now = Time.now
puts now
#=> 2022-01-28 12:43:10 +0900
# 「<< N」で Nヵ月前
puts Date.new(now.year, now.month, 1) << 2 #=> 2021-11-01
puts Date.new(now.year, now.month, -1) << 2 #=> 2021-11-30
puts Date.new(now.year, now.month, -1) << -1 #=> 2022-02-28
# 「>> N」で Nか月後
puts Date.new(now.year, now.month, -1) >> 2 #=> 2022-03-31
puts Date.new(now.year, now.month, -1) >> 3 #=> 2022-04-30
(追記)
ちゃんとリファレンスマニュアルを読もう。
以下引用。
class Date インスタンスメソッド
self << n -> Date
self より n ヶ月前の日付オブジェクトを返します。 n は数値でなければなりません。
require 'date'
Date.new(2001,2,3) << 1 #=> #<Date: 2001-01-03 ...>
Date.new(2001,2,3) << -2 #=> #<Date: 2001-04-03 ...>
# 対応する月に同じ日が存在しない時は、代わりにその月の末日が使われます。
Date.new(2001,3,28) << 1 #=> #<Date: 2001-02-28 ...>
Date.new(2001,3,31) << 1 #=> #<Date: 2001-02-28 ...>
# このことは以下のように、もしかすると予期しない振る舞いをするかもしれません。
Date.new(2001,3,31) << 2 #=> #<Date: 2001-01-31 ...>
Date.new(2001,3,31) << 1 << 1 #=> #<Date: 2001-01-28 ...>
Date.new(2001,3,31) << 1 << -1 #=> #<Date: 2001-03-28 ...>
self >> n -> Date
self から n ヶ月後の日付オブジェクトを返します。 n は数値でなければなりません。
require 'date'
Date.new(2001,2,3) >> 1 #=> #<Date: 2001-03-03 ...>
Date.new(2001,2,3) >> -2 #=> #<Date: 2000-12-03 ...>
# 対応する月に同じ日が存在しない時は、代わりにその月の末日が使われます。
Date.new(2001,1,28) >> 1 #=> #<Date: 2001-02-28 ...>
Date.new(2001,1,31) >> 1 #=> #<Date: 2001-02-28 ...>
# このことは以下のように、もしかすると予期しない振る舞いをするかもしれません。
Date.new(2001,1,31) >> 2 #=> #<Date: 2001-03-31 ...>
Date.new(2001,1,31) >> 1 >> 1 #=> #<Date: 2001-03-28 ...>
Date.new(2001,1,31) >> 1 >> -1 #=> #<Date: 2001-01-28 ...>