zakuro 0.0.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/.editorconfig +4 -0
  3. data/.gitignore +7 -1
  4. data/.rubocop.yml +3 -0
  5. data/Gemfile +2 -0
  6. data/Makefile +2 -0
  7. data/README.md +126 -33
  8. data/Rakefile +1 -1
  9. data/doc/gengou.md +315 -0
  10. data/doc/operation.md +25 -0
  11. data/doc/operation/csv/month.csv +202 -0
  12. data/doc/operation/operation.xlsx +0 -0
  13. data/doc/operation/transfer.rb +77 -0
  14. data/lib/zakuro/condition.rb +19 -15
  15. data/lib/zakuro/cycle/abstract_remainder.rb +3 -4
  16. data/lib/zakuro/era/japan/gengou.rb +106 -0
  17. data/lib/zakuro/era/japan/gengou/parser.rb +167 -0
  18. data/lib/zakuro/era/japan/gengou/type.rb +178 -0
  19. data/lib/zakuro/era/japan/gengou/validator.rb +236 -0
  20. data/lib/zakuro/era/japan/reki.rb +91 -0
  21. data/lib/zakuro/era/japan/yaml/set-001-until-south.yaml +1121 -0
  22. data/lib/zakuro/era/japan/yaml/set-002-from-north.yaml +485 -0
  23. data/lib/zakuro/era/japan/yaml/set-003-modern.yaml +28 -0
  24. data/lib/zakuro/era/western.rb +11 -1
  25. data/lib/zakuro/operation/month/parser.rb +373 -0
  26. data/lib/zakuro/operation/month/type.rb +453 -0
  27. data/lib/zakuro/operation/month/validator.rb +802 -0
  28. data/lib/zakuro/operation/operation.rb +66 -0
  29. data/lib/zakuro/operation/yaml/month.yaml +6452 -0
  30. data/lib/zakuro/output/error.rb +2 -0
  31. data/lib/zakuro/output/logger.rb +2 -0
  32. data/lib/zakuro/output/response.rb +21 -19
  33. data/lib/zakuro/result/core.rb +52 -0
  34. data/lib/zakuro/result/data.rb +187 -0
  35. data/lib/zakuro/result/operation.rb +114 -0
  36. data/lib/zakuro/result/result.rb +37 -0
  37. data/lib/zakuro/{output → tools}/stringifier.rb +16 -9
  38. data/lib/zakuro/tools/typeof.rb +33 -0
  39. data/lib/zakuro/version.rb +1 -1
  40. data/lib/zakuro/version/senmyou/README.md +3 -1
  41. data/lib/zakuro/version/senmyou/base/era.rb +3 -1
  42. data/lib/zakuro/version/senmyou/base/multi_gengou.rb +98 -0
  43. data/lib/zakuro/version/senmyou/base/multi_gengou_roller.rb +217 -0
  44. data/lib/zakuro/version/senmyou/base/remainder.rb +4 -4
  45. data/lib/zakuro/version/senmyou/base/solar_term.rb +82 -0
  46. data/lib/zakuro/version/senmyou/base/year.rb +52 -6
  47. data/lib/zakuro/version/senmyou/monthly/first_day.rb +44 -0
  48. data/lib/zakuro/version/senmyou/monthly/initialized_month.rb +119 -0
  49. data/lib/zakuro/version/senmyou/monthly/lunar_phase.rb +3 -3
  50. data/lib/zakuro/version/senmyou/monthly/month.rb +136 -67
  51. data/lib/zakuro/version/senmyou/monthly/month_label.rb +87 -0
  52. data/lib/zakuro/version/senmyou/monthly/operated_month.rb +196 -0
  53. data/lib/zakuro/version/senmyou/{summary/annual_data.rb → range/annual_range.rb} +34 -61
  54. data/lib/zakuro/version/senmyou/range/full_range.rb +194 -0
  55. data/lib/zakuro/version/senmyou/range/operated_range.rb +126 -0
  56. data/lib/zakuro/version/senmyou/range/operated_solar_terms.rb +181 -0
  57. data/lib/zakuro/version/senmyou/range/western_date_allocation.rb +68 -0
  58. data/lib/zakuro/version/senmyou/range/year_boundary.rb +138 -0
  59. data/lib/zakuro/version/senmyou/senmyou.rb +2 -2
  60. data/lib/zakuro/version/senmyou/specifier/single_day_specifier.rb +102 -0
  61. data/lib/zakuro/version/senmyou/stella/lunar_orbit.rb +2 -2
  62. data/lib/zakuro/version/senmyou/stella/solar_average.rb +105 -128
  63. data/lib/zakuro/version/senmyou/stella/solar_location.rb +213 -0
  64. data/lib/zakuro/version/senmyou/stella/solar_orbit.rb +4 -189
  65. data/lib/zakuro/version/senmyou/summary/single.rb +125 -0
  66. data/lib/zakuro/version_factory.rb +1 -1
  67. metadata +46 -15
  68. data/lib/zakuro/era/gengou/set-001-until-south.yaml +0 -375
  69. data/lib/zakuro/era/gengou/set-002-from-north.yaml +0 -166
  70. data/lib/zakuro/era/gengou/set-003-modern.yaml +0 -12
  71. data/lib/zakuro/era/japan.rb +0 -630
  72. data/lib/zakuro/output/result.rb +0 -219
  73. data/lib/zakuro/version/senmyou/base/gengou.rb +0 -210
  74. data/lib/zakuro/version/senmyou/summary/gengou_data.rb +0 -294
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ # TODO: moduleでMonthly とする(全暦むけに共通化したあと)
4
+
5
+ # :nodoc:
6
+ module Zakuro
7
+ # :nodoc:
8
+ module Senmyou
9
+ #
10
+ # MonthLabel 月表示情報
11
+ #
12
+ class MonthLabel
13
+ # @return [True] 大の月(30日)
14
+ # @return [False] 小の月(29日)
15
+ attr_reader :is_many_days
16
+ # @return [Integer] 月(xx月のxx)
17
+ attr_reader :number
18
+ # @return [True] 閏月
19
+ # @return [False] 平月
20
+ attr_reader :leaped
21
+
22
+ # :reek:ControlParameter and :reek:BooleanParameter
23
+
24
+ #
25
+ # 初期化
26
+ #
27
+ # @param [Integer] number 月(xx月のxx)
28
+ # @param [True, False] is_many_days 月の大小
29
+ # @param [True, False] leaped 閏月/平月
30
+ #
31
+ def initialize(number: -1, is_many_days: false, leaped: false)
32
+ # 月の大小
33
+ @is_many_days = is_many_days
34
+ # 月
35
+ @number = number
36
+ # 閏
37
+ @leaped = leaped
38
+ end
39
+
40
+ #
41
+ # 月の日数を返す
42
+ #
43
+ # @return [Integer] 日数
44
+ #
45
+ def days
46
+ @is_many_days ? 30 : 29
47
+ end
48
+
49
+ #
50
+ # 月の名前(大小)を返す
51
+ #
52
+ # @return [String] 月の名前(大小)
53
+ #
54
+ def days_name
55
+ @is_many_days ? '大' : '小'
56
+ end
57
+
58
+ #
59
+ # 一ヶ月戻す
60
+ #
61
+ # @return [True] 昨年
62
+ # @return [False] 今年
63
+ #
64
+ def back_to_last_month
65
+ @number -= 1
66
+
67
+ return false if @number.positive?
68
+
69
+ @number = 12
70
+
71
+ true
72
+ end
73
+
74
+ #
75
+ # 同一の月情報かを検証する
76
+ #
77
+ # @param [Month] other 他の月情報
78
+ #
79
+ # @return [True] 同一の月
80
+ # @return [False] 異なる月
81
+ #
82
+ def same?(other:)
83
+ @number == other.number && @leaped == other.leaped
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,196 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './month'
4
+ require_relative '../../../operation/operation'
5
+
6
+ # :nodoc:
7
+ module Zakuro
8
+ # :nodoc:
9
+ module Senmyou
10
+ # :reek:TooManyInstanceVariables { max_instance_variables: 5 }
11
+
12
+ #
13
+ # OperatedMonth 月情報(運用)
14
+ #
15
+ class OperatedMonth < Month
16
+ # @return [Operation::MonthHistory] 変更履歴(月)
17
+ attr_reader :history
18
+ # @return [OperatedSolarTerms] 運用時二十四節気
19
+ attr_reader :operated_solar_terms
20
+
21
+ #
22
+ # 初期化
23
+ #
24
+ # @param [OperatedSolarTerms] operated_solar_terms 運用時二十四節気
25
+ # @param [MonthLabel] month_label 月表示名
26
+ # @param [FirstDay] first_day 月初日(朔日)
27
+ # @param [Array<SolarTerm>] solar_terms 二十四節気
28
+ # @param [Operation::MonthHistory] history 変更履歴(月)
29
+ #
30
+ def initialize(operated_solar_terms:, month_label: MonthLabel.new, first_day: FirstDay.new,
31
+ solar_terms: [], history: Operation::MonthHistory.new)
32
+ super(month_label: month_label, first_day: first_day, solar_terms: solar_terms)
33
+ @history = history
34
+ @operated_solar_terms = operated_solar_terms
35
+ end
36
+
37
+ #
38
+ # 書き換える
39
+ #
40
+ def rewrite
41
+ rewrite_month
42
+ rewrite_solar_terms
43
+ rewrite_first_day
44
+ end
45
+
46
+ #
47
+ # 月ごとの差分で書き換える
48
+ #
49
+ def rewrite_month
50
+ diff = history.diffs.month
51
+
52
+ @month_label = MonthLabel.new(
53
+ number: OperatedMonth.rewrite_month_fields(
54
+ month_diff: diff, month_label: month_label, name: 'number'
55
+ ),
56
+ is_many_days: OperatedMonth.rewrite_month_fields(
57
+ month_diff: diff, month_label: month_label, name: 'is_many_days'
58
+ ),
59
+ leaped: OperatedMonth.rewrite_month_fields(
60
+ month_diff: diff, month_label: month_label, name: 'leaped'
61
+ )
62
+ )
63
+ end
64
+
65
+ def self.rewrite_month_fields(month_diff:, month_label:, name:)
66
+ method_name = name.intern
67
+
68
+ diff = month_diff.send(method_name)
69
+ default = month_label.send(method_name)
70
+ return default if diff.invalid?
71
+
72
+ diff.actual
73
+ end
74
+
75
+ #
76
+ # 二十四節気ごとの差分で書き換える
77
+ #
78
+ def rewrite_solar_terms
79
+ matched, operated_solar_term = @operated_solar_terms.get(
80
+ western_date: first_day.western_date
81
+ )
82
+
83
+ return unless matched
84
+
85
+ @solar_terms = OperatedMonth.create_operated_solar_terms(
86
+ operated_solar_term: operated_solar_term,
87
+ solar_terms: solar_terms
88
+ )
89
+ end
90
+
91
+ #
92
+ # <Description>
93
+ #
94
+ # @param [<Type>] operated_solar_term <description>
95
+ # @param [Array<SolarTerm>] solar_terms 二十四節気
96
+ #
97
+ # @return [Array<SolarTerm>] 二十四節気
98
+ #
99
+ def self.create_operated_solar_terms(operated_solar_term:, solar_terms:)
100
+ index = operated_solar_term.index
101
+
102
+ # 別の月に移動する二十四節気。割り当てない。
103
+ result = remove_solar_term(index: index, solar_terms: solar_terms)
104
+
105
+ return result if used_solar_term?(index: index, solar_terms: solar_terms)
106
+
107
+ result.push(operated_solar_term)
108
+
109
+ result
110
+ end
111
+
112
+ # :reek:ControlParameter
113
+
114
+ #
115
+ # 二十四節気が使用されているか
116
+ #
117
+ # @param [Integer] index 二十四節気番号
118
+ # @param [Array<SolarTerm>] solar_terms 二十四節気
119
+ #
120
+ # @return [True] 使用
121
+ # @return [False] 未使用
122
+ #
123
+ def self.used_solar_term?(index:, solar_terms:)
124
+ solar_terms.each do |solar_term|
125
+ return true if index == solar_term.index
126
+ end
127
+
128
+ false
129
+ end
130
+
131
+ # :reek:ControlParameter
132
+
133
+ #
134
+ # 対象の二十四節気を除外する
135
+ #
136
+ # @param [Integer] index 二十四節気番号
137
+ # @param [Array<SolarTerm>] solar_terms 二十四節気
138
+ #
139
+ # @return [Array<SolarTerm>] 二十四節気(対象除外済)
140
+ #
141
+ def self.remove_solar_term(index:, solar_terms:)
142
+ result = []
143
+ solar_terms.each do |solar_term|
144
+ next if index == solar_term.index
145
+
146
+ result.push(solar_term)
147
+ end
148
+
149
+ result
150
+ end
151
+
152
+ #
153
+ # 月初日ごとの差分で書き換える
154
+ #
155
+ def rewrite_first_day
156
+ diffs = @history.diffs
157
+ return if diffs.invalid_days?
158
+
159
+ days = diffs.days
160
+
161
+ @first_day = FirstDay.new(
162
+ western_date: rewrite_western_date(days: days),
163
+ remainder: rewrite_remainder(days: days)
164
+ )
165
+ end
166
+
167
+ #
168
+ # 月初日の大余小余を日差分で書き換える
169
+ #
170
+ # @param [Integer] days 日差分
171
+ #
172
+ # @return [Remainder] 月初日の大余小余
173
+ #
174
+ def rewrite_remainder(days:)
175
+ remainder = first_day.remainder.clone
176
+ remainder.add!(Remainder.new(day: days, minute: 0, second: 0))
177
+
178
+ remainder
179
+ end
180
+
181
+ #
182
+ # 月初日の西暦日を日差分で書き換える
183
+ #
184
+ # @param [Integer] days 日差分
185
+ #
186
+ # @return [Western::Calendar] 月初日の西暦日
187
+ #
188
+ def rewrite_western_date(days:)
189
+ western_date = first_day.western_date.clone
190
+ western_date += days
191
+
192
+ western_date
193
+ end
194
+ end
195
+ end
196
+ end
@@ -2,21 +2,24 @@
2
2
 
3
3
  require_relative '../../../output/logger'
4
4
  require_relative '../base/remainder'
5
- require_relative '../monthly/month'
5
+ require_relative '../monthly/initialized_month'
6
6
  require_relative '../base/solar_term'
7
7
  require_relative '../monthly/lunar_phase'
8
8
  require_relative '../stella/solar_orbit'
9
9
  require_relative '../stella/solar_average'
10
+ require_relative '../stella/solar_location'
10
11
  require_relative '../stella/lunar_orbit'
11
12
 
12
13
  # :nodoc:
13
14
  module Zakuro
14
15
  # :nodoc:
15
16
  module Senmyou
16
- # AnnualData 年間データ
17
- module AnnualData
17
+ #
18
+ # AnnualRange 年間範囲
19
+ #
20
+ module AnnualRange
18
21
  # @return [Logger] ロガー
19
- LOGGER = Logger.new(location: 'annual_data')
22
+ LOGGER = Logger.new(location: 'annual_range')
20
23
 
21
24
  # :reek:TooManyStatements { max_statements: 6 }
22
25
 
@@ -61,20 +64,18 @@ module Zakuro
61
64
  #
62
65
  # @return [Array<Month>] 1年データ
63
66
  #
64
- def self.collect_annual_data_after_last_november_1st(western_year:)
65
- annual_data = initialized_annual_data(western_year: western_year)
67
+ def self.collect_annual_range_after_last_november_1st(western_year:)
68
+ annual_range = initialized_annual_range(western_year: western_year)
66
69
 
67
- apply_big_and_small_of_the_month(annual_data: annual_data)
70
+ apply_big_and_small_of_the_month(annual_range: annual_range)
68
71
 
69
- SolarAverage.set_solar_terms_into_annual_data(western_year: western_year,
70
- annual_data: annual_data)
72
+ solar_average = SolarAverage.new(western_year: western_year)
73
+ solar_average.set(annual_range: annual_range)
71
74
 
72
75
  # 月間隔を取得するためだけの末尾要素を削除
73
- annual_data.pop
76
+ annual_range.pop
74
77
 
75
- adjust_leap_month(annual_data: annual_data)
76
-
77
- annual_data
78
+ initialize_month_label(annual_range: annual_range)
78
79
  end
79
80
 
80
81
  #
@@ -91,7 +92,7 @@ module Zakuro
91
92
  remainder: winter_solstice_age
92
93
  )
93
94
  solar_term = \
94
- SolarOrbit.calc_solar_term_by_remainder(
95
+ SolarLocation.get(
95
96
  solar_term: solar_term
96
97
  )
97
98
 
@@ -112,75 +113,47 @@ module Zakuro
112
113
  #
113
114
  # @return [Array<Month>] 1年データ
114
115
  #
115
- def self.initialized_annual_data(western_year:)
116
+ def self.initialized_annual_range(western_year:)
116
117
  result = []
117
118
  lunar_phase = LunarPhase.new(western_year: western_year)
118
119
 
119
- is_last_year = true
120
-
121
- monthes = [11, 12] + [*1..12]
122
-
123
- monthes.each do |month|
124
- LOGGER.debug('---', "month: #{month}", "is_last_year: #{is_last_year}")
125
-
120
+ # 14ヶ月分を生成する(閏年で最大13ヶ月 + 末月の大小/二十四節気を求めるために必要な月)
121
+ (0..13).each do |_index|
126
122
  adjusted = lunar_phase.next_month
127
123
 
128
124
  result.push(
129
- Month.new(is_last_year: is_last_year, number: month,
130
- remainder: adjusted, phase_index: 0)
125
+ InitializedMonth.new(month_label: MonthLabel.new,
126
+ first_day: FirstDay.new(remainder: adjusted),
127
+ phase_index: 0)
131
128
  )
132
- is_last_year = false if month == 12
133
129
  end
130
+
134
131
  result
135
132
  end
136
- private_class_method :initialized_annual_data
133
+ private_class_method :initialized_annual_range
137
134
 
138
135
  #
139
136
  # 1年データの各月に月の大小を設定する
140
137
  #
141
- # @param [Array<Month>] annual_data 1年データ
142
- #
143
- def self.apply_big_and_small_of_the_month(annual_data:)
144
- size = annual_data.size - 1
145
- (0...size).each do |idx|
146
- current_month = annual_data[idx]
147
- next_month = annual_data[idx + 1]
148
- current_month.is_many_days = \
149
- current_month.remainder.same_remainder_divided_by_ten?(
150
- other: next_month.remainder.day
151
- )
138
+ # @param [Array<Month>] annual_range 1年データ
139
+ #
140
+ def self.apply_big_and_small_of_the_month(annual_range:)
141
+ # NOTE: 最後の月は処理できない(=計算外の余分な月が最後に必要である)
142
+ annual_range.each_cons(2) do |(current_month, next_month)|
143
+ current_month.eval_many_days(next_month_day: next_month.remainder.day)
152
144
  end
153
145
  end
154
146
  private_class_method :apply_big_and_small_of_the_month
155
147
 
156
- # :reek:TooManyStatements { max_statements: 10 }
157
-
158
148
  #
159
- # 閏月が存在した場合に以降の月を1つずつ減らす
160
- # @example 7,8,9 と続く月の8月が閏の場合、7, 閏7, 8 となる
149
+ # 月表示情報を更新する
161
150
  #
162
- # @param [Array<Month>] annual_data 1年データ
151
+ # @param [Array<Month>] annual_range 1年データ
163
152
  #
164
- def self.adjust_leap_month(annual_data:)
165
- # 閏による月の再調整を行う
166
- leaped = false
167
- annual_data.each do |month|
168
- if month.even_term.invalid?
169
- month.leaped = true
170
- leaped = true
171
- end
172
- next unless leaped
173
-
174
- # NOTE: 常気法では閏月は2-3年に一度のため、1年に二度発生しない前提
175
- number = month.number - 1
176
- if number <= 0
177
- month.is_last_year = true
178
- number = 12
179
- end
180
- month.number = number
181
- end
153
+ def self.initialize_month_label(annual_range:)
154
+ annual_range.each(&:rename_month_label_by_solar_term)
182
155
  end
183
- private_class_method :adjust_leap_month
156
+ private_class_method :initialize_month_label
184
157
  end
185
158
  end
186
159
  end
@@ -0,0 +1,194 @@
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
+ require_relative './year_boundary'
8
+ require_relative './western_date_allocation'
9
+
10
+ require_relative '../base/year'
11
+
12
+ # :nodoc:
13
+ module Zakuro
14
+ # :nodoc:
15
+ module Senmyou
16
+ # :reek:TooManyInstanceVariables { max_instance_variables: 5 }
17
+
18
+ #
19
+ # FullRange 完全範囲
20
+ # ある日からある日の範囲を計算可能な年月範囲
21
+ # * 前提として元号年はその元号の開始年から数える
22
+ # * ある日の元号年を求める場合、その元号が含まれる最初の年まで遡る
23
+ # * 元号は一つとは限らない。南北朝などで二つある場合は、古い方の元号から求める
24
+ #
25
+ # NOTE: 割り当てた元号は年初を基準にした元号年である
26
+ # * 元旦を基準にした時の正しい元号を設定している
27
+ # * 引き当てたい日付が元旦ではない場合、その月日に従い元号を再度求める
28
+ # * この再計算が必要になるのは、元号が切り替わる年のみである
29
+ #
30
+ class FullRange
31
+ # @return [Western::Calendar] 開始日
32
+ attr_reader :start_date
33
+ # @return [Western::Calendar] 終了日
34
+ attr_reader :end_date
35
+ # @return [MultiGengouRoller] 改元処理
36
+ attr_reader :multi_gengou_roller
37
+ # @return [Western::Calendar] 最過去の元旦
38
+ attr_reader :new_year_date
39
+ # @return [Integer] 西暦年
40
+ attr_reader :western_year
41
+
42
+ # @return [Logger] ロガー
43
+ LOGGER = Logger.new(location: 'full_range')
44
+
45
+ #
46
+ # 初期化
47
+ #
48
+ # @param [Western::Calendar] start_date 開始日
49
+ # @param [Western::Calendar] end_date 終了日
50
+ #
51
+ def initialize(start_date: Western::Calendar.new, end_date: Western::Calendar.new)
52
+ @start_date = start_date
53
+ @end_date = end_date
54
+ return if invalid?
55
+
56
+ @multi_gengou_roller = MultiGengouRoller.new(start_date: start_date, end_date: end_date)
57
+ @new_year_date = @multi_gengou_roller.oldest_date.clone
58
+ @western_year = @new_year_date.year
59
+ end
60
+
61
+ #
62
+ # 無効か
63
+ #
64
+ # @return [True] 無効
65
+ # @return [False] 有効
66
+ #
67
+ def invalid?
68
+ @start_date.invalid?
69
+ end
70
+
71
+ #
72
+ # 完全範囲を取得する
73
+ #
74
+ # @return [Array<Year>] 完全範囲
75
+ #
76
+ def get
77
+ return [] if invalid?
78
+
79
+ years = YearBoundary.get(annual_ranges: annual_ranges)
80
+ years = update_gengou(years: years)
81
+
82
+ WesternDateAllocation.update_first_day(years: years)
83
+
84
+ years
85
+ end
86
+
87
+ # :reek:TooManyStatements { max_statements: 6 }
88
+
89
+ #
90
+ # 完全範囲内の年データを取得する
91
+ #
92
+ # @return [Array<Year>] 年データ(冬至基準)
93
+ #
94
+ def annual_ranges
95
+ oldest_date = @new_year_date
96
+ newest_date = @multi_gengou_roller.newest_date
97
+
98
+ years = []
99
+ ((oldest_date.year)..(newest_date.year + 2)).each do |year|
100
+ years.push(
101
+ AnnualRange.collect_annual_range_after_last_november_1st(
102
+ western_year: year
103
+ )
104
+ )
105
+ end
106
+
107
+ years
108
+ end
109
+
110
+ # :reek:TooManyStatements { max_statements: 8 }
111
+
112
+ #
113
+ # 完全範囲内の年データの元号を開始年基準で更新する
114
+ #
115
+ # @param [Array<Year>] years 年データ(元旦基準)
116
+ #
117
+ # @return [Array<Year>] 元号更新済み年データ(元旦基準)
118
+ #
119
+ def update_gengou(years:)
120
+ updated_years = []
121
+
122
+ nearest_end_date = choise_nearest_end_date
123
+
124
+ years.each do |year|
125
+ next_year(years: updated_years, year: year)
126
+
127
+ if @new_year_date > nearest_end_date
128
+ @multi_gengou_roller.transfer
129
+ nearest_end_date = choise_nearest_end_date
130
+ end
131
+ @multi_gengou_roller.next_year
132
+ end
133
+
134
+ updated_years
135
+ end
136
+
137
+ private
138
+
139
+ #
140
+ # 元号処理対象の年を進める
141
+ #
142
+ # @param [Array<Year>] years 元号処理済み年データ(元旦基準)
143
+ # @param [Year] year 元号処理前の年(元旦基準)
144
+ #
145
+ def next_year(years:, year:)
146
+ updated_year = update_year(year: year)
147
+
148
+ years.push(updated_year)
149
+
150
+ next_new_year_date(total_days: updated_year.total_days)
151
+
152
+ nil
153
+ end
154
+
155
+ #
156
+ # 年の元号を更新する
157
+ #
158
+ # @param [Year] year 元号処理前の年(元旦基準)
159
+ #
160
+ # @return [Year] 元号処理済の年(元旦基準)
161
+ #
162
+ def update_year(year:)
163
+ multi_gengou = @multi_gengou_roller.multi_gengou.clone
164
+
165
+ updated_year = Year.new(multi_gengou: multi_gengou, new_year_date: @new_year_date.clone,
166
+ months: year.months)
167
+ updated_year.commit
168
+
169
+ updated_year
170
+ end
171
+
172
+ #
173
+ # 次の年に進める
174
+ #
175
+ # @param [Integer] total_days 年の日数
176
+ #
177
+ def next_new_year_date(total_days:)
178
+ @new_year_date += total_days
179
+ @multi_gengou_roller.next(days: total_days)
180
+
181
+ nil
182
+ end
183
+
184
+ #
185
+ # 現在日からみて直近の未来に対する元号の切替前日を求める
186
+ #
187
+ # @return [Western::Calendar] 元号の切替前日
188
+ #
189
+ def choise_nearest_end_date
190
+ @multi_gengou_roller.choise_nearest_end_date
191
+ end
192
+ end
193
+ end
194
+ end