From: Tadayoshi Funaba Date: 1999-07-12T23:42:04+09:00 Subject: [ruby-list:15371] Re: 年月を範囲でうまく扱うには? ふなばです。 At 1999-07-09T02:50:44+0900 (Y10K-2922115.88144), gotoken@math.sci.hokudai.ac.jp (GOTO Kentaro) wrote: gotoken> だいぶ違うじゃん(^^;; 書きはじめたら、もうちょっと違うなにかがでてくるかと思ったんですが、なん もでてきませんでした :-) gotoken> ってわけで、Mon#+ は定義しない方が好みです。 僕はあまり気にならないです。というわけで、つかいまくってます :-) Mon も範囲と考えて、少しなおしておきます。でも、日付の範囲としては、中 途半端なので、 一般的には、まずは Time/Date の範囲を考えるべきだし、用 途が限られてる。 require 'date2' class Date; def succ() self + 1 end end class Mon include Comparable include Enumerable class << self def mon_to_jm(y, m) (y + 4712) * 12 + m - 1 end def jm_to_mon(jm) [jm / 12 - 4712, jm % 12 + 1] end def exist2? (y, m) jm = mon_to_jm(y, m) if [y, m] == jm_to_mon(jm) jm end end alias_method :exist?, :exist2? def new2(y=-4712, m=1, gs=Date::ITALY) unless jm = exist2?(y, m) fail ArgumentError, 'invalid mon' end new(jm, gs) end def this(gs=Date::ITALY) new(mon_to_jm(*(Time.now.to_a[4..5].reverse << gs))) end end def initialize(jm=0, gs=Date::ITALY) @jm, @gs = jm, gs end def jm() @jm end def year() Mon.jm_to_mon(@jm)[0] end def mon() Mon.jm_to_mon(@jm)[1] end def + (other) case other when Numeric; return Mon.new(@jm + other, @gs) end fail TypeError, 'expected numeric' end def - (other) case other when Numeric; return Mon.new(@jm - other, @gs) when Mon; return @jm - other.jm end fail TypeError, 'expected numeric or mon' end def <=> (other) case other when Numeric; return @jm <=> other when Mon; return @jm <=> other.jm end fail TypeError, 'expected numeric or mon' end def downto(min) @jm.downto(min.jm) do |jm| yield Mon.new(jm, @gs) end end def upto(max) @jm.downto(max.jm) do |jm| yield Mon.new(jm, @gs) end end def step(max, step) @jm.step(max.jm, step) do |jm| yield Mon.new(jm, @gs) end end def succ() self + 1 end def first jd = nil 1.upto 31 do |d| break if jd = Date.exist?(year, mon, d, @gs) end Date.new(jd, @gs) end alias_method :begin, :first def last jd = nil 31.downto 1 do |d| break if jd = Date.exist?(year, mon, d, @gs) end Date.new(jd, @gs) end alias_method :end, :last def length last - first + 1 end alias_method :size, :length def each (first..last).each do |d| yield d end end def === (other) case other when Numeric; return @jm == Mon.mon_to_jm(*(Date.jd_to_civil(other)[0..1])) when Date; return @jm == Mon.mon_to_jm(other.year, other.mon) end fail TypeError, 'expected numeric or date' end def eql? (other) self == other end def hash() @jm end def to_s() format('%04d-%02d', year, mon) end end if __FILE__ == $0 class Date; def sun? () wday == 0 end end puts Mon.new2(2001,1).select{|d| d.sun?} puts Mon.new2(1752,9,Date::ENGLAND).length puts Mon.new2(2001,12) === Date.new3(2001,12,25) puts Mon.new2(2001,12) === Date.today puts Mon.new2(2001,2).last == Mon.new2(2001,2).to_a[-1] end 25.times{|i|$><<('Jqqd `lmtHep RqBy haCja2,'[i]|'Jes4 A.ot(Er Bu`y hAakER,'[i]).chr} ふなば ただよし