# holiday.rb: Written by Tadayoshi Funaba 1998-2000 # $Id: holiday.rb,v 1.11 2000-07-16 10:23:53+09 tadf Exp $ class Date def fixed? return false unless jd >= 2432753 # 1948-07-20/PooD *x = mon, mday (x == [ 1, 1]) or # --01-01 (x == [ 1, 15] and # --01-15 (1948-07-20/1999-12-31) jd <= 2451544) or (x == [ 2, 11] and # --02-11 (1966-12-09/PooD) jd >= 2439469) or (x == [ 4, 29]) or # --04-29 (x == [ 5, 3]) or # --05-03 (x == [ 5, 5]) or # --05-05 (x == [ 7, 20] and # --07-20 (1996-01-01/PooD) jd >= 2450084) or (x == [ 9, 15] and # --09-15 (1966-06-25/PooD) jd >= 2439302) or (x == [10, 10] and # --10-10 (1966-06-25/1999-12-31) jd >= 2439302 and jd <= 2451544) or (x == [11, 3]) or # --11-03 (x == [11, 23]) or # --11-23 (x == [12, 23] and # --12-23 (1989-02-17/PooD) jd >= 2447575) end def float? (mon == 1 and nth_kday?(2, 1) and # 2nd Mon, Jan (2000-01-01/PooD) jd >= 2451545) or (mon == 10 and nth_kday?(2, 1) and # 2nd Mon, Oct (2000-01-01/PooD) jd >= 2451545) end class << self def deq(a, b, y) (a + 0.242194 * (y - 1980) - ((y - b) / 4).to_i).to_i end private :deq def veq(y, sg=ITALY) case y when 1851..1899; a = 19.8277; b = 1983.0 when 1900..1979; a = 20.8357; b = 1983.0 when 1980..2099; a = 20.8431; b = 1980.0 when 2100..2150; a = 21.8510; b = 1980.0 end jd = civil_to_jd(y, 3, deq(a, b, y), sg) unless (2397124..2506696) === jd # 1851-01-01/2150-12-31 raise ArgumentError, 'domain error' end return new1(jd, sg) end def aeq(y, sg=ITALY) case y when 1851..1899; a = 22.2588; b = 1983.0 when 1900..1979; a = 23.2588; b = 1983.0 when 1980..2099; a = 23.2488; b = 1980.0 when 2100..2150; a = 24.2488; b = 1980.0 end jd = civil_to_jd(y, 9, deq(a, b, y), sg) unless (2397124..2506696) === jd # 1851-01-01/2150-12-31 raise ArgumentError, 'domain error' end return new1(jd, sg) end end def veq? return false unless jd >= 2432753 # 1948-07-20/PooD self === type.veq(year, sg) end def aeq? return false unless jd >= 2432753 # 1948-07-20/PooD self === type.aeq(year, sg) end def nhol2? () fixed? or float? or veq? or aeq? end def sun? () wday == 0 end protected :sun? def nhol32? jd >= 2441785 and # 1973-04-12/PooD (self - 1).sun? and (self - 1).nhol2? end def nhol33? jd >= 2446427 and # 1985-12-27/PooD not sun? and not nhol32? and (self - 1).nhol2? and (self + 1).nhol2? end def nholx? jd == 2447582 or # 1989-02-24 jd == 2448208 or # 1990-11-12 jd == 2449148 # 1993-06-09 end def nhol? () nhol2? or nhol32? or nhol33? or nholx? end class << self def nth_kday(n, k, y, m, sg=ITALY) jd = nil if n > 0 1.upto 31 do |d| break if jd = exist?(y, m, d, sg) end jd -= 1 else 31.downto 1 do |d| break if jd = exist?(y, m, d, sg) end jd += 7 end jd = (jd - (((jd - k) + 1) % 7)) + 7 * n return new1(jd, sg) end end def nth_kday? (n, k) k == wday and self === type.nth_kday(n, k, year, mon, sg) end class << self def julian_easter(y, sg=ITALY) a = y % 4 b = y % 7 c = y % 19 d = (19 * c + 15) % 30 e = (2 * a + 4 * b - d + 34) % 7 f, g = (d + e + 114).divmod(31) jd = civil_to_jd(y, f, g + 1, JULIAN) return new1(jd, sg) end def gregorian_easter(y, sg=ITALY) a = y % 19 b, c = y.divmod(100) d, e = b.divmod(4) f = ((b + 8) / 25).to_i g = ((b - f + 1) / 3).to_i h = (19 * a + b - d - g + 15) % 30 i, k = c.divmod(4) l = (32 + 2 * e + 2 * i - h - k) % 7 m = ((a + 11 * h + 22 * l) / 451).to_i n, p = (h + l - 7 * m + 114).divmod(31) jd = civil_to_jd(y, n, p + 1, GREGORIAN) return new1(jd, sg) end alias_method :easter, :gregorian_easter end def easter? self === (if os? type.julian_easter(year, sg) else type.gregorian_easter(year, sg) end) end end