zakuro 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.editorconfig +4 -0
- data/.gitignore +7 -1
- data/Gemfile +2 -0
- data/Makefile +2 -0
- data/README.md +63 -30
- data/Rakefile +1 -1
- data/doc/gengou.md +315 -0
- data/lib/zakuro/condition.rb +2 -2
- data/lib/zakuro/era/gengou/set-001-until-south.yaml +911 -165
- data/lib/zakuro/era/gengou/set-002-from-north.yaml +402 -83
- data/lib/zakuro/era/gengou/set-003-modern.yaml +18 -2
- data/lib/zakuro/era/japan.rb +39 -9
- data/lib/zakuro/era/western.rb +10 -0
- data/lib/zakuro/output/response.rb +4 -4
- data/lib/zakuro/version.rb +1 -1
- data/lib/zakuro/version/senmyou/README.md +3 -1
- data/lib/zakuro/version/senmyou/base/era.rb +2 -0
- data/lib/zakuro/version/senmyou/base/multi_gengou.rb +98 -0
- data/lib/zakuro/version/senmyou/base/multi_gengou_roller.rb +205 -0
- data/lib/zakuro/version/senmyou/base/year.rb +52 -6
- data/lib/zakuro/version/senmyou/monthly/month.rb +10 -0
- data/lib/zakuro/version/senmyou/senmyou.rb +2 -2
- data/lib/zakuro/version/senmyou/stella/solar_average.rb +26 -14
- data/lib/zakuro/version/senmyou/summary/{annual_data.rb → annual_range.rb} +21 -21
- data/lib/zakuro/version/senmyou/summary/full_range.rb +216 -0
- data/lib/zakuro/version/senmyou/summary/specifier.rb +100 -0
- metadata +13 -9
- data/lib/zakuro/version/senmyou/base/gengou.rb +0 -210
- data/lib/zakuro/version/senmyou/summary/gengou_data.rb +0 -294
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative './era'
|
4
|
+
|
3
5
|
# :nodoc:
|
4
6
|
module Zakuro
|
5
7
|
# :nodoc:
|
@@ -9,18 +11,63 @@ module Zakuro
|
|
9
11
|
#
|
10
12
|
class Year
|
11
13
|
# @return [Gengou] 元号
|
12
|
-
attr_reader :
|
14
|
+
attr_reader :multi_gengou
|
13
15
|
# @return [Array<Month>] 年内の全ての月
|
14
16
|
attr_reader :months
|
17
|
+
# @return [Integer] 年の日数
|
18
|
+
attr_reader :total_days
|
19
|
+
# @return [Western::Calendar] 元旦
|
20
|
+
attr_reader :new_year_date
|
15
21
|
|
16
22
|
#
|
17
23
|
# 初期化
|
18
24
|
#
|
19
|
-
# @param [Gengou]
|
25
|
+
# @param [Gengou] multi_gengou 元号
|
26
|
+
#
|
27
|
+
def initialize(multi_gengou: MultiGengou.new, new_year_date: Western::Calendar.new,
|
28
|
+
months: [], total_days: 0)
|
29
|
+
@multi_gengou = multi_gengou
|
30
|
+
@months = months
|
31
|
+
@new_year_date = new_year_date
|
32
|
+
@total_days = total_days
|
33
|
+
end
|
34
|
+
|
35
|
+
#
|
36
|
+
# 年の日数を確定する
|
37
|
+
#
|
38
|
+
def commit
|
39
|
+
@total_days = 0
|
40
|
+
months.each do |month|
|
41
|
+
@total_days += month.days
|
42
|
+
end
|
43
|
+
|
44
|
+
self
|
45
|
+
end
|
46
|
+
|
47
|
+
#
|
48
|
+
# 次年にする
|
49
|
+
#
|
50
|
+
# @param [Japan::Gengou] first_line 元号(1行目)
|
51
|
+
# @param [Japan::Gengou] second_line 元号(2行目)
|
52
|
+
#
|
53
|
+
# @return [MultiGengou] 自身
|
54
|
+
#
|
55
|
+
def next_year
|
56
|
+
@multi_gengou.next_year
|
57
|
+
|
58
|
+
@new_year_date += @total_days
|
59
|
+
@total_days = 0
|
60
|
+
|
61
|
+
self
|
62
|
+
end
|
63
|
+
|
64
|
+
#
|
65
|
+
# 十干十二支を取得する
|
66
|
+
#
|
67
|
+
# @return [String] 十干十二支
|
20
68
|
#
|
21
|
-
def
|
22
|
-
@
|
23
|
-
@months = []
|
69
|
+
def zodiac_name
|
70
|
+
Era.zodiac_name(western_year: @new_year_date.year)
|
24
71
|
end
|
25
72
|
|
26
73
|
#
|
@@ -32,7 +79,6 @@ module Zakuro
|
|
32
79
|
return if duplicated?(month: month)
|
33
80
|
|
34
81
|
@months.push(month)
|
35
|
-
@gengou.add_days(days: month.days)
|
36
82
|
|
37
83
|
nil
|
38
84
|
end
|
@@ -96,6 +96,16 @@ module Zakuro
|
|
96
96
|
@number == other.number && @leaped == other.leaped
|
97
97
|
end
|
98
98
|
|
99
|
+
#
|
100
|
+
# 二十四節気が未設定かどうかを検証する
|
101
|
+
#
|
102
|
+
# @return [True] 設定なし
|
103
|
+
# @return [False] 設定あり
|
104
|
+
#
|
105
|
+
def empty_solar_term?
|
106
|
+
@even_term.invalid? && @odd_term.invalid?
|
107
|
+
end
|
108
|
+
|
99
109
|
#
|
100
110
|
# 文字化する
|
101
111
|
#
|
@@ -3,7 +3,7 @@
|
|
3
3
|
require 'date'
|
4
4
|
require_relative '../abstract_version'
|
5
5
|
require_relative '../../era/western'
|
6
|
-
require_relative 'summary/
|
6
|
+
require_relative 'summary/specifier'
|
7
7
|
|
8
8
|
# :nodoc:
|
9
9
|
module Zakuro
|
@@ -27,7 +27,7 @@ module Zakuro
|
|
27
27
|
#
|
28
28
|
def self.to_japan_date(western_date:)
|
29
29
|
date = Western::Calendar.create(date: western_date)
|
30
|
-
|
30
|
+
SingleDaySpecifier.get(date: date)
|
31
31
|
end
|
32
32
|
end
|
33
33
|
end
|
@@ -17,11 +17,11 @@ module Zakuro
|
|
17
17
|
# 冬至から数えた1年データの月ごとに二十四節気を割り当てる
|
18
18
|
#
|
19
19
|
# @param [Integer] western_year 西暦年
|
20
|
-
# @param [Array<Month>]
|
20
|
+
# @param [Array<Month>] annual_range 1年データ
|
21
21
|
#
|
22
22
|
# @return [Array<Month>] 1年データ
|
23
23
|
#
|
24
|
-
def self.
|
24
|
+
def self.set_solar_terms_into_annual_range(western_year:, annual_range:)
|
25
25
|
# 天正冬至
|
26
26
|
winter_solstice = WinterSolstice.calc(western_year: western_year)
|
27
27
|
|
@@ -30,17 +30,17 @@ module Zakuro
|
|
30
30
|
winter_solstice: winter_solstice
|
31
31
|
)
|
32
32
|
|
33
|
-
apply_solar_terms_from_last_winter_solstice(
|
33
|
+
apply_solar_terms_from_last_winter_solstice(annual_range: annual_range,
|
34
34
|
solar_terms: solar_terms)
|
35
35
|
|
36
36
|
# 前後の二十四節気
|
37
37
|
rest_solar_terms = \
|
38
38
|
collect_solar_terms_before_and_after(solar_terms: solar_terms)
|
39
39
|
|
40
|
-
apply_solar_terms_before_and_after(
|
40
|
+
apply_solar_terms_before_and_after(annual_range: annual_range,
|
41
41
|
rest_solar_terms: rest_solar_terms)
|
42
42
|
|
43
|
-
|
43
|
+
annual_range
|
44
44
|
end
|
45
45
|
|
46
46
|
# :reek:TooManyStatements { max_statements: 6 }
|
@@ -69,16 +69,21 @@ module Zakuro
|
|
69
69
|
#
|
70
70
|
# 各月の二十四節気を設定する
|
71
71
|
#
|
72
|
-
# @param [Array<Month>]
|
72
|
+
# @param [Array<Month>] annual_range 1年データ
|
73
73
|
# @param [Array<Remainder>] solar_terms 1年データ内の全二十四節気
|
74
74
|
#
|
75
|
-
def self.apply_solar_terms_from_last_winter_solstice(
|
75
|
+
def self.apply_solar_terms_from_last_winter_solstice(annual_range:,
|
76
76
|
solar_terms:)
|
77
|
+
|
77
78
|
c_idx = 0
|
78
79
|
st_idx = 0
|
79
|
-
|
80
|
-
|
81
|
-
|
80
|
+
month_size = annual_range.size
|
81
|
+
|
82
|
+
while c_idx < month_size && st_idx < solar_terms.size
|
83
|
+
raise StandardError, "month is over. idx: #{c_idx}" if c_idx >= month_size
|
84
|
+
|
85
|
+
current_month = annual_range[c_idx]
|
86
|
+
next_month = annual_range[c_idx + 1]
|
82
87
|
solar_term = solar_terms[st_idx]
|
83
88
|
|
84
89
|
if in_range_solar_term?(target: solar_term, min: current_month.remainder,
|
@@ -88,6 +93,13 @@ module Zakuro
|
|
88
93
|
st_idx += 1
|
89
94
|
next
|
90
95
|
end
|
96
|
+
|
97
|
+
# 一度も割り当てがない場合は二十四節気を進める
|
98
|
+
if current_month.empty_solar_term?
|
99
|
+
st_idx += 1
|
100
|
+
next
|
101
|
+
end
|
102
|
+
|
91
103
|
c_idx += 1
|
92
104
|
end
|
93
105
|
end
|
@@ -120,18 +132,18 @@ module Zakuro
|
|
120
132
|
#
|
121
133
|
# 1年データ前後の二十四節気を適用する
|
122
134
|
#
|
123
|
-
# @param [Array<Month>]
|
135
|
+
# @param [Array<Month>] annual_range 1年データ
|
124
136
|
# @param [Hash<Integer, Hash<Symbol, Integer>>, Hash<Integer, Hash<Symbol, Remainder>>]
|
125
137
|
# rest_solar_terms 前後
|
126
138
|
#
|
127
|
-
def self.apply_solar_terms_before_and_after(
|
139
|
+
def self.apply_solar_terms_before_and_after(annual_range:, rest_solar_terms:)
|
128
140
|
rest_solar_terms.each do |key, value|
|
129
141
|
index = value[:index]
|
130
142
|
solar_term = value[:solar_term]
|
131
|
-
data =
|
143
|
+
data = annual_range[index]
|
132
144
|
next unless in_range_solar_term?(
|
133
145
|
target: solar_term,
|
134
|
-
min: data.remainder, max:
|
146
|
+
min: data.remainder, max: annual_range[index + 1].remainder
|
135
147
|
)
|
136
148
|
|
137
149
|
set_solar_term(month: data,
|
@@ -13,10 +13,10 @@ require_relative '../stella/lunar_orbit'
|
|
13
13
|
module Zakuro
|
14
14
|
# :nodoc:
|
15
15
|
module Senmyou
|
16
|
-
#
|
17
|
-
module
|
16
|
+
# AnnualRange 年間データ
|
17
|
+
module AnnualRange
|
18
18
|
# @return [Logger] ロガー
|
19
|
-
LOGGER = Logger.new(location: '
|
19
|
+
LOGGER = Logger.new(location: 'annual_range')
|
20
20
|
|
21
21
|
# :reek:TooManyStatements { max_statements: 6 }
|
22
22
|
|
@@ -61,20 +61,20 @@ module Zakuro
|
|
61
61
|
#
|
62
62
|
# @return [Array<Month>] 1年データ
|
63
63
|
#
|
64
|
-
def self.
|
65
|
-
|
64
|
+
def self.collect_annual_range_after_last_november_1st(western_year:)
|
65
|
+
annual_range = initialized_annual_range(western_year: western_year)
|
66
66
|
|
67
|
-
apply_big_and_small_of_the_month(
|
67
|
+
apply_big_and_small_of_the_month(annual_range: annual_range)
|
68
68
|
|
69
|
-
SolarAverage.
|
70
|
-
|
69
|
+
SolarAverage.set_solar_terms_into_annual_range(western_year: western_year,
|
70
|
+
annual_range: annual_range)
|
71
71
|
|
72
72
|
# 月間隔を取得するためだけの末尾要素を削除
|
73
|
-
|
73
|
+
annual_range.pop
|
74
74
|
|
75
|
-
adjust_leap_month(
|
75
|
+
adjust_leap_month(annual_range: annual_range)
|
76
76
|
|
77
|
-
|
77
|
+
annual_range
|
78
78
|
end
|
79
79
|
|
80
80
|
#
|
@@ -112,7 +112,7 @@ module Zakuro
|
|
112
112
|
#
|
113
113
|
# @return [Array<Month>] 1年データ
|
114
114
|
#
|
115
|
-
def self.
|
115
|
+
def self.initialized_annual_range(western_year:)
|
116
116
|
result = []
|
117
117
|
lunar_phase = LunarPhase.new(western_year: western_year)
|
118
118
|
|
@@ -133,18 +133,18 @@ module Zakuro
|
|
133
133
|
end
|
134
134
|
result
|
135
135
|
end
|
136
|
-
private_class_method :
|
136
|
+
private_class_method :initialized_annual_range
|
137
137
|
|
138
138
|
#
|
139
139
|
# 1年データの各月に月の大小を設定する
|
140
140
|
#
|
141
|
-
# @param [Array<Month>]
|
141
|
+
# @param [Array<Month>] annual_range 1年データ
|
142
142
|
#
|
143
|
-
def self.apply_big_and_small_of_the_month(
|
144
|
-
size =
|
143
|
+
def self.apply_big_and_small_of_the_month(annual_range:)
|
144
|
+
size = annual_range.size - 1
|
145
145
|
(0...size).each do |idx|
|
146
|
-
current_month =
|
147
|
-
next_month =
|
146
|
+
current_month = annual_range[idx]
|
147
|
+
next_month = annual_range[idx + 1]
|
148
148
|
current_month.is_many_days = \
|
149
149
|
current_month.remainder.same_remainder_divided_by_ten?(
|
150
150
|
other: next_month.remainder.day
|
@@ -159,12 +159,12 @@ module Zakuro
|
|
159
159
|
# 閏月が存在した場合に以降の月を1つずつ減らす
|
160
160
|
# @example 7,8,9 と続く月の8月が閏の場合、7, 閏7, 8 となる
|
161
161
|
#
|
162
|
-
# @param [Array<Month>]
|
162
|
+
# @param [Array<Month>] annual_range 1年データ
|
163
163
|
#
|
164
|
-
def self.adjust_leap_month(
|
164
|
+
def self.adjust_leap_month(annual_range:)
|
165
165
|
# 閏による月の再調整を行う
|
166
166
|
leaped = false
|
167
|
-
|
167
|
+
annual_range.each do |month|
|
168
168
|
if month.even_term.invalid?
|
169
169
|
month.leaped = true
|
170
170
|
leaped = true
|
@@ -0,0 +1,216 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../base/multi_gengou_roller'
|
4
|
+
|
5
|
+
require_relative '../../../era/western'
|
6
|
+
require_relative './annual_range'
|
7
|
+
|
8
|
+
# :nodoc:
|
9
|
+
module Zakuro
|
10
|
+
# :nodoc:
|
11
|
+
module Senmyou
|
12
|
+
# FullRange 完全範囲
|
13
|
+
# ある日からある日の範囲を計算可能な年月範囲
|
14
|
+
# * 前提として元号年はその元号の開始年から数える
|
15
|
+
# * ある日の元号年を求める場合、その元号が含まれる最初の年まで遡る
|
16
|
+
# * 元号は一つとは限らない。南北朝などで二つある場合は、古い方の元号から求める
|
17
|
+
#
|
18
|
+
# NOTE: 割り当てた元号は年初を基準にした元号年である
|
19
|
+
# * 元旦を基準にした時の正しい元号を設定している
|
20
|
+
# * 引き当てたい日付が元旦ではない場合、その月日に従い元号を再度求める
|
21
|
+
# * この再計算が必要になるのは、元号が切り替わる年のみである
|
22
|
+
class FullRange
|
23
|
+
attr_reader :multi_gengou_roller
|
24
|
+
attr_reader :new_year_date
|
25
|
+
attr_reader :western_year
|
26
|
+
|
27
|
+
# @return [Logger] ロガー
|
28
|
+
LOGGER = Logger.new(location: 'full_range')
|
29
|
+
|
30
|
+
def initialize(start_date: Western::Calendar.new, end_date: Western::Calendar.new)
|
31
|
+
@multi_gengou_roller = MultiGengouRoller.new(start_date: start_date, end_date: end_date)
|
32
|
+
@new_year_date = @multi_gengou_roller.oldest_date.clone
|
33
|
+
@western_year = @new_year_date.year
|
34
|
+
end
|
35
|
+
|
36
|
+
#
|
37
|
+
# 完全範囲を取得する
|
38
|
+
#
|
39
|
+
# @return [Array<Year>] 完全範囲
|
40
|
+
#
|
41
|
+
def get
|
42
|
+
years = FullRange.rearranged_years(annual_ranges: annual_ranges)
|
43
|
+
years = update_gengou(years: years)
|
44
|
+
years
|
45
|
+
end
|
46
|
+
|
47
|
+
# :reek:TooManyStatements { max_statements: 6 }
|
48
|
+
|
49
|
+
#
|
50
|
+
# 完全範囲内の年データを取得する
|
51
|
+
#
|
52
|
+
# @return [Array<Year>] 年データ(冬至基準)
|
53
|
+
#
|
54
|
+
def annual_ranges
|
55
|
+
oldest_date = @new_year_date
|
56
|
+
newest_date = @multi_gengou_roller.newest_date
|
57
|
+
|
58
|
+
years = []
|
59
|
+
((oldest_date.year)..(newest_date.year + 2)).each do |year|
|
60
|
+
years.push(
|
61
|
+
AnnualRange.collect_annual_range_after_last_november_1st(
|
62
|
+
western_year: year
|
63
|
+
)
|
64
|
+
)
|
65
|
+
end
|
66
|
+
|
67
|
+
years
|
68
|
+
end
|
69
|
+
|
70
|
+
#
|
71
|
+
# 完全範囲内の年データの開始月を変更する
|
72
|
+
#
|
73
|
+
# @param [Array<Year>] annual_ranges 年データ(冬至基準)
|
74
|
+
#
|
75
|
+
# @return [Array<Year>] 年データ(元旦基準)
|
76
|
+
#
|
77
|
+
def self.rearranged_years(annual_ranges:)
|
78
|
+
years = []
|
79
|
+
|
80
|
+
(0..(annual_ranges.size - 2)).each do |index|
|
81
|
+
year = rearranged_year(annual_ranges: annual_ranges, index: index)
|
82
|
+
years.push(year)
|
83
|
+
end
|
84
|
+
|
85
|
+
years
|
86
|
+
end
|
87
|
+
|
88
|
+
# :reek:TooManyStatements { max_statements: 8 }
|
89
|
+
|
90
|
+
#
|
91
|
+
# 完全範囲内の年データの元号を開始年基準で更新する
|
92
|
+
#
|
93
|
+
# @param [Array<Year>] years 年データ(元旦基準)
|
94
|
+
#
|
95
|
+
# @return [Array<Year>] 元号更新済み年データ(元旦基準)
|
96
|
+
#
|
97
|
+
def update_gengou(years:)
|
98
|
+
updated_years = []
|
99
|
+
|
100
|
+
nearest_end_date = choise_nearest_end_date
|
101
|
+
|
102
|
+
years.each do |year|
|
103
|
+
next_year(years: updated_years, year: year)
|
104
|
+
|
105
|
+
if @new_year_date > nearest_end_date
|
106
|
+
@multi_gengou_roller.transfer
|
107
|
+
nearest_end_date = choise_nearest_end_date
|
108
|
+
end
|
109
|
+
@multi_gengou_roller.next_year
|
110
|
+
end
|
111
|
+
|
112
|
+
updated_years
|
113
|
+
end
|
114
|
+
|
115
|
+
#
|
116
|
+
# 当年データを生成する
|
117
|
+
#
|
118
|
+
def self.push_current_year(annual_range:, year: Year.new)
|
119
|
+
annual_range.each do |month|
|
120
|
+
next if month.is_last_year
|
121
|
+
|
122
|
+
year.push(month: month)
|
123
|
+
end
|
124
|
+
|
125
|
+
year
|
126
|
+
end
|
127
|
+
|
128
|
+
#
|
129
|
+
# 当年データを生成する
|
130
|
+
#
|
131
|
+
def self.push_last_year(annual_range:, year: Year.new)
|
132
|
+
annual_range.each do |month|
|
133
|
+
next unless month.is_last_year
|
134
|
+
|
135
|
+
year.push(month: month)
|
136
|
+
end
|
137
|
+
|
138
|
+
year
|
139
|
+
end
|
140
|
+
|
141
|
+
#
|
142
|
+
# 年データの開始月を変更する
|
143
|
+
#
|
144
|
+
# @param [Array<Year>] annual_ranges 年データ(冬至基準)
|
145
|
+
#
|
146
|
+
# @return [Year] 年データ(元旦基準)
|
147
|
+
#
|
148
|
+
def self.rearranged_year(annual_ranges:, index:)
|
149
|
+
current_annual_range = annual_ranges[index]
|
150
|
+
next_annual_range = annual_ranges[index + 1]
|
151
|
+
|
152
|
+
year = push_current_year(annual_range: current_annual_range)
|
153
|
+
push_last_year(annual_range: next_annual_range, year: year)
|
154
|
+
|
155
|
+
year
|
156
|
+
end
|
157
|
+
private_class_method :rearranged_year
|
158
|
+
|
159
|
+
private
|
160
|
+
|
161
|
+
#
|
162
|
+
# 元号処理対象の年を進める
|
163
|
+
#
|
164
|
+
# @param [Array<Year>] years 元号処理済み年データ(元旦基準)
|
165
|
+
# @param [Year] year 元号処理前の年(元旦基準)
|
166
|
+
#
|
167
|
+
def next_year(years:, year:)
|
168
|
+
updated_year = update_year(year: year)
|
169
|
+
|
170
|
+
years.push(updated_year)
|
171
|
+
|
172
|
+
next_new_year_date(total_days: updated_year.total_days)
|
173
|
+
|
174
|
+
nil
|
175
|
+
end
|
176
|
+
|
177
|
+
#
|
178
|
+
# 年の元号を更新する
|
179
|
+
#
|
180
|
+
# @param [Year] year 元号処理前の年(元旦基準)
|
181
|
+
#
|
182
|
+
# @return [Year] 元号処理済の年(元旦基準)
|
183
|
+
#
|
184
|
+
def update_year(year:)
|
185
|
+
multi_gengou = @multi_gengou_roller.multi_gengou.clone
|
186
|
+
|
187
|
+
updated_year = Year.new(multi_gengou: multi_gengou, new_year_date: @new_year_date.clone,
|
188
|
+
months: year.months)
|
189
|
+
updated_year.commit
|
190
|
+
|
191
|
+
updated_year
|
192
|
+
end
|
193
|
+
|
194
|
+
#
|
195
|
+
# 次の年に進める
|
196
|
+
#
|
197
|
+
# @param [Integer] total_days 年の日数
|
198
|
+
#
|
199
|
+
def next_new_year_date(total_days:)
|
200
|
+
@new_year_date += total_days
|
201
|
+
@multi_gengou_roller.next(days: total_days)
|
202
|
+
|
203
|
+
nil
|
204
|
+
end
|
205
|
+
|
206
|
+
#
|
207
|
+
# 現在日からみて直近の未来に対する元号の切替前日を求める
|
208
|
+
#
|
209
|
+
# @return [Western::Calendar] 元号の切替前日
|
210
|
+
#
|
211
|
+
def choise_nearest_end_date
|
212
|
+
@multi_gengou_roller.choise_nearest_end_date
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|