zakuro 0.0.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.
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