zakuro 0.1.0 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +30 -12
  3. data/doc/operation/csv/month.csv +202 -202
  4. data/doc/operation/operation.xlsx +0 -0
  5. data/doc/operation/transfer.rb +6 -2
  6. data/lib/zakuro/calculation/base/multi_gengou.rb +101 -0
  7. data/lib/zakuro/calculation/base/multi_gengou_roller.rb +218 -0
  8. data/lib/zakuro/calculation/base/year.rb +107 -0
  9. data/lib/zakuro/calculation/cycle/abstract_remainder.rb +471 -0
  10. data/lib/zakuro/calculation/cycle/abstract_solar_term.rb +173 -0
  11. data/lib/zakuro/calculation/cycle/zodiac.rb +106 -0
  12. data/lib/zakuro/calculation/monthly/first_day.rb +45 -0
  13. data/lib/zakuro/calculation/monthly/initialized_month.rb +125 -0
  14. data/lib/zakuro/calculation/monthly/month.rb +187 -0
  15. data/lib/zakuro/calculation/monthly/month_label.rb +88 -0
  16. data/lib/zakuro/calculation/monthly/operated_month.rb +209 -0
  17. data/lib/zakuro/calculation/range/full_range.rb +210 -0
  18. data/lib/zakuro/calculation/range/operated_range.rb +144 -0
  19. data/lib/zakuro/calculation/range/operated_solar_terms.rb +201 -0
  20. data/lib/zakuro/calculation/range/transfer/western_date_allocation.rb +82 -0
  21. data/lib/zakuro/calculation/range/transfer/year_boundary.rb +146 -0
  22. data/lib/zakuro/calculation/specifier/single_day.rb +109 -0
  23. data/lib/zakuro/calculation/summary/single.rb +129 -0
  24. data/lib/zakuro/condition.rb +16 -13
  25. data/lib/zakuro/era/japan/gengou/parser.rb +1 -3
  26. data/lib/zakuro/era/japan/gengou/type.rb +3 -3
  27. data/lib/zakuro/era/japan/gengou/validator.rb +15 -13
  28. data/lib/zakuro/merchant.rb +2 -2
  29. data/lib/zakuro/operation/month/parser.rb +132 -36
  30. data/lib/zakuro/operation/month/type.rb +11 -10
  31. data/lib/zakuro/operation/month/validator.rb +332 -28
  32. data/lib/zakuro/operation/operation.rb +21 -0
  33. data/lib/zakuro/operation/yaml/month.yaml +1 -1
  34. data/lib/zakuro/output/error.rb +7 -6
  35. data/lib/zakuro/output/logger.rb +50 -49
  36. data/lib/zakuro/output/response.rb +145 -144
  37. data/lib/zakuro/result/operation.rb +64 -36
  38. data/lib/zakuro/tools/stringifier.rb +2 -2
  39. data/lib/zakuro/tools/typeof.rb +2 -2
  40. data/lib/zakuro/version.rb +1 -1
  41. data/lib/zakuro/version/abstract_version.rb +1 -1
  42. data/lib/zakuro/version/context.rb +23 -0
  43. data/lib/zakuro/version/senmyou/const/number.rb +51 -0
  44. data/lib/zakuro/version/senmyou/const/remainder.rb +43 -0
  45. data/lib/zakuro/version/senmyou/cycle/remainder.rb +61 -0
  46. data/lib/zakuro/version/senmyou/cycle/solar_term.rb +31 -0
  47. data/lib/zakuro/version/senmyou/monthly/lunar_phase.rb +166 -181
  48. data/lib/zakuro/version/senmyou/range/annual_range.rb +86 -159
  49. data/lib/zakuro/version/senmyou/senmyou.rb +10 -4
  50. data/lib/zakuro/version/senmyou/stella/lunar/adjustment.rb +237 -0
  51. data/lib/zakuro/version/senmyou/stella/lunar/localization.rb +45 -0
  52. data/lib/zakuro/version/senmyou/stella/lunar/location.rb +108 -0
  53. data/lib/zakuro/version/senmyou/stella/lunar/value.rb +89 -0
  54. data/lib/zakuro/version/senmyou/stella/origin/average_november.rb +34 -0
  55. data/lib/zakuro/version/senmyou/stella/origin/lunar_age.rb +62 -0
  56. data/lib/zakuro/version/senmyou/stella/origin/winter_solstice.rb +55 -0
  57. data/lib/zakuro/version/senmyou/stella/solar/adjustment.rb +93 -0
  58. data/lib/zakuro/version/senmyou/stella/solar/average.rb +175 -0
  59. data/lib/zakuro/version/senmyou/stella/solar/interval.rb +103 -0
  60. data/lib/zakuro/version/senmyou/stella/solar/location.rb +164 -0
  61. data/lib/zakuro/version/senmyou/stella/solar/value.rb +138 -0
  62. data/lib/zakuro/version/version_class_resolver.rb +62 -0
  63. data/lib/zakuro/version_factory.rb +2 -2
  64. metadata +38 -24
  65. data/lib/zakuro/cycle/abstract_remainder.rb +0 -456
  66. data/lib/zakuro/cycle/zodiac.rb +0 -103
  67. data/lib/zakuro/version/senmyou/base/era.rb +0 -83
  68. data/lib/zakuro/version/senmyou/base/multi_gengou.rb +0 -98
  69. data/lib/zakuro/version/senmyou/base/multi_gengou_roller.rb +0 -217
  70. data/lib/zakuro/version/senmyou/base/remainder.rb +0 -60
  71. data/lib/zakuro/version/senmyou/base/solar_term.rb +0 -76
  72. data/lib/zakuro/version/senmyou/base/year.rb +0 -104
  73. data/lib/zakuro/version/senmyou/monthly/first_day.rb +0 -44
  74. data/lib/zakuro/version/senmyou/monthly/initialized_month.rb +0 -48
  75. data/lib/zakuro/version/senmyou/monthly/month.rb +0 -181
  76. data/lib/zakuro/version/senmyou/monthly/month_label.rb +0 -87
  77. data/lib/zakuro/version/senmyou/monthly/operated_month.rb +0 -167
  78. data/lib/zakuro/version/senmyou/range/full_range.rb +0 -324
  79. data/lib/zakuro/version/senmyou/range/operated_range.rb +0 -105
  80. data/lib/zakuro/version/senmyou/range/operated_solar_terms.rb +0 -163
  81. data/lib/zakuro/version/senmyou/specifier/single_day_specifier.rb +0 -99
  82. data/lib/zakuro/version/senmyou/stella/lunar_orbit.rb +0 -332
  83. data/lib/zakuro/version/senmyou/stella/solar_average.rb +0 -214
  84. data/lib/zakuro/version/senmyou/stella/solar_orbit.rb +0 -394
  85. data/lib/zakuro/version/senmyou/stella/winter_solstice.rb +0 -106
  86. data/lib/zakuro/version/senmyou/summary/single.rb +0 -71
@@ -0,0 +1,471 @@
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
+ # @note 切り捨て前に繰り上げる
338
+ #
339
+ # @return [Integer] 小余(秒切り捨て)
340
+ #
341
+ def floor_minute
342
+ result = @minute + @second / @base_minute
343
+ result.floor
344
+ end
345
+
346
+ #
347
+ # 大余に四捨五入した結果を返す(秒は除外する)
348
+ #
349
+ # @return [AbstractRemainder] 大余
350
+ #
351
+ def round
352
+ day = @day
353
+ day += 1 if @minute >= (@base_day / 2)
354
+
355
+ initialize(day, 0, 0)
356
+ end
357
+
358
+ #
359
+ # 文字化する
360
+ #
361
+ # @return [String] 文字化
362
+ #
363
+ def to_s
364
+ "大余(日): #{@day}, 小余(分): #{@minute}, 小余(秒): #{@second}"
365
+ end
366
+
367
+ #
368
+ # 特定の文字フォーマットにして出力する
369
+ #
370
+ # @param [String] form フォーマット(大余、小余、秒それぞれを%dで指定する)
371
+ #
372
+ # @return [String] フォーマットした結果
373
+ #
374
+ def format(form: '%d-%d')
375
+ return '' if invalid?
376
+
377
+ super(form, @day, @minute, @second)
378
+ end
379
+
380
+ private
381
+
382
+ def carry!(day, minute, second)
383
+ @day, @minute, @second = carry(day, minute, second)
384
+
385
+ self
386
+ end
387
+
388
+ # 繰り上げ、繰り下げ
389
+ def carry(param_day, param_minute, param_second)
390
+ # NOTE: 計算方法としてマイナスでも徐算・剰余算の結果をプラス同様に扱う
391
+ minute, second = carry_second(param_minute, param_second)
392
+
393
+ day, minute = carry_minute(param_day, minute)
394
+
395
+ day = carry_day(day, @limited)
396
+
397
+ [day, minute, second]
398
+ end
399
+
400
+ def carry_second(param_minute, param_second)
401
+ sign = param_second.negative? ? -1 : 1
402
+ abs = sign * param_second
403
+ minute = param_minute + (sign * (abs / @base_minute).floor)
404
+ second = sign * (abs % @base_minute)
405
+
406
+ if sign.negative?
407
+ second += @base_minute
408
+ minute -= 1
409
+ end
410
+
411
+ [minute, second]
412
+ end
413
+
414
+ def carry_minute(param_day, param_minute)
415
+ sign = param_minute.negative? ? -1 : 1
416
+ abs = sign * param_minute
417
+
418
+ day = param_day + (sign * (abs / @base_day).floor)
419
+ minute = sign * (abs % @base_day)
420
+
421
+ if sign.negative?
422
+ minute += @base_day
423
+ day -= 1
424
+ end
425
+
426
+ [day, minute]
427
+ end
428
+
429
+ def carry_day(day, limited)
430
+ sign = day.negative? ? -1 : 1
431
+ abs = sign * day
432
+ carried = sign * (abs % @base_limit) if limited
433
+ carried += @base_limit if sign.negative?
434
+ carried
435
+ end
436
+
437
+ def up?(other)
438
+ invalid?(param: other)
439
+ day = other.day
440
+ minute = other.minute
441
+ return true if @day > day
442
+ return false if @day < day
443
+
444
+ return true if @minute > minute
445
+ return false if @minute < minute
446
+
447
+ @second > other.second
448
+ end
449
+
450
+ def eql?(other)
451
+ invalid?(param: other)
452
+
453
+ (@day == other.day && @minute == other.minute && @second == other.second)
454
+ end
455
+
456
+ def down?(other)
457
+ invalid?(param: other)
458
+ day = other.day
459
+ minute = other.minute
460
+ return true if @day < day
461
+ return false if @day > day
462
+
463
+ return true if @minute < minute
464
+ return false if @minute > minute
465
+
466
+ @second < other.second
467
+ end
468
+ end
469
+ end
470
+ end
471
+ end