zakuro 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/lib/zakuro/calculation/base/multi_gengou.rb +101 -0
  3. data/lib/zakuro/calculation/base/multi_gengou_roller.rb +218 -0
  4. data/lib/zakuro/calculation/base/year.rb +107 -0
  5. data/lib/zakuro/calculation/cycle/abstract_remainder.rb +459 -0
  6. data/lib/zakuro/calculation/cycle/abstract_solar_term.rb +151 -0
  7. data/lib/zakuro/calculation/cycle/zodiac.rb +106 -0
  8. data/lib/zakuro/calculation/monthly/first_day.rb +45 -0
  9. data/lib/zakuro/calculation/monthly/initialized_month.rb +120 -0
  10. data/lib/zakuro/calculation/monthly/month.rb +184 -0
  11. data/lib/zakuro/calculation/monthly/month_label.rb +88 -0
  12. data/lib/zakuro/calculation/monthly/operated_month.rb +201 -0
  13. data/lib/zakuro/calculation/range/full_range.rb +210 -0
  14. data/lib/zakuro/calculation/range/operated_range.rb +134 -0
  15. data/lib/zakuro/calculation/range/operated_solar_terms.rb +201 -0
  16. data/lib/zakuro/calculation/range/transfer/western_date_allocation.rb +76 -0
  17. data/lib/zakuro/calculation/range/transfer/year_boundary.rb +142 -0
  18. data/lib/zakuro/calculation/specifier/single_day.rb +109 -0
  19. data/lib/zakuro/calculation/summary/single.rb +129 -0
  20. data/lib/zakuro/merchant.rb +2 -2
  21. data/lib/zakuro/output/error.rb +7 -6
  22. data/lib/zakuro/output/logger.rb +50 -49
  23. data/lib/zakuro/output/response.rb +145 -144
  24. data/lib/zakuro/tools/typeof.rb +2 -2
  25. data/lib/zakuro/version.rb +1 -1
  26. data/lib/zakuro/version/abstract_version.rb +1 -1
  27. data/lib/zakuro/version/context.rb +23 -0
  28. data/lib/zakuro/version/senmyou/cycle/remainder.rb +63 -0
  29. data/lib/zakuro/version/senmyou/cycle/solar_term.rb +31 -0
  30. data/lib/zakuro/version/senmyou/monthly/lunar_phase.rb +186 -182
  31. data/lib/zakuro/version/senmyou/range/annual_range.rb +134 -129
  32. data/lib/zakuro/version/senmyou/senmyou.rb +10 -4
  33. data/lib/zakuro/version/senmyou/stella/lunar_orbit.rb +5 -5
  34. data/lib/zakuro/version/senmyou/stella/solar_average.rb +4 -4
  35. data/lib/zakuro/version/senmyou/stella/solar_location.rb +27 -27
  36. data/lib/zakuro/version/senmyou/stella/solar_orbit.rb +2 -2
  37. data/lib/zakuro/version/senmyou/stella/winter_solstice.rb +4 -4
  38. data/lib/zakuro/version/version_class_resolver.rb +62 -0
  39. data/lib/zakuro/version_factory.rb +2 -2
  40. metadata +24 -22
  41. data/lib/zakuro/cycle/abstract_remainder.rb +0 -456
  42. data/lib/zakuro/cycle/zodiac.rb +0 -103
  43. data/lib/zakuro/version/senmyou/base/era.rb +0 -83
  44. data/lib/zakuro/version/senmyou/base/multi_gengou.rb +0 -98
  45. data/lib/zakuro/version/senmyou/base/multi_gengou_roller.rb +0 -217
  46. data/lib/zakuro/version/senmyou/base/remainder.rb +0 -60
  47. data/lib/zakuro/version/senmyou/base/solar_term.rb +0 -148
  48. data/lib/zakuro/version/senmyou/base/year.rb +0 -104
  49. data/lib/zakuro/version/senmyou/monthly/first_day.rb +0 -44
  50. data/lib/zakuro/version/senmyou/monthly/initialized_month.rb +0 -119
  51. data/lib/zakuro/version/senmyou/monthly/month.rb +0 -181
  52. data/lib/zakuro/version/senmyou/monthly/month_label.rb +0 -87
  53. data/lib/zakuro/version/senmyou/monthly/operated_month.rb +0 -196
  54. data/lib/zakuro/version/senmyou/range/full_range.rb +0 -194
  55. data/lib/zakuro/version/senmyou/range/operated_range.rb +0 -126
  56. data/lib/zakuro/version/senmyou/range/operated_solar_terms.rb +0 -181
  57. data/lib/zakuro/version/senmyou/range/western_date_allocation.rb +0 -68
  58. data/lib/zakuro/version/senmyou/range/year_boundary.rb +0 -138
  59. data/lib/zakuro/version/senmyou/specifier/single_day_specifier.rb +0 -102
  60. data/lib/zakuro/version/senmyou/summary/single.rb +0 -125
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fd8b402a7084ab57e0424c65d9851cc72f759b81f6f9b4c7f1e71afcda27d561
4
- data.tar.gz: f204f25a8a6addad96556cb9376b406d6c1285375e79c693169d3095b6f5b387
3
+ metadata.gz: 7e4972c48d6122814c2ce4f7b671948768cd2f7a8b977071c523cd982098ad35
4
+ data.tar.gz: d5e5efd67f13ae70c453ff8095fe65c19c2dba8ec5213c3c6cedc166e7dfb7d4
5
5
  SHA512:
6
- metadata.gz: a7c7c8b0fef50d3da9f45701883ec271f3c000676a4a70e1d0c73ae4b15249e6a2cd57be47bd01a9ad6109da9b6593745ccc348c83d32743a09442bf7a922343
7
- data.tar.gz: c5e6aa6ef4b4cc21814859753bf8bfd02be637173011bc6a2eb3dd28f4cfe1505d9faeb6544759f3f92543a8ee35820c73d54811a48d9d47ab645d38a995ed16
6
+ metadata.gz: d7b235556dd510eeaff8b42712211b399c75ac6ce5ef3ac25812f7742f9da90e08c90bba7f4d6ba030c56d26d650df17ce802ed47cc30267874ffd25b97bc7b7
7
+ data.tar.gz: 80ecbbe5e4b0d2428dc50f7fd8cdbf35e8667e0bbecc91d604541b4ee9dfdf72c2fb29ada37801c127719520f685520e973c3694ad149bc52f63d88b2fb83701
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../era/japan/gengou'
4
+ require_relative '../../era/western'
5
+
6
+ # :nodoc:
7
+ module Zakuro
8
+ # :nodoc:
9
+ module Calculation
10
+ # :nodoc:
11
+ module Base
12
+ #
13
+ # MultiGengou 複数元号
14
+ #
15
+ class MultiGengou
16
+ # @return [Japan::Gengou] 元号(1行目)
17
+ attr_reader :first_line
18
+ # @return [Japan::Gengou] 元号(2行目)
19
+ attr_reader :second_line
20
+ # @return [Western::Calendar] 元旦
21
+ attr_reader :new_year_date
22
+
23
+ def initialize(first_line: Japan::Gengou.new, second_line: Japan::Gengou.new,
24
+ new_year_date: Western::Calendar.new)
25
+ @first_line = first_line
26
+ @second_line = second_line
27
+ @new_year_date = new_year_date
28
+ end
29
+
30
+ # :reek:TooManyStatements { max_statements: 7 }
31
+
32
+ #
33
+ # 改元する
34
+ #
35
+ # @param [Japan::Gengou] first_line 元号(1行目)
36
+ # @param [Japan::Gengou] second_line 元号(2行目)
37
+ #
38
+ # @return [MultiGengou] 自身
39
+ #
40
+ def transfer(first_line: Japan::Gengou.new, second_line: Japan::Gengou.new)
41
+ cloned_first_line = first_line.clone
42
+ cloned_second_line = second_line.clone
43
+
44
+ if integrated?(first_line: cloned_first_line, second_line: cloned_second_line)
45
+ @first_line = @second_line.clone
46
+ @second_line = cloned_second_line
47
+ end
48
+
49
+ @first_line = cloned_first_line if @first_line.name != first_line.name
50
+ @second_line = cloned_second_line if @second_line.name != second_line.name
51
+
52
+ self
53
+ end
54
+
55
+ #
56
+ # 次年にする
57
+ #
58
+ # @param [Japan::Gengou] first_line 元号(1行目)
59
+ # @param [Japan::Gengou] second_line 元号(2行目)
60
+ #
61
+ # @return [MultiGengou] 自身
62
+ #
63
+ def next_year
64
+ @first_line.next_year
65
+ @second_line.next_year
66
+
67
+ self
68
+ end
69
+
70
+ #
71
+ # ディープコピー
72
+ #
73
+ # @param [MultiGengou] obj 自身
74
+ #
75
+ def initialize_copy(obj)
76
+ @first_line = obj.first_line.clone
77
+ @second_line = obj.second_line.clone
78
+ end
79
+
80
+ private
81
+
82
+ #
83
+ # 複数元号を統一するかどうか
84
+ #
85
+ # @param [Japan::Gengou] first_line 元号(1行目)
86
+ # @param [Japan::Gengou] second_line 元号(2行目)
87
+ #
88
+ # @return [True] 統一する
89
+ # @return [False] 統一しない
90
+ #
91
+ def integrated?(first_line: Japan::Gengou.new, second_line: Japan::Gengou.new)
92
+ return false if @second_line.name != first_line.name
93
+
94
+ return false unless second_line.invalid?
95
+
96
+ true
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,218 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './multi_gengou'
4
+
5
+ require_relative '../../era/japan/gengou'
6
+
7
+ # :nodoc:
8
+ module Zakuro
9
+ # :nodoc:
10
+ module Calculation
11
+ # :nodoc:
12
+ module Base
13
+ #
14
+ # MultiGengouRoller 改元処理
15
+ #
16
+ class MultiGengouRoller
17
+ # @return [MultiGengou] 複数元号
18
+ attr_reader :multi_gengou
19
+ # @return [Western::Calendar] 元旦(元号が2つある場合は再過去の日付になる)
20
+ attr_reader :oldest_date
21
+ # @return [Western::Calendar] 元号内での最未来日(元号が2つある場合は再未来の日付になる)
22
+ attr_reader :newest_date
23
+ # @return [Western::Calendar] 現在日
24
+ attr_reader :current_date
25
+
26
+ def initialize(start_date: Western::Calendar.new, end_date: Western::Calendar.new)
27
+ end_date = start_date if end_date.invalid?
28
+
29
+ @oldest_date = MultiGengouRoller.choise_oldest_gengou_date(
30
+ first_line: MultiGengouRoller.first_line(date: start_date),
31
+ second_line: MultiGengouRoller.second_line(date: start_date)
32
+ )
33
+ @current_date = @oldest_date.clone
34
+ @newest_date = MultiGengouRoller.choise_newest_gengou_date(
35
+ first_line: MultiGengouRoller.first_line(date: end_date),
36
+ second_line: MultiGengouRoller.second_line(date: end_date)
37
+ )
38
+
39
+ @multi_gengou = MultiGengou.new(
40
+ first_line: current_first_line,
41
+ second_line: current_second_line,
42
+ new_year_date: @oldest_date
43
+ )
44
+ end
45
+
46
+ #
47
+ # 現在日付を未来に進める
48
+ #
49
+ # @param [<Type>] days <description>
50
+ #
51
+ # @return [<Type>] <description>
52
+ #
53
+ def next(days: 0)
54
+ @current_date += days
55
+ end
56
+
57
+ #
58
+ # 現在日から元号(1行目)を取得する
59
+ #
60
+ # @return [Japan::Gengou] 元号(1行目)
61
+ #
62
+ def current_first_line
63
+ MultiGengouRoller.first_line(date: @current_date)
64
+ end
65
+
66
+ #
67
+ # 現在日から元号(2行目)を取得する
68
+ #
69
+ # @return [Japan::Gengou] 元号(2行目)
70
+ #
71
+ def current_second_line
72
+ MultiGengouRoller.second_line(date: @current_date)
73
+ end
74
+
75
+ #
76
+ # 改元する
77
+ #
78
+ # @return [MultiGengou] 複数元号
79
+ #
80
+ def transfer
81
+ MultiGengouRoller.transfer(multi_gengou: @multi_gengou, date: @current_date)
82
+ end
83
+
84
+ #
85
+ # 次年にする
86
+ #
87
+ # @return [MultiGengou] 複数元号
88
+ #
89
+ def next_year
90
+ @multi_gengou.next_year
91
+ end
92
+
93
+ #
94
+ # 元号(1行目)を取得する
95
+ #
96
+ # @return [Japan::Gengou] 元号(1行目)
97
+ #
98
+ def self.first_line(date: Western::Calender.new)
99
+ Japan::GengouResource.first_line(date: date)
100
+ end
101
+
102
+ #
103
+ # 元号(2行目)を取得する
104
+ #
105
+ # @return [Japan::Gengou] 元号(2行目)
106
+ #
107
+ def self.second_line(date: Western::Calender.new)
108
+ Japan::GengouResource.second_line(date: date)
109
+ end
110
+
111
+ #
112
+ # 改元する
113
+ #
114
+ # @param [MultiGengou] multi_gengou 複数元号
115
+ # @param [Western::Calendar] date 対象日
116
+ #
117
+ # @return [MultiGengou] 改元済み複数元号
118
+ #
119
+ def self.transfer(multi_gengou:, date:)
120
+ multi_gengou.transfer(
121
+ first_line: first_line(date: date),
122
+ second_line: second_line(date: date)
123
+ )
124
+
125
+ multi_gengou
126
+ end
127
+
128
+ #
129
+ # 現在日からみて直近の未来に対する元号の切替前日を求める
130
+ # @note 2つの元号が重複した場合はより過去の日となる
131
+ #
132
+ # @param [Japan::Gengou] first_line 元号(1行目)
133
+ # @param [Japan::Gengou] second_line 元号(2行目)
134
+ #
135
+ # @return [Western::Calendar] 元号の切替前日
136
+ #
137
+ def choise_nearest_end_date
138
+ condition = lambda do |first_date, second_date|
139
+ first_date < second_date ? first_date : second_date
140
+ end
141
+
142
+ second_line = current_second_line
143
+
144
+ MultiGengouRoller.choise_date(condition: condition, second_line: second_line,
145
+ first_date: current_first_line.end_date.clone,
146
+ second_date: second_line.end_date.clone)
147
+ end
148
+
149
+ #
150
+ # 最過去の元旦を求める
151
+ # @note 2つの元号が重複した場合はより過去の日となる
152
+ #
153
+ # @param [Japan::Gengou] first_line 元号(1行目)
154
+ # @param [Japan::Gengou] second_line 元号(2行目)
155
+ #
156
+ # @return [Western::Calendar] 最過去の元旦
157
+ #
158
+ def self.choise_oldest_gengou_date(first_line:, second_line:)
159
+ condition = lambda do |first_date, second_date|
160
+ first_date < second_date ? first_date : second_date
161
+ end
162
+ choise_date(condition: condition, second_line: second_line,
163
+ first_date: first_line.new_year_date.clone,
164
+ second_date: second_line.new_year_date.clone)
165
+ end
166
+
167
+ #
168
+ # 元号内での最未来日を求める
169
+ # @note 2つの元号が重複した場合はより未来の日となる
170
+ #
171
+ # @param [Japan::Gengou] first_line 元号(1行目)
172
+ # @param [Japan::Gengou] second_line 元号(2行目)
173
+ #
174
+ # @return [Western::Calendar] 最未来日
175
+ #
176
+ def self.choise_newest_gengou_date(first_line:, second_line:)
177
+ condition = lambda do |first_date, second_date|
178
+ first_date > second_date ? first_date : second_date
179
+ end
180
+ choise_date(condition: condition, second_line: second_line,
181
+ first_date: first_line.end_date.clone,
182
+ second_date: second_line.end_date.clone)
183
+ end
184
+
185
+ # :reek:LongParameterList {max_params: 4}
186
+
187
+ #
188
+ # 条件を元に日付を求める
189
+ #
190
+ # @param [Proc] condition 比較条件
191
+ # @param [Japan::Gengou] second_line 元号(2行目)
192
+ # @param [Western::Calendar] first_date 比較対象(1行目)
193
+ # @param [Western::Calendar] second_date 比較対象(2行目)
194
+ #
195
+ # @return [Western::Calendar] 比較結果
196
+ #
197
+ def self.choise_date(condition:, second_line:, first_date:, second_date:)
198
+ # first_lineは常に存在する
199
+ return first_date if second_line.invalid?
200
+
201
+ condition.call(first_date, second_date)
202
+ end
203
+
204
+ #
205
+ # ディープコピー
206
+ #
207
+ # @param [MultiGengou] obj 自身
208
+ #
209
+ def initialize_copy(obj)
210
+ @oldest_date = obj.oldest_date.clone
211
+ @current_date = obj.current_date.clone
212
+ @newest_date = obj.newest_date.clone
213
+ @multi_gengou = obj.multi_gengou.clone
214
+ end
215
+ end
216
+ end
217
+ end
218
+ end
@@ -0,0 +1,107 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../cycle/zodiac'
4
+
5
+ # :nodoc:
6
+ module Zakuro
7
+ # :nodoc:
8
+ module Calculation
9
+ # :nodoc:
10
+ module Base
11
+ #
12
+ # Year 年
13
+ #
14
+ class Year
15
+ # @return [Gengou] 元号
16
+ attr_reader :multi_gengou
17
+ # @return [Array<Month>] 年内の全ての月
18
+ attr_reader :months
19
+ # @return [Integer] 年の日数
20
+ attr_reader :total_days
21
+ # @return [Western::Calendar] 元旦
22
+ attr_reader :new_year_date
23
+
24
+ #
25
+ # 初期化
26
+ #
27
+ # @param [Gengou] multi_gengou 元号
28
+ #
29
+ def initialize(multi_gengou: MultiGengou.new, new_year_date: Western::Calendar.new,
30
+ months: [], total_days: 0)
31
+ @multi_gengou = multi_gengou
32
+ @months = months
33
+ @new_year_date = new_year_date
34
+ @total_days = total_days
35
+ end
36
+
37
+ #
38
+ # 年の日数を確定する
39
+ #
40
+ def commit
41
+ @total_days = 0
42
+ months.each do |month|
43
+ @total_days += month.days
44
+ end
45
+
46
+ self
47
+ end
48
+
49
+ #
50
+ # 次年にする
51
+ #
52
+ # @param [Japan::Gengou] first_line 元号(1行目)
53
+ # @param [Japan::Gengou] second_line 元号(2行目)
54
+ #
55
+ # @return [MultiGengou] 自身
56
+ #
57
+ def next_year
58
+ @multi_gengou.next_year
59
+
60
+ @new_year_date += @total_days
61
+ @total_days = 0
62
+
63
+ self
64
+ end
65
+
66
+ #
67
+ # 十干十二支を取得する
68
+ #
69
+ # @return [String] 十干十二支
70
+ #
71
+ def zodiac_name
72
+ Cycle::Zodiac.year_name(western_year: @new_year_date.year)
73
+ end
74
+
75
+ #
76
+ # 月を追加する
77
+ #
78
+ # @param [Month] month 月
79
+ #
80
+ def push(month:)
81
+ return if duplicated?(month: month)
82
+
83
+ @months.push(month)
84
+
85
+ nil
86
+ end
87
+
88
+ #
89
+ # すでに登録済みの月と重複しているか判定する
90
+ #
91
+ # @note 昨年11月1日から今年1月1日の前日までで、去年データと重複する場合は登録スキップする
92
+ #
93
+ # @param [Month] month 月
94
+ #
95
+ # @return [True] 重複している
96
+ # @return [True] 重複していない
97
+ #
98
+ def duplicated?(month:)
99
+ @months.each do |existed|
100
+ return true if existed.same?(other: month)
101
+ end
102
+ false
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,459 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :nodoc:
4
+ module Zakuro
5
+ # :nodoc:
6
+ module Calculation
7
+ # :nodoc:
8
+ module Cycle
9
+ #
10
+ # 大余小余(時刻情報)
11
+ # @abstract 大余小余計算に必要な処理を行う、暦に依存しない汎用的なクラス
12
+ #
13
+ class AbstractRemainder # rubocop:disable Metrics/ClassLength
14
+ # @return [Integer] 大余上限
15
+ LIMIT = 60
16
+
17
+ # @return [Integer] 大余("日"に相当)
18
+ attr_reader :day
19
+ # @return [Integer] 小余("分"に相当)
20
+ attr_reader :minute
21
+ # @return [Integer] 秒
22
+ attr_reader :second
23
+ # @return [Integer] 繰り上げなしの小余
24
+ attr_reader :base_limit
25
+ # @return [Integer] 1大余に必要な小余(暦によって基数が異なる)
26
+ attr_reader :base_day
27
+ # @return [Integer] 1小余に必要な秒(暦によって基数が異なる)
28
+ attr_reader :base_minute
29
+ # 繰り上げ有無
30
+ # @return [True] 繰り上げあり
31
+ # @return [False] 繰り上げなし
32
+ attr_reader :limited
33
+
34
+ # :reek:instanceVariableAssumption
35
+ # rubocop:disable Metrics/ParameterLists
36
+
37
+ #
38
+ # 初期化
39
+ #
40
+ # @param [Integer] base_day 1大余に必要な小余(暦によって基数が異なる)
41
+ # @param [Integer] base_mitune 1小余に必要な秒(暦によって基数が異なる)
42
+ # @param [Integer] day 大余("日"に相当)
43
+ # @param [Integer] minute 小余("分"に相当)
44
+ # @param [Integer] second 秒
45
+ # @param [Integer] total 繰り上げなしの小余
46
+ #
47
+ def initialize(base_day: -1, base_mitune: -1, day: -1, minute: -1, second: -1, total: -1)
48
+ @base_limit = LIMIT
49
+ @base_day = base_day
50
+ @base_minute = base_mitune
51
+ @limited = true
52
+
53
+ set(day: day, minute: minute, second: second, total: total)
54
+ end
55
+ # rubocop:enable Metrics/ParameterLists
56
+
57
+ #
58
+ # 値を設定する
59
+ #
60
+ # @param [Integer] day 大余("日"に相当)
61
+ # @param [Integer] minute 小余("分"に相当)
62
+ # @param [Integer] second 秒
63
+ # @param [Integer] total 繰り上げなしの小余
64
+ #
65
+ # @return [AbstractRemainder] 自身の参照
66
+ #
67
+ def set(day: -1, minute: -1, second: -1, total: -1)
68
+ @day = day
69
+ @minute = minute
70
+ @second = second
71
+
72
+ if total != -1
73
+ @day = (total.to_f / @base_day).floor
74
+ @minute = (total % @base_day)
75
+ @second = 0
76
+ end
77
+
78
+ self
79
+ end
80
+
81
+ #
82
+ # 繰り上げ処理を外す
83
+ #
84
+ # @return [AbstractRemainder] 自身の参照
85
+ #
86
+ def lift_limit
87
+ @limited = false
88
+
89
+ self
90
+ end
91
+
92
+ #
93
+ # 繰り上げ処理を設定する
94
+ #
95
+ # @return [AbstractRemainder] 自身の参照
96
+ #
97
+ def set_limit
98
+ @limited = true
99
+
100
+ self
101
+ end
102
+
103
+ #
104
+ # 無効かどうか
105
+ #
106
+ # @param [AbstractRemainder] param 自クラスのインスタンス(デフォルトは自身の参照)
107
+ #
108
+ # @return [True] 無効
109
+ # @return [False] 有効
110
+ #
111
+ def invalid?(param: self)
112
+ raise ArgumentError, 'unmatch parameter type' unless param.is_a?(AbstractRemainder)
113
+
114
+ param.day == -1 || param.minute == -1 || param.second == -1
115
+ end
116
+
117
+ #
118
+ # 十干十二支名
119
+ #
120
+ # @return [String] 十干十二支名
121
+ #
122
+ def zodiac_name
123
+ Cycle::Zodiac.day_name(day: @day)
124
+ end
125
+
126
+ #
127
+ # 日が同じ十干かどうか(大小の月判定)
128
+ #
129
+ # @param [Integer] other 大余
130
+ #
131
+ # @return [True] 当月朔日と翌月朔日が同じ十干(「大」の月)
132
+ # @return [False] 当月朔日と翌月朔日が異なる十干(「小」の月)
133
+ #
134
+ def same_remainder_divided_by_ten?(other:)
135
+ day = @day % LIMIT
136
+
137
+ (day % 10) == (other % 10)
138
+ end
139
+
140
+ #
141
+ # (非破壊的に)加算する
142
+ #
143
+ # @param [AbstractRemainder] other 他の大余小余
144
+ #
145
+ # @return [AbstractRemainder] 加算結果
146
+ #
147
+ def add(other)
148
+ invalid?(param: other)
149
+ day = @day + other.day
150
+ minute = @minute + other.minute
151
+ second = @second + other.second
152
+ day, minute, second = carry(day, minute, second)
153
+
154
+ clone.set(day: day, minute: minute, second: second)
155
+ end
156
+
157
+ #
158
+ # (破壊的に)加算する
159
+ #
160
+ # @param [AbstractRemainder] other 他の大余小余
161
+ #
162
+ # @return [AbstractRemainder] 加算結果
163
+ #
164
+ def add!(other)
165
+ result = add(other)
166
+ @day = result.day
167
+ @minute = result.minute
168
+ @second = result.second
169
+
170
+ self
171
+ end
172
+
173
+ #
174
+ # (非破壊的に)除算する
175
+ #
176
+ # @param [AbstractRemainder] other 他の大余小余
177
+ #
178
+ # @return [AbstractRemainder] 除算結果
179
+ #
180
+ def sub(other)
181
+ invalid?(param: other)
182
+ day = @day - other.day
183
+ minute = @minute - other.minute
184
+ second = @second - other.second
185
+ day, minute, second = carry(day, minute, second)
186
+
187
+ clone.set(day: day, minute: minute, second: second)
188
+ end
189
+
190
+ #
191
+ # (破壊的に)除算する
192
+ #
193
+ # @param [AbstractRemainder] other 他の大余小余
194
+ #
195
+ # @return [AbstractRemainder] 除算結果
196
+ #
197
+ def sub!(other)
198
+ result = sub(other)
199
+ @day = result.day
200
+ @minute = result.minute
201
+ @second = result.second
202
+
203
+ self
204
+ end
205
+
206
+ #
207
+ # 大小比較(>)
208
+ #
209
+ # @param [AbstractRemainder] other 他の大余小余
210
+ #
211
+ # @return [True] より大きい
212
+ # @return [False] 以下
213
+ #
214
+ def >(other)
215
+ up?(other)
216
+ end
217
+
218
+ #
219
+ # 大小比較(>=)
220
+ #
221
+ # @param [AbstractRemainder] other 他の大余小余
222
+ #
223
+ # @return [True] 以上
224
+ # @return [False] より小さい
225
+ #
226
+ def >=(other)
227
+ up?(other) || \
228
+ (@day == other.day && @minute == other.minute && @second == other.second)
229
+ end
230
+
231
+ #
232
+ # 大小比較(<)
233
+ #
234
+ # @param [AbstractRemainder] other 他の大余小余
235
+ #
236
+ # @return [True] より小さい
237
+ # @return [False] 以上
238
+ #
239
+ def <(other)
240
+ down?(other)
241
+ end
242
+
243
+ #
244
+ # 大小比較(<=)
245
+ #
246
+ # @param [AbstractRemainder] other 他の大余小余
247
+ #
248
+ # @return [True] 以下
249
+ # @return [False] より大きい
250
+ #
251
+ def <=(other)
252
+ down?(other) || \
253
+ (@day == other.day && @minute == other.minute && @second == other.second)
254
+ end
255
+
256
+ #
257
+ # 大小比較(==)
258
+ #
259
+ # @param [AbstractRemainder] other 他の大余小余
260
+ #
261
+ # @return [True] 等しい
262
+ # @return [False] 等しくない
263
+ #
264
+ def ==(other)
265
+ eql?(other)
266
+ end
267
+
268
+ #
269
+ # 大小比較(!=)
270
+ #
271
+ # @param [AbstractRemainder] other 他の大余小余
272
+ #
273
+ # @return [True] 等しくない
274
+ # @return [False] 等しい
275
+ #
276
+ def !=(other)
277
+ !eql?(other)
278
+ end
279
+
280
+ # 進朔
281
+ # @see 進朔 http://eco.mtk.nao.ac.jp/koyomi/wiki/C2C0B1A2C2C0CDDBCEF12FBFCABAF3.html
282
+ # 進朔とは、朔の瞬間が1日の3/4すなわち夕方以降となる場合に、その日ではなく1日進めて翌日を1日目にする方法のことです。
283
+ # 進朔するかどうかの基準時刻を進朔限といいます。宣明暦では1日8400分ですから、進朔限は6300分で、それ以降だと進朔されます。
284
+
285
+ #
286
+ # (非破壊的に)進朔する
287
+ #
288
+ # @see http://eco.mtk.nao.ac.jp/koyomi/wiki/C2C0B1A2C2C0CDDBCEF12FBFCABAF3.html
289
+ #
290
+ # 進朔とは、朔の瞬間が1日の3/4すなわち夕方以降となる場合に、その日ではなく1日進めて翌日を1日目にする方法のことです。
291
+ # 進朔するかどうかの基準時刻を進朔限といいます。宣明暦では1日8400分ですから、進朔限は6300分で、それ以降だと進朔されます。
292
+ #
293
+ # @return [AbstractRemainder] 進朔結果
294
+ #
295
+ def up_on_new_moon
296
+ cloned = clone
297
+ limit = (base_day * 3) / 4
298
+ if @minute >= limit
299
+ day, minute, second = carry((@day + 1), @minute, @second)
300
+ return cloned.set(day: day, minute: minute, second: second)
301
+ end
302
+
303
+ cloned
304
+ end
305
+
306
+ #
307
+ # (破壊的に)進朔する
308
+ #
309
+ # @see http://eco.mtk.nao.ac.jp/koyomi/wiki/C2C0B1A2C2C0CDDBCEF12FBFCABAF3.html
310
+ #
311
+ # 進朔とは、朔の瞬間が1日の3/4すなわち夕方以降となる場合に、その日ではなく1日進めて翌日を1日目にする方法のことです。
312
+ # 進朔するかどうかの基準時刻を進朔限といいます。宣明暦では1日8400分ですから、進朔限は6300分で、それ以降だと進朔されます。
313
+ #
314
+ # @return [AbstractRemainder] 進朔結果
315
+ #
316
+ def up_on_new_moon!
317
+ result = up_on_new_moon
318
+ @day = result.day
319
+ @minute = result.minute
320
+ @second = result.second
321
+
322
+ self
323
+ end
324
+
325
+ #
326
+ # 小余に揃えた結果を返す(秒は除外する)
327
+ #
328
+ # @return [Integer] 小余
329
+ #
330
+ def to_minute
331
+ @day * @base_day + @minute
332
+ end
333
+
334
+ #
335
+ # 大余に四捨五入した結果を返す(秒は除外する)
336
+ #
337
+ # @return [AbstractRemainder] 大余
338
+ #
339
+ def round
340
+ day = @day
341
+ day += 1 if @minute >= (@base_day / 2)
342
+
343
+ initialize(day, 0, 0)
344
+ end
345
+
346
+ #
347
+ # 文字化する
348
+ #
349
+ # @return [String] 文字化
350
+ #
351
+ def to_s
352
+ "大余(日): #{@day}, 小余(分): #{@minute}, 小余(秒): #{@second}"
353
+ end
354
+
355
+ #
356
+ # 特定の文字フォーマットにして出力する
357
+ #
358
+ # @param [String] form フォーマット(大余、小余、秒それぞれを%dで指定する)
359
+ #
360
+ # @return [String] フォーマットした結果
361
+ #
362
+ def format(form: '%d-%d')
363
+ return '' if invalid?
364
+
365
+ super(form, @day, @minute, @second)
366
+ end
367
+
368
+ private
369
+
370
+ def carry!(day, minute, second)
371
+ @day, @minute, @second = carry(day, minute, second)
372
+
373
+ self
374
+ end
375
+
376
+ # 繰り上げ、繰り下げ
377
+ def carry(param_day, param_minute, param_second)
378
+ # NOTE: 計算方法としてマイナスでも徐算・剰余算の結果をプラス同様に扱う
379
+ minute, second = carry_second(param_minute, param_second)
380
+
381
+ day, minute = carry_minute(param_day, minute)
382
+
383
+ day = carry_day(day, @limited)
384
+
385
+ [day, minute, second]
386
+ end
387
+
388
+ def carry_second(param_minute, param_second)
389
+ sign = param_second.negative? ? -1 : 1
390
+ abs = sign * param_second
391
+ minute = param_minute + (sign * (abs / @base_minute).floor)
392
+ second = sign * (abs % @base_minute)
393
+
394
+ if sign.negative?
395
+ second += @base_minute
396
+ minute -= 1
397
+ end
398
+
399
+ [minute, second]
400
+ end
401
+
402
+ def carry_minute(param_day, param_minute)
403
+ sign = param_minute.negative? ? -1 : 1
404
+ abs = sign * param_minute
405
+
406
+ day = param_day + (sign * (abs / @base_day).floor)
407
+ minute = sign * (abs % @base_day)
408
+
409
+ if sign.negative?
410
+ minute += @base_day
411
+ day -= 1
412
+ end
413
+
414
+ [day, minute]
415
+ end
416
+
417
+ def carry_day(day, limited)
418
+ sign = day.negative? ? -1 : 1
419
+ abs = sign * day
420
+ carried = sign * (abs % @base_limit) if limited
421
+ carried += @base_limit if sign.negative?
422
+ carried
423
+ end
424
+
425
+ def up?(other)
426
+ invalid?(param: other)
427
+ day = other.day
428
+ minute = other.minute
429
+ return true if @day > day
430
+ return false if @day < day
431
+
432
+ return true if @minute > minute
433
+ return false if @minute < minute
434
+
435
+ @second > other.second
436
+ end
437
+
438
+ def eql?(other)
439
+ invalid?(param: other)
440
+
441
+ (@day == other.day && @minute == other.minute && @second == other.second)
442
+ end
443
+
444
+ def down?(other)
445
+ invalid?(param: other)
446
+ day = other.day
447
+ minute = other.minute
448
+ return true if @day < day
449
+ return false if @day > day
450
+
451
+ return true if @minute < minute
452
+ return false if @minute > minute
453
+
454
+ @second < other.second
455
+ end
456
+ end
457
+ end
458
+ end
459
+ end