zakuro 0.1.1 → 0.1.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/lib/zakuro/operation/month/parser.rb +1 -1
- data/lib/zakuro/operation/month/type.rb +5 -10
- data/lib/zakuro/version.rb +1 -1
- data/lib/zakuro/version/senmyou/base/solar_term.rb +62 -0
- data/lib/zakuro/version/senmyou/monthly/initialized_month.rb +71 -0
- data/lib/zakuro/version/senmyou/monthly/lunar_phase.rb +2 -2
- data/lib/zakuro/version/senmyou/monthly/operated_month.rb +77 -48
- data/lib/zakuro/version/senmyou/range/annual_range.rb +17 -42
- data/lib/zakuro/version/senmyou/range/full_range.rb +8 -138
- data/lib/zakuro/version/senmyou/range/western_date_allocation.rb +68 -0
- data/lib/zakuro/version/senmyou/range/year_boundary.rb +138 -0
- data/lib/zakuro/version/senmyou/stella/lunar_orbit.rb +1 -1
- data/lib/zakuro/version/senmyou/stella/solar_average.rb +101 -146
- data/lib/zakuro/version/senmyou/stella/solar_location.rb +213 -0
- data/lib/zakuro/version/senmyou/stella/solar_orbit.rb +1 -182
- metadata +9 -6
@@ -7,208 +7,163 @@ module Zakuro
|
|
7
7
|
#
|
8
8
|
# SolarAverage 常気(太陽軌道平均)
|
9
9
|
#
|
10
|
-
|
10
|
+
class SolarAverage
|
11
11
|
# @return [Remainder] 気策(24分の1年)
|
12
12
|
SOLAR_TERM_AVERAGE = Remainder.new(day: 15, minute: 1835, second: 5)
|
13
13
|
|
14
|
-
# :reek:TooManyStatements { max_statements: 6 }
|
15
|
-
|
16
14
|
#
|
17
|
-
#
|
15
|
+
# 初期化
|
18
16
|
#
|
19
17
|
# @param [Integer] western_year 西暦年
|
20
|
-
# @param [Array<Month>] annual_range 1年データ
|
21
|
-
#
|
22
|
-
# @return [Array<Month>] 1年データ
|
23
18
|
#
|
24
|
-
def
|
25
|
-
|
26
|
-
winter_solstice = WinterSolstice.calc(western_year: western_year)
|
27
|
-
|
28
|
-
# 前年冬至からの二十四節気
|
29
|
-
solar_terms = collect_solar_terms_from_last_winter_solstice(
|
30
|
-
winter_solstice: winter_solstice
|
31
|
-
)
|
32
|
-
|
33
|
-
apply_solar_terms_from_last_winter_solstice(annual_range: annual_range,
|
34
|
-
solar_terms: solar_terms)
|
35
|
-
|
36
|
-
# 前後の二十四節気
|
37
|
-
rest_solar_terms = \
|
38
|
-
collect_solar_terms_before_and_after(solar_terms: solar_terms)
|
39
|
-
|
40
|
-
apply_solar_terms_before_and_after(annual_range: annual_range,
|
41
|
-
rest_solar_terms: rest_solar_terms)
|
42
|
-
|
43
|
-
annual_range
|
19
|
+
def initialize(western_year:)
|
20
|
+
@solar_term = SolarAverage.first_solar_term(western_year: western_year)
|
44
21
|
end
|
45
22
|
|
46
|
-
# :reek:TooManyStatements { max_statements: 6 }
|
47
|
-
|
48
23
|
#
|
49
|
-
#
|
24
|
+
# 冬至から数えた1年データの月ごとに二十四節気を割り当てる
|
50
25
|
#
|
51
|
-
# @param [
|
26
|
+
# @param [Array<Month>] annual_range 1年データ
|
52
27
|
#
|
53
|
-
# @return [Array<
|
28
|
+
# @return [Array<Month>] 1年データ
|
54
29
|
#
|
55
|
-
def
|
56
|
-
|
57
|
-
|
58
|
-
(
|
59
|
-
|
60
|
-
|
30
|
+
def set(annual_range:)
|
31
|
+
# 次月と比較しながら当月の二十四節気を決める
|
32
|
+
# NOTE: 最後の月は処理できない(=計算外の余分な月が最後に必要である)
|
33
|
+
annual_range.each_cons(2) do |(current_month, next_month)|
|
34
|
+
set_solar_term(
|
35
|
+
current_month: current_month,
|
36
|
+
next_month: next_month
|
37
|
+
)
|
61
38
|
end
|
62
39
|
|
63
|
-
|
40
|
+
annual_range
|
64
41
|
end
|
65
|
-
private_class_method :collect_solar_terms_from_last_winter_solstice
|
66
|
-
|
67
|
-
# :reek:TooManyStatements { max_statements: 9 }
|
68
42
|
|
69
43
|
#
|
70
|
-
#
|
44
|
+
# 計算開始する二十四節気を求める
|
71
45
|
#
|
72
|
-
# @param [
|
73
|
-
#
|
46
|
+
# @param [Integer] western_year 西暦年
|
47
|
+
#
|
48
|
+
# @return [SolarTerm] 二十四節気
|
74
49
|
#
|
75
|
-
def self.
|
76
|
-
|
77
|
-
|
78
|
-
month_size = annual_range.size
|
50
|
+
def self.first_solar_term(western_year:)
|
51
|
+
# 天正冬至
|
52
|
+
winter_solstice = WinterSolstice.calc(western_year: western_year)
|
79
53
|
|
80
|
-
|
81
|
-
|
54
|
+
# 二十四節気(冬至)
|
55
|
+
solar_term = SolarTerm.new(index: 0, remainder: winter_solstice)
|
82
56
|
|
83
|
-
|
84
|
-
next_month: annual_range[month_index + 1],
|
85
|
-
solar_term: solar_terms[solar_term_index],
|
86
|
-
solar_term_index: solar_term_index)
|
87
|
-
solar_term_index += 1
|
88
|
-
next
|
89
|
-
end
|
57
|
+
first_solar_term_index = SolarAverage.calc_fist_solar_term_index(western_year: western_year)
|
90
58
|
|
91
|
-
|
92
|
-
|
93
|
-
end
|
94
|
-
private_class_method :apply_solar_terms_from_last_winter_solstice
|
59
|
+
# 対象の二十四節気まで戻す
|
60
|
+
solar_term.prev_by_index(first_solar_term_index)
|
95
61
|
|
96
|
-
|
97
|
-
# 当月に二十四節気を設定する
|
98
|
-
#
|
99
|
-
# @param [Remainder] current_month 当月
|
100
|
-
# @param [Month] next_month 次月
|
101
|
-
# @param [Month] solar_term 二十四節気
|
102
|
-
# @param [Integer] solar_term_index 二十四節気位置
|
103
|
-
#
|
104
|
-
# @return [True] 設定済
|
105
|
-
# @return [False] 未設定
|
106
|
-
#
|
107
|
-
def self.set_solar_term_on_current_month(current_month:,
|
108
|
-
next_month:, solar_term:, solar_term_index:)
|
109
|
-
if in_range_solar_term?(target: solar_term, min: current_month.remainder,
|
110
|
-
max: next_month.remainder)
|
111
|
-
set_solar_term(month: current_month,
|
112
|
-
solar_term: solar_term, solar_term_index: solar_term_index)
|
113
|
-
return true
|
114
|
-
end
|
115
|
-
|
116
|
-
# 一度も割り当てがない場合は設定済みとして次の二十四節気を進める
|
117
|
-
return true if current_month.empty_solar_term?
|
118
|
-
|
119
|
-
false
|
62
|
+
solar_term
|
120
63
|
end
|
121
64
|
|
122
65
|
#
|
123
|
-
#
|
66
|
+
# 計算開始する二十四節気番号を求める
|
67
|
+
#
|
68
|
+
# * 前提として入定気は冬至の手前にある
|
69
|
+
# * 例えば、定気が大雪であれば入定気は大雪の範囲内にある
|
70
|
+
# * 入定気は、定気の開始位置に重複しない限り、常に定気より後にある
|
71
|
+
# * 基本的に定気の一つ前から起算すれば、当時から求めた11月(閏10/閏11月)に二十四節気を割り当てられる
|
124
72
|
#
|
125
|
-
# @param [
|
73
|
+
# @param [Integer] western_year 西暦年
|
126
74
|
#
|
127
|
-
# @return [
|
75
|
+
# @return [Integer] 二十四節気番号
|
128
76
|
#
|
129
|
-
def self.
|
130
|
-
|
77
|
+
def self.calc_fist_solar_term_index(western_year:)
|
78
|
+
# 天正閏余
|
79
|
+
winter_solstice_age = \
|
80
|
+
WinterSolstice.calc_moon_age(western_year: western_year)
|
131
81
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
# 当年冬至
|
137
|
-
0 => { index: -2, solar_term: touji },
|
138
|
-
# 当年小寒
|
139
|
-
1 => { index: -2, solar_term: touji.add(SOLAR_TERM_AVERAGE) }
|
140
|
-
}
|
141
|
-
end
|
142
|
-
private_class_method :collect_solar_terms_before_and_after
|
82
|
+
# 入定気を求める
|
83
|
+
solar_location = SolarLocation.get(
|
84
|
+
solar_term: SolarTerm.new(remainder: winter_solstice_age)
|
85
|
+
)
|
143
86
|
|
144
|
-
|
87
|
+
solar_term_index = solar_location.index
|
145
88
|
|
146
|
-
|
147
|
-
|
148
|
-
#
|
149
|
-
# @param [Array<Month>] annual_range 1年データ
|
150
|
-
# @param [Hash<Integer, Hash<Symbol, Integer>>, Hash<Integer, Hash<Symbol, Remainder>>]
|
151
|
-
# rest_solar_terms 前後
|
152
|
-
#
|
153
|
-
def self.apply_solar_terms_before_and_after(annual_range:, rest_solar_terms:)
|
154
|
-
rest_solar_terms.each do |key, value|
|
155
|
-
index = value[:index]
|
156
|
-
solar_term = value[:solar_term]
|
157
|
-
data = annual_range[index]
|
158
|
-
next unless in_range_solar_term?(
|
159
|
-
target: solar_term,
|
160
|
-
min: data.remainder, max: annual_range[index + 1].remainder
|
161
|
-
)
|
89
|
+
# 入定気の一つ後の二十四節気まで戻す(ただし11月経朔が二十四節気上にある場合は戻さない)
|
90
|
+
solar_term_index += 1 unless solar_location.remainder == Remainder.new(total: 0)
|
162
91
|
|
163
|
-
|
164
|
-
solar_term: solar_term, solar_term_index: key)
|
165
|
-
end
|
92
|
+
solar_term_index
|
166
93
|
end
|
167
|
-
private_class_method :apply_solar_terms_before_and_after
|
168
94
|
|
169
95
|
# :reek:TooManyStatements { max_statements: 7 }
|
170
96
|
|
171
97
|
#
|
172
|
-
#
|
98
|
+
# 月内(当月朔日から当月末日(来月朔日の前日)の間)に二十四節気があるか
|
173
99
|
# @note 大余60で一巡するため 以下2パターンがある
|
174
|
-
# *
|
175
|
-
# *
|
100
|
+
# * current_month <= next_month : (二十四節気) >= current_month && (二十四節気) < next_month
|
101
|
+
# * current_month > next_month : (二十四節気) >= current_month || (二十四節気) < next_month
|
176
102
|
#
|
177
|
-
# @param [Remainder]
|
178
|
-
# @param [Remainder]
|
179
|
-
# @param [Remainder]
|
103
|
+
# @param [Remainder] solar_term 二十四節気
|
104
|
+
# @param [Remainder] current_month 月初
|
105
|
+
# @param [Remainder] next_month 月末
|
180
106
|
#
|
181
107
|
# @return [True] 対象の二十四節気がある
|
182
108
|
# @return [False] 対象の二十四節気がない
|
183
109
|
#
|
184
|
-
def self.
|
110
|
+
def self.in_solar_term?(solar_term:, current_month:, next_month:)
|
185
111
|
# 大余で比較する
|
186
|
-
target_time =
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
112
|
+
target_time = solar_term.day
|
113
|
+
current_month_time = current_month.day
|
114
|
+
next_month_time = next_month.day
|
115
|
+
current_month_over = (target_time >= current_month_time)
|
116
|
+
next_month_under = (target_time < next_month_time)
|
191
117
|
|
192
|
-
|
118
|
+
return current_month_over && next_month_under if current_month_time <= next_month_time
|
119
|
+
|
120
|
+
current_month_over || next_month_under
|
193
121
|
end
|
194
|
-
|
122
|
+
|
123
|
+
private
|
124
|
+
|
125
|
+
# :reek:TooManyStatements { max_statements: 8 }
|
195
126
|
|
196
127
|
#
|
197
128
|
# 二十四節気を設定する
|
198
129
|
#
|
199
|
-
# @param [Month]
|
200
|
-
# @param [
|
201
|
-
# @param [Integer] solar_term_index 連番(二十四節気)
|
130
|
+
# @param [Month] current_month 当月
|
131
|
+
# @param [Month] next_month 次月
|
202
132
|
#
|
203
|
-
def
|
204
|
-
|
133
|
+
def set_solar_term(current_month:, next_month:)
|
134
|
+
# 安全策として無限ループは回避する
|
135
|
+
# * 最大試行回数:4回(設定なし => 設定あり => 設定あり => 設定なし)
|
136
|
+
# * 閏月は1回しか設定しない
|
137
|
+
# * 最大2回設定する(中気・節気)
|
138
|
+
(0..3).each do |_index|
|
139
|
+
in_range = SolarAverage.in_solar_term?(
|
140
|
+
solar_term: @solar_term.remainder, current_month: current_month.remainder,
|
141
|
+
next_month: next_month.remainder
|
142
|
+
)
|
205
143
|
|
206
|
-
|
207
|
-
|
144
|
+
# 範囲外
|
145
|
+
unless in_range
|
146
|
+
# 1つ以上設定されていれば切り上げる(一つ飛ばしで二十四節気を設定することはない)
|
147
|
+
break unless current_month.empty_solar_term?
|
208
148
|
|
209
|
-
|
149
|
+
next_solar_term
|
150
|
+
next
|
151
|
+
end
|
152
|
+
|
153
|
+
current_month.add_term(term: @solar_term.clone)
|
154
|
+
next_solar_term
|
155
|
+
|
156
|
+
# 宣明暦は最大2つまで
|
157
|
+
break if current_month.solar_term_size == 2
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
#
|
162
|
+
# 次の二十四節気に移る
|
163
|
+
#
|
164
|
+
def next_solar_term
|
165
|
+
@solar_term.next!
|
210
166
|
end
|
211
|
-
private_class_method :set_solar_term
|
212
167
|
end
|
213
168
|
end
|
214
169
|
end
|
@@ -0,0 +1,213 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# :nodoc:
|
4
|
+
module Zakuro
|
5
|
+
# :nodoc:
|
6
|
+
module Senmyou
|
7
|
+
#
|
8
|
+
# SolarLocation 入定気演算
|
9
|
+
#
|
10
|
+
# 入定気とは、太陽がどの二十四節気に属するか、またその二十四節気の開始点からどれだけ離れているかを示す
|
11
|
+
#
|
12
|
+
module SolarLocation
|
13
|
+
#
|
14
|
+
# Interval 入気定日加減数(二十四節気の間隔)
|
15
|
+
#
|
16
|
+
module Interval
|
17
|
+
# @return [Hash<Symbol, Remainder>] 一覧
|
18
|
+
LIST = {
|
19
|
+
# 冬至(とうじ)・大雪(たいせつ)
|
20
|
+
touji: Remainder.new(day: 14, minute: 4235, second: 5),
|
21
|
+
taisetsu: Remainder.new(day: 14, minute: 4235, second: 5),
|
22
|
+
# 小寒(しょうかん)・小雪(しょうせつ)
|
23
|
+
shoukan: Remainder.new(day: 14, minute: 5235, second: 5),
|
24
|
+
shousetsu: Remainder.new(day: 14, minute: 5235, second: 5),
|
25
|
+
# 大寒(だいかん)・立冬(りっとう)
|
26
|
+
daikan: Remainder.new(day: 14, minute: 6235, second: 5),
|
27
|
+
rittou: Remainder.new(day: 14, minute: 6235, second: 5),
|
28
|
+
# 立春(りっしゅん)・霜降(そうこう)
|
29
|
+
risshun: Remainder.new(day: 14, minute: 7235, second: 5),
|
30
|
+
soukou: Remainder.new(day: 14, minute: 7235, second: 5),
|
31
|
+
# 雨水(うすい)・寒露(かんろ)
|
32
|
+
usui: Remainder.new(day: 15, minute: 35, second: 5),
|
33
|
+
kanro: Remainder.new(day: 15, minute: 35, second: 5),
|
34
|
+
# 啓蟄(けいちつ)・秋分(しゅうぶん)
|
35
|
+
keichitsu: Remainder.new(day: 15, minute: 1235, second: 5),
|
36
|
+
shuubun: Remainder.new(day: 15, minute: 1235, second: 5),
|
37
|
+
# 春分(しゅんぶん)・白露(はくろ)
|
38
|
+
shunbun: Remainder.new(day: 15, minute: 2435, second: 5),
|
39
|
+
hakuro: Remainder.new(day: 15, minute: 2435, second: 5),
|
40
|
+
# 清明(せいめい)・処暑(しょしょ)
|
41
|
+
seimei: Remainder.new(day: 15, minute: 3635, second: 5),
|
42
|
+
shosho: Remainder.new(day: 15, minute: 3635, second: 5),
|
43
|
+
# 穀雨(こくう)・立秋(りっしゅう)
|
44
|
+
kokuu: Remainder.new(day: 15, minute: 4835, second: 5),
|
45
|
+
risshuu: Remainder.new(day: 15, minute: 4835, second: 5),
|
46
|
+
# 立夏(りっか)・大暑(たいしょ)
|
47
|
+
rikka: Remainder.new(day: 15, minute: 5835, second: 5),
|
48
|
+
taisho: Remainder.new(day: 15, minute: 5835, second: 5),
|
49
|
+
# 小満(しょうまん)・小暑(しょうしょ)
|
50
|
+
shouman: Remainder.new(day: 15, minute: 6835, second: 5),
|
51
|
+
shousho: Remainder.new(day: 15, minute: 6835, second: 5),
|
52
|
+
# 芒種(ぼうしゅ)・夏至(げし)
|
53
|
+
boushu: Remainder.new(day: 15, minute: 7835, second: 5),
|
54
|
+
geshi: Remainder.new(day: 15, minute: 7835, second: 5)
|
55
|
+
}.freeze
|
56
|
+
|
57
|
+
# @return [Array<Remainder>] 索引
|
58
|
+
INDEXES = [
|
59
|
+
LIST[:touji], # 0
|
60
|
+
LIST[:shoukan], # 1
|
61
|
+
LIST[:daikan], # 2
|
62
|
+
LIST[:risshun], # 3
|
63
|
+
LIST[:usui], # 4
|
64
|
+
LIST[:keichitsu], # 5
|
65
|
+
LIST[:shunbun], # 6
|
66
|
+
LIST[:seimei], # 7
|
67
|
+
LIST[:kokuu], # 8
|
68
|
+
LIST[:rikka], # 9
|
69
|
+
LIST[:shouman], # 10
|
70
|
+
LIST[:boushu], # 11
|
71
|
+
LIST[:geshi], # 12
|
72
|
+
LIST[:shousho], # 13
|
73
|
+
LIST[:taisho], # 14
|
74
|
+
LIST[:risshuu], # 15
|
75
|
+
LIST[:shosho], # 16
|
76
|
+
LIST[:hakuro], # 17
|
77
|
+
LIST[:shuubun], # 18
|
78
|
+
LIST[:kanro], # 19
|
79
|
+
LIST[:soukou], # 20
|
80
|
+
LIST[:rittou], # 21
|
81
|
+
LIST[:shousetsu], # 22
|
82
|
+
LIST[:taisetsu] # 23
|
83
|
+
].freeze
|
84
|
+
end
|
85
|
+
|
86
|
+
#
|
87
|
+
# 入定気を計算する
|
88
|
+
#
|
89
|
+
# * 定気(index)の指定がない場合は、11月の入定気を求める
|
90
|
+
# * 定気(index)の指定がある場合は、大余小余から適切な入定気を再計算する
|
91
|
+
#
|
92
|
+
# @param [SolarTerm] solar_term 入定気
|
93
|
+
#
|
94
|
+
# @return [SolarTerm] 入定気
|
95
|
+
#
|
96
|
+
def self.get(solar_term:)
|
97
|
+
if solar_term.invalid?
|
98
|
+
return calc_first_solar_term(
|
99
|
+
winter_solstice_age: solar_term.remainder
|
100
|
+
)
|
101
|
+
end
|
102
|
+
|
103
|
+
calc_next_solar_term_recursively(
|
104
|
+
solar_term: solar_term
|
105
|
+
)
|
106
|
+
end
|
107
|
+
|
108
|
+
# :reek:TooManyStatements { max_statements: 7 }
|
109
|
+
|
110
|
+
#
|
111
|
+
# 入定気(定気の開始点からの日時)と属する定気を計算する
|
112
|
+
#
|
113
|
+
# @param [Remainder] winter_solstice_age 天正冬至
|
114
|
+
#
|
115
|
+
# @return [SolarTerm] 二十四節気
|
116
|
+
# SolarTerm.remainder : 入定気(定気の開始点からの日時)
|
117
|
+
# SolarTerm.index : 定気
|
118
|
+
#
|
119
|
+
def self.calc_first_solar_term(winter_solstice_age:)
|
120
|
+
# 入定気の起算方法
|
121
|
+
# 概要:
|
122
|
+
# * 太陽の運行による補正値は、二十四節気の気ごとに定められる
|
123
|
+
# * 11月経朔の前にある気を求め、それから11月経朔との間隔を求める
|
124
|
+
# * 気ごとの補正値と、気から11月経朔までにかかる補正値を求める
|
125
|
+
# 前提:
|
126
|
+
# * 11月経朔に関わる二十四節気は、時系列から順に、小雪・大雪・冬至である
|
127
|
+
# * 小雪〜大雪の間隔は小雪定数で、大雪〜冬至の間隔は大雪定数で決められている(24気損益眺朒(ちょうじく)数のこと)
|
128
|
+
# * 11月経朔は、この小雪〜冬至の間のいずれかにある
|
129
|
+
# 計算:
|
130
|
+
# 2パターンある
|
131
|
+
# (a) 大雪〜冬至にある場合
|
132
|
+
# *「大雪定数 >= 天正閏余」の場合を指す
|
133
|
+
# * * NOTE 資料では「より大きい(>)」とされるが、大雪そのものの場合は大雪から起算すべき
|
134
|
+
# * この場合は、大雪〜経朔の間隔を求める
|
135
|
+
# (b) 小雪〜大雪にある場合
|
136
|
+
# *「大雪定数 < 天正閏余」の場合を指す
|
137
|
+
# * この場合は、小雪〜経朔の間隔を求める
|
138
|
+
|
139
|
+
# NOTE: 上記パターンとは別に、稀だが立冬のパターンも存在する
|
140
|
+
# この場合は比較方法はそのままに立冬〜経朔の間隔を求める
|
141
|
+
|
142
|
+
rest = winter_solstice_age.clone
|
143
|
+
# 大雪(23)/小雪(22)/立冬(21)
|
144
|
+
[23, 22, 21].each do |index|
|
145
|
+
solar_term = prev_solar_term(winter_solstice_age: rest, index: index)
|
146
|
+
|
147
|
+
if solar_term.invalid?
|
148
|
+
rest = solar_term.remainder
|
149
|
+
next
|
150
|
+
end
|
151
|
+
|
152
|
+
return solar_term
|
153
|
+
end
|
154
|
+
|
155
|
+
# 立冬(21)を超える天正閏余は成立し得ない(1朔望月をはるかに超えることになる)
|
156
|
+
raise ArgumentError.new, 'invalid winster solstice age'
|
157
|
+
end
|
158
|
+
private_class_method :calc_first_solar_term
|
159
|
+
|
160
|
+
#
|
161
|
+
# 入気定日加減数で入定気を遡る
|
162
|
+
#
|
163
|
+
# @param [Remainder] winter_solstice_age 天正冬至
|
164
|
+
# @param [Integer] index 二十四節気の連番
|
165
|
+
#
|
166
|
+
# @return [SolarTerm] 二十四節気
|
167
|
+
# SolarTerm.remainder : 入定気(定気の開始点からの日時)
|
168
|
+
# SolarTerm.index : 定気(範囲外であれば-1とする)
|
169
|
+
#
|
170
|
+
def self.prev_solar_term(winter_solstice_age:, index:)
|
171
|
+
interval = Interval::INDEXES[index]
|
172
|
+
if winter_solstice_age > interval
|
173
|
+
# 入定気が確定しない(さらに前の定気まで遡れる)
|
174
|
+
return SolarTerm.new(
|
175
|
+
remainder: winter_solstice_age.sub(interval),
|
176
|
+
index: -1
|
177
|
+
)
|
178
|
+
end
|
179
|
+
|
180
|
+
# 入定気が確定する
|
181
|
+
SolarTerm.new(
|
182
|
+
remainder: interval.sub(winter_solstice_age),
|
183
|
+
index: index
|
184
|
+
)
|
185
|
+
end
|
186
|
+
private_class_method :prev_solar_term
|
187
|
+
|
188
|
+
# :reek:TooManyStatements { max_statements: 8 }
|
189
|
+
|
190
|
+
#
|
191
|
+
# 次の二十四節気を計算する
|
192
|
+
#
|
193
|
+
# @param [SolarTerm] solar_term 今回の二十四節気
|
194
|
+
#
|
195
|
+
# @return [SolarTerm] 次回の二十四節気
|
196
|
+
#
|
197
|
+
def self.calc_next_solar_term_recursively(solar_term:)
|
198
|
+
remainder = solar_term.remainder
|
199
|
+
index = solar_term.index
|
200
|
+
interval = Interval::INDEXES[index]
|
201
|
+
return solar_term if remainder < interval
|
202
|
+
|
203
|
+
remainder.sub!(interval)
|
204
|
+
index += 1
|
205
|
+
index = 0 if index >= Interval::INDEXES.size
|
206
|
+
calc_next_solar_term_recursively(
|
207
|
+
solar_term: SolarTerm.new(remainder: remainder, index: index)
|
208
|
+
)
|
209
|
+
end
|
210
|
+
private_class_method :calc_next_solar_term_recursively
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|