From c3bf468593d816e521ba1e41153382b6dd55ea13 Mon Sep 17 00:00:00 2001 From: Tatsuki Sugiura Date: Sat, 25 Dec 2010 17:33:16 +0900 Subject: [PATCH] Add a difinition for Japan. --- data/index.yaml | 1 + data/jp.yaml | 202 ++++++++++++++++++++++++++++++++++++++ lib/holidays/MANIFEST | 37 +++---- lib/holidays/jp.rb | 109 ++++++++++++++++++++ test/defs/test_defs_jp.rb | 50 ++++++++++ 5 files changed, 381 insertions(+), 18 deletions(-) create mode 100644 data/jp.yaml create mode 100644 lib/holidays/jp.rb create mode 100644 test/defs/test_defs_jp.rb diff --git a/data/index.yaml b/data/index.yaml index e900d9e..14110bc 100644 --- a/data/index.yaml +++ b/data/index.yaml @@ -26,3 +26,4 @@ defs: North_America: ['ca.yaml', 'mx.yaml', 'us.yaml', 'north_america_informal.yaml'] Scandinavia: ['dk.yaml', 'is.yaml', 'no.yaml', 'se.yaml'] Europe: ['cz.yaml', 'dk.yaml', 'de.yaml', 'es.yaml', 'fr.yaml', 'gb.yaml', 'ie.yaml', 'is.yaml', 'it.yaml', 'nl.yaml', 'no.yaml', 'pt.yaml'] + JP: ['jp.yaml'] diff --git a/data/jp.yaml b/data/jp.yaml new file mode 100644 index 0000000..0e86b5b --- /dev/null +++ b/data/jp.yaml @@ -0,0 +1,202 @@ +# Japanese holiday definitions for Ruby Holiday gem. +# Reference: http://www.h3.dion.ne.jp/~sakatsu/holiday_topic.htm +# +# This difinition can calculate current Japanese holidays, +# don't compat with past changes of Japan Holiday Act. +# +# CHANGES: +# 2010-12-25: Initial version by Tatsuki Sugiura +# +--- +months: + 1: + - name: 元日 + regions: [jp] + mday: 1 + - name: 成人の日 + regions: [jp] + wday: 1 + week: 2 + 2: + - name: 建国記念日 + regions: [jp] + mday: 11 + - name: 振替休日 + regions: [jp] + function: jp_substitute_holiday(year, 2, 11) + 3: + - name: 春分の日 + regions: [jp] + function: jp_vernal_equinox_day(year) + - name: 振替休日 + regions: [jp] + function: jp_substitute_holiday(Holidays.jp_vernal_equinox_day(year)) + 4: + - name: 昭和の日 + regions: [jp] + mday: 29 + - name: 振替休日 + regions: [jp] + function: jp_substitute_holiday(year, 4, 29) + 5: + - name: 憲法記念日 + regions: [jp] + mday: 3 + - name: みどりの日 + regions: [jp] + mday: 4 + - name: こどもの日 + regions: [jp] + mday: 5 + - name: 振替休日 + regions: [jp] + function: jp_substitute_holiday(year, 5, 3) + - name: 振替休日 + regions: [jp] + function: jp_substitute_holiday(year, 5, 5) + 7: + - name: 海の日 + regions: [jp] + wday: 1 + week: 3 + - name: 振替休日 + regions: [jp] + function: jp_substitute_holiday(year, 7, Date.calculate_mday(year, 7, 3, 1)) + 9: + - name: 敬老の日 + regions: [jp] + wday: 1 + week: 3 + - name: 振替休日 + regions: [jp] + function: jp_substitute_holiday(year, 9, Date.calculate_mday(year, 9, 3, 1)) + - name: 国民の休日 + regions: [jp] + function: jp_citizons_holiday(year) + - name: 秋分の日 + regions: [jp] + function: jp_national_culture_day(year) + - name: 振替休日 + regions: [jp] + function: jp_substitute_holiday(Holidays.jp_national_culture_day(year)) + 10: + - name: 体育の日 + regions: [jp] + wday: 1 + week: 2 + - name: 振替休日 + regions: [jp] + function: jp_substitute_holiday(year, 10, Date.calculate_mday(year, 10, 2, 1)) + 11: + - name: 文化の日 + regions: [jp] + mday: 3 + - name: 振替休日 + regions: [jp] + function: jp_substitute_holiday(year, 11, 3) + - name: 勤労感謝の日 + regions: [jp] + mday: 23 + - name: 振替休日 + regions: [jp] + function: jp_substitute_holiday(year, 11, 23) + 12: + - name: 天皇誕生日 + regions: [jp] + mday: 23 + - name: 振替休日 + regions: [jp] + function: jp_substitute_holiday(year, 12, 23) +methods: + jp_vernal_equinox_day: | + def self.jp_vernal_equinox_day(year) + day = + case year + when 1851..1899 + 19.8277 + when 1900..1979 + 20.8357 + when 1980..2099 + 20.8431 + when 2100..2150 + 21.8510 + else + raise IndexError.new("Out of range") + end + day += 0.242194 * (year - 1980) - ((year - 1980)/4).floor + day = day.floor + Date.civil(year, 3, day) + end + jp_national_culture_day: | + def self.jp_national_culture_day(year) + day = + case year + when 1851..1899 + 22.2588 + when 1900..1979 + 23.2588 + when 1980..2099 + 23.2488 + when 2100..2150 + 24.2488 + else + raise IndexError.new("Out of range") + end + day += 0.242194 * (year - 1980) - ((year - 1980)/4).floor + day = day.floor + Date.civil(year, 9, day) + end + jp_citizons_holiday: | + def self.jp_citizons_holiday(year) + year < 2003 and return nil + ncd = Holidays.jp_national_culture_day(year) + if ncd.wday == 3 + ncd - 1 + else + nil + end + end + jp_substitute_holiday: | + def self.jp_substitute_holiday(*date) + date = date[0].kind_of?(Date) ? date.first : Date.civil(*date) + date.wday == 0 ? date+1 : nil + end +tests: | + {Date.civil(2008,1,1) => '元日', + Date.civil(2010,1,11) => '成人の日', + Date.civil(2008,2,11) => '建国記念日', + Date.civil(2008,4,29) => '昭和の日', + Date.civil(2008,5,3) => '憲法記念日', + Date.civil(2008,5,5) => 'こどもの日', + Date.civil(2010,7,19) => '海の日', + Date.civil(2010,9,20) => '敬老の日', + Date.civil(2010,10,11) => '体育の日', + Date.civil(2008,11,3) => '文化の日', + Date.civil(2008,11,23) => '勤労感謝の日', + Date.civil(2008,12,23) => '天皇誕生日', + Date.civil(2010,3,22) => '振替休日', + Date.civil(2008,11,24) => '振替休日', + }.each do |date, name| + assert_equal name, (Holidays.on(date, :jp, :informal)[0] || {})[:name] + end + + # vernal equinox day + [Date.civil(2004,3,20), Date.civil(2005,3,20), Date.civil(2006,3,21), + Date.civil(2007,3,21), Date.civil(2008,3,20), Date.civil(2009,3,20), + Date.civil(2010,3,21)].each do |date| + assert_equal '春分の日', Holidays.on(date, :jp)[0][:name] + end + + # national culture day + [Date.civil(2004,9,23), Date.civil(2005,9,23), Date.civil(2006,9,23), + Date.civil(2007,9,23), Date.civil(2008,9,23), Date.civil(2009,9,23), + Date.civil(2010,9,23), Date.civil(2011,9,23), Date.civil(2012,9,22), + Date.civil(2013,9,23)].each do |date| + assert_equal '秋分の日', Holidays.on(date, :jp)[0][:name] + end + + # citizons holiday + [Date.civil(2032,9,21), Date.civil(2049,9,21), Date.civil(2009,9,22), + Date.civil(2015,9,22), Date.civil(2026,9,22)].each do |date| + assert_equal '国民の休日', Holidays.on(date, :jp)[0][:name] + end diff --git a/lib/holidays/MANIFEST b/lib/holidays/MANIFEST index db7fffa..3f29717 100644 --- a/lib/holidays/MANIFEST +++ b/lib/holidays/MANIFEST @@ -1,28 +1,29 @@ ==== Regional definitions The following definition files are included in this installation: -* holidays/nyse -* holidays/no -* holidays/es -* holidays/ie -* holidays/united_nations * holidays/au -* holidays/mx -* holidays/za -* holidays/scandinavia * holidays/ca -* holidays/us -* holidays/nl -* holidays/it * holidays/de * holidays/dk * holidays/cz -* holidays/nz -* holidays/ups -* holidays/pt -* holidays/europe -* holidays/se -* holidays/north_america -* holidays/fr +* holidays/es * holidays/gb +* holidays/fr +* holidays/ie * holidays/is +* holidays/it +* holidays/jp +* holidays/nl +* holidays/mx +* holidays/no +* holidays/nz +* holidays/pt +* holidays/se +* holidays/us +* holidays/za +* holidays/united_nations +* holidays/scandinavia +* holidays/ups +* holidays/europe +* holidays/nyse +* holidays/north_america diff --git a/lib/holidays/jp.rb b/lib/holidays/jp.rb new file mode 100644 index 0000000..517e9d6 --- /dev/null +++ b/lib/holidays/jp.rb @@ -0,0 +1,109 @@ +# encoding: utf-8 +module Holidays + # This file is generated by the Ruby Holiday gem. + # + # Definitions loaded: data/jp.yaml + # + # To use the definitions in this file, load them right after you load the + # Holiday gem: + # + # require 'holidays' + # require 'holidays/jp' + # + # More definitions are available at http://code.dunae.ca/holidays. + module JP # :nodoc: + DEFINED_REGIONS = [:jp] + + HOLIDAYS_BY_MONTH = { + 1 => [{:mday => 1, :name => "元日", :regions => [:jp]}, + {:wday => 1, :week => 2, :name => "成人の日", :regions => [:jp]}], + 2 => [{:mday => 11, :name => "建国記念日", :regions => [:jp]}, + {:function => lambda { |year| Holidays.jp_substitute_holiday(year, 2, 11) }, :function_id => "jp_substitute_holiday(year, 2, 11)", :name => "振替休日", :regions => [:jp]}], + 3 => [{:function => lambda { |year| Holidays.jp_vernal_equinox_day(year) }, :function_id => "jp_vernal_equinox_day(year)", :name => "春分の日", :regions => [:jp]}, + {:function => lambda { |year| Holidays.jp_substitute_holiday(Holidays.jp_vernal_equinox_day(year)) }, :function_id => "jp_substitute_holiday(Holidays.jp_vernal_equinox_day(year))", :name => "振替休日", :regions => [:jp]}], + 4 => [{:mday => 29, :name => "昭和の日", :regions => [:jp]}, + {:function => lambda { |year| Holidays.jp_substitute_holiday(year, 4, 29) }, :function_id => "jp_substitute_holiday(year, 4, 29)", :name => "振替休日", :regions => [:jp]}], + 5 => [{:mday => 3, :name => "憲法記念日", :regions => [:jp]}, + {:mday => 4, :name => "みどりの日", :regions => [:jp]}, + {:mday => 5, :name => "こどもの日", :regions => [:jp]}, + {:function => lambda { |year| Holidays.jp_substitute_holiday(year, 5, 3) }, :function_id => "jp_substitute_holiday(year, 5, 3)", :name => "振替休日", :regions => [:jp]}, + {:function => lambda { |year| Holidays.jp_substitute_holiday(year, 5, 5) }, :function_id => "jp_substitute_holiday(year, 5, 5)", :name => "振替休日", :regions => [:jp]}], + 7 => [{:wday => 1, :week => 3, :name => "海の日", :regions => [:jp]}, + {:function => lambda { |year| Holidays.jp_substitute_holiday(year, 7, Date.calculate_mday(year, 7, 3, 1)) }, :function_id => "jp_substitute_holiday(year, 7, Date.calculate_mday(year, 7, 3, 1))", :name => "振替休日", :regions => [:jp]}], + 9 => [{:wday => 1, :week => 3, :name => "敬老の日", :regions => [:jp]}, + {:function => lambda { |year| Holidays.jp_substitute_holiday(year, 9, Date.calculate_mday(year, 9, 3, 1)) }, :function_id => "jp_substitute_holiday(year, 9, Date.calculate_mday(year, 9, 3, 1))", :name => "振替休日", :regions => [:jp]}, + {:function => lambda { |year| Holidays.jp_citizons_holiday(year) }, :function_id => "jp_citizons_holiday(year)", :name => "国民の休日", :regions => [:jp]}, + {:function => lambda { |year| Holidays.jp_national_culture_day(year) }, :function_id => "jp_national_culture_day(year)", :name => "秋分の日", :regions => [:jp]}, + {:function => lambda { |year| Holidays.jp_substitute_holiday(Holidays.jp_national_culture_day(year)) }, :function_id => "jp_substitute_holiday(Holidays.jp_national_culture_day(year))", :name => "振替休日", :regions => [:jp]}], + 10 => [{:wday => 1, :week => 2, :name => "体育の日", :regions => [:jp]}, + {:function => lambda { |year| Holidays.jp_substitute_holiday(year, 10, Date.calculate_mday(year, 10, 2, 1)) }, :function_id => "jp_substitute_holiday(year, 10, Date.calculate_mday(year, 10, 2, 1))", :name => "振替休日", :regions => [:jp]}], + 11 => [{:mday => 3, :name => "文化の日", :regions => [:jp]}, + {:function => lambda { |year| Holidays.jp_substitute_holiday(year, 11, 3) }, :function_id => "jp_substitute_holiday(year, 11, 3)", :name => "振替休日", :regions => [:jp]}, + {:mday => 23, :name => "勤労感謝の日", :regions => [:jp]}, + {:function => lambda { |year| Holidays.jp_substitute_holiday(year, 11, 23) }, :function_id => "jp_substitute_holiday(year, 11, 23)", :name => "振替休日", :regions => [:jp]}], + 12 => [{:mday => 23, :name => "天皇誕生日", :regions => [:jp]}, + {:function => lambda { |year| Holidays.jp_substitute_holiday(year, 12, 23) }, :function_id => "jp_substitute_holiday(year, 12, 23)", :name => "振替休日", :regions => [:jp]}] + } + end + +def self.jp_vernal_equinox_day(year) + day = + case year + when 1851..1899 + 19.8277 + when 1900..1979 + 20.8357 + when 1980..2099 + 20.8431 + when 2100..2150 + 21.8510 + else + raise IndexError.new("Out of range") + end + day += 0.242194 * (year - 1980) - ((year - 1980)/4).floor + day = day.floor + Date.civil(year, 3, day) +end + + +def self.jp_national_culture_day(year) + day = + case year + when 1851..1899 + 22.2588 + when 1900..1979 + 23.2588 + when 1980..2099 + 23.2488 + when 2100..2150 + 24.2488 + else + raise IndexError.new("Out of range") + end + day += 0.242194 * (year - 1980) - ((year - 1980)/4).floor + day = day.floor + Date.civil(year, 9, day) +end + + +def self.jp_citizons_holiday(year) + year < 2003 and return nil + ncd = Holidays.jp_national_culture_day(year) + if ncd.wday == 3 + ncd - 1 + else + nil + end +end + + +def self.jp_substitute_holiday(*date) + date = date[0].kind_of?(Date) ? date.first : Date.civil(*date) + date.wday == 0 ? date+1 : nil +end + + + +end + +Holidays.merge_defs(Holidays::JP::DEFINED_REGIONS, Holidays::JP::HOLIDAYS_BY_MONTH) diff --git a/test/defs/test_defs_jp.rb b/test/defs/test_defs_jp.rb new file mode 100644 index 0000000..7c72d1c --- /dev/null +++ b/test/defs/test_defs_jp.rb @@ -0,0 +1,50 @@ +# encoding: utf-8 +require File.expand_path(File.dirname(__FILE__)) + '/../test_helper' + +# This file is generated by the Ruby Holiday gem. +# +# Definitions loaded: data/jp.yaml +class JpDefinitionTests < Test::Unit::TestCase # :nodoc: + + def test_jp +{Date.civil(2008,1,1) => '元日', + Date.civil(2010,1,11) => '成人の日', + Date.civil(2008,2,11) => '建国記念日', + Date.civil(2008,4,29) => '昭和の日', + Date.civil(2008,5,3) => '憲法記念日', + Date.civil(2008,5,5) => 'こどもの日', + Date.civil(2010,7,19) => '海の日', + Date.civil(2010,9,20) => '敬老の日', + Date.civil(2010,10,11) => '体育の日', + Date.civil(2008,11,3) => '文化の日', + Date.civil(2008,11,23) => '勤労感謝の日', + Date.civil(2008,12,23) => '天皇誕生日', + Date.civil(2010,3,22) => '振替休日', + Date.civil(2008,11,24) => '振替休日', +}.each do |date, name| + assert_equal name, (Holidays.on(date, :jp, :informal)[0] || {})[:name] +end + +# vernal equinox day +[Date.civil(2004,3,20), Date.civil(2005,3,20), Date.civil(2006,3,21), + Date.civil(2007,3,21), Date.civil(2008,3,20), Date.civil(2009,3,20), + Date.civil(2010,3,21)].each do |date| + assert_equal '春分の日', Holidays.on(date, :jp)[0][:name] +end + +# national culture day +[Date.civil(2004,9,23), Date.civil(2005,9,23), Date.civil(2006,9,23), + Date.civil(2007,9,23), Date.civil(2008,9,23), Date.civil(2009,9,23), + Date.civil(2010,9,23), Date.civil(2011,9,23), Date.civil(2012,9,22), + Date.civil(2013,9,23)].each do |date| + assert_equal '秋分の日', Holidays.on(date, :jp)[0][:name] +end + +# citizons holiday +[Date.civil(2032,9,21), Date.civil(2049,9,21), Date.civil(2009,9,22), + Date.civil(2015,9,22), Date.civil(2026,9,22)].each do |date| + assert_equal '国民の休日', Holidays.on(date, :jp)[0][:name] +end + + end +end