zakuro 0.0.0

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 (61) hide show
  1. checksums.yaml +7 -0
  2. data/.editorconfig +9 -0
  3. data/.gitignore +69 -0
  4. data/.rspec +3 -0
  5. data/.rubocop.yml +14 -0
  6. data/.travis.yml +6 -0
  7. data/Gemfile +19 -0
  8. data/LICENSE.txt +21 -0
  9. data/README.md +44 -0
  10. data/Rakefile +20 -0
  11. data/bin/console +14 -0
  12. data/bin/setup +8 -0
  13. data/images/12/346/234/210/344/273/245/351/231/215/343/201/256/345/205/245/345/256/232/346/260/227.png +0 -0
  14. data/images/12/346/234/210/344/273/245/351/231/215/343/201/256/346/234/210/343/201/256/351/200/262/351/200/200.png +0 -0
  15. data/images/source/description.numbers +0 -0
  16. data/images//345/205/245/345/256/232/346/260/227/343/201/256/350/265/267/347/256/227.png +0 -0
  17. data/images//345/220/204/346/234/210/343/201/256/346/261/202/343/202/201/346/226/271.png +0 -0
  18. data/images//345/244/252/351/231/275/343/201/250/346/234/210.png +0 -0
  19. data/lib/zakuro.rb +9 -0
  20. data/lib/zakuro/condition.rb +239 -0
  21. data/lib/zakuro/cycle/abstract_remainder.rb +457 -0
  22. data/lib/zakuro/cycle/zodiac.rb +103 -0
  23. data/lib/zakuro/era/gengou/set-001-until-south.yaml +375 -0
  24. data/lib/zakuro/era/gengou/set-002-from-north.yaml +166 -0
  25. data/lib/zakuro/era/gengou/set-003-modern.yaml +12 -0
  26. data/lib/zakuro/era/japan.rb +630 -0
  27. data/lib/zakuro/era/western.rb +412 -0
  28. data/lib/zakuro/merchant.rb +57 -0
  29. data/lib/zakuro/output/error.rb +10 -0
  30. data/lib/zakuro/output/logger.rb +64 -0
  31. data/lib/zakuro/output/response.rb +170 -0
  32. data/lib/zakuro/output/result.rb +219 -0
  33. data/lib/zakuro/output/stringifier.rb +62 -0
  34. data/lib/zakuro/version.rb +7 -0
  35. data/lib/zakuro/version/abstract_version.rb +29 -0
  36. data/lib/zakuro/version/genka/genka.rb +19 -0
  37. data/lib/zakuro/version/gihou/gihou.rb +19 -0
  38. data/lib/zakuro/version/gregorio/gregorio.rb +19 -0
  39. data/lib/zakuro/version/houryaku/houryaku.rb +19 -0
  40. data/lib/zakuro/version/joukyou/joukyou.rb +19 -0
  41. data/lib/zakuro/version/kansei/kansei.rb +19 -0
  42. data/lib/zakuro/version/senmyou/README.md +586 -0
  43. data/lib/zakuro/version/senmyou/base/era.rb +81 -0
  44. data/lib/zakuro/version/senmyou/base/gengou.rb +210 -0
  45. data/lib/zakuro/version/senmyou/base/remainder.rb +60 -0
  46. data/lib/zakuro/version/senmyou/base/solar_term.rb +66 -0
  47. data/lib/zakuro/version/senmyou/base/year.rb +58 -0
  48. data/lib/zakuro/version/senmyou/monthly/lunar_phase.rb +220 -0
  49. data/lib/zakuro/version/senmyou/monthly/month.rb +112 -0
  50. data/lib/zakuro/version/senmyou/senmyou.rb +34 -0
  51. data/lib/zakuro/version/senmyou/stella/lunar_orbit.rb +332 -0
  52. data/lib/zakuro/version/senmyou/stella/solar_average.rb +192 -0
  53. data/lib/zakuro/version/senmyou/stella/solar_orbit.rb +398 -0
  54. data/lib/zakuro/version/senmyou/stella/winter_solstice.rb +106 -0
  55. data/lib/zakuro/version/senmyou/summary/annual_data.rb +186 -0
  56. data/lib/zakuro/version/senmyou/summary/gengou_data.rb +294 -0
  57. data/lib/zakuro/version/taien/taien.rb +19 -0
  58. data/lib/zakuro/version/tenpou/tenpou.rb +19 -0
  59. data/lib/zakuro/version_factory.rb +59 -0
  60. data/zakuro.gemspec +31 -0
  61. metadata +106 -0
@@ -0,0 +1,457 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :nodoc:
4
+ module Zakuro
5
+ # :nodoc:
6
+ module Cycle
7
+ #
8
+ # 大余小余(時刻情報)
9
+ # @abstract 大余小余計算に必要な処理を行う、暦に依存しない汎用的なクラス
10
+ #
11
+ class AbstractRemainder # rubocop:disable Metrics/ClassLength
12
+ # @return [Integer] 大余上限
13
+ LIMIT = 60
14
+
15
+ # @return [Integer] 大余("日"に相当)
16
+ attr_reader :day
17
+ # @return [Integer] 小余("分"に相当)
18
+ attr_reader :minute
19
+ # @return [Integer] 秒
20
+ attr_reader :second
21
+ # @return [Integer] 繰り上げなしの小余
22
+ attr_reader :base_limit
23
+ # @return [Integer] 1大余に必要な小余(暦によって基数が異なる)
24
+ attr_reader :base_day
25
+ # @return [Integer] 1小余に必要な秒(暦によって基数が異なる)
26
+ attr_reader :base_minute
27
+ # 繰り上げ有無
28
+ # @return [True] 繰り上げあり
29
+ # @return [False] 繰り上げなし
30
+ attr_reader :limited
31
+
32
+ # :reek:instanceVariableAssumption
33
+ # rubocop:disable Metrics/ParameterLists
34
+
35
+ #
36
+ # 初期化
37
+ #
38
+ # @param [Integer] day 大余("日"に相当)
39
+ # @param [Integer] minute 小余("分"に相当)
40
+ # @param [Integer] second 秒
41
+ # @param [Integer] total 繰り上げなしの小余
42
+ # @param [Integer] base_day 1大余に必要な小余(暦によって基数が異なる)
43
+ # @param [Integer] base_mitune 1小余に必要な秒(暦によって基数が異なる)
44
+ #
45
+ def initialize(day: -1, minute: -1, second: -1, total: -1,
46
+ base_day:, base_mitune:)
47
+ @base_limit = LIMIT
48
+ @base_day = base_day
49
+ @base_minute = base_mitune
50
+ @limited = true
51
+
52
+ set(day: day, minute: minute, second: second, total: total)
53
+ end
54
+ # rubocop:enable Metrics/ParameterLists
55
+
56
+ #
57
+ # 値を設定する
58
+ #
59
+ # @param [Integer] day 大余("日"に相当)
60
+ # @param [Integer] minute 小余("分"に相当)
61
+ # @param [Integer] second 秒
62
+ # @param [Integer] total 繰り上げなしの小余
63
+ #
64
+ # @return [AbstractRemainder] 自身の参照
65
+ #
66
+ def set(day: -1, minute: -1, second: -1, total: -1)
67
+ @day = day
68
+ @minute = minute
69
+ @second = second
70
+
71
+ if total != -1
72
+ @day = (total.to_f / @base_day).floor
73
+ @minute = (total % @base_day)
74
+ @second = 0
75
+ end
76
+
77
+ self
78
+ end
79
+
80
+ #
81
+ # 繰り上げ処理を外す
82
+ #
83
+ # @return [AbstractRemainder] 自身の参照
84
+ #
85
+ def lift_limit
86
+ @limited = false
87
+
88
+ self
89
+ end
90
+
91
+ #
92
+ # 繰り上げ処理を設定する
93
+ #
94
+ # @return [AbstractRemainder] 自身の参照
95
+ #
96
+ def set_limit
97
+ @limited = true
98
+
99
+ self
100
+ end
101
+
102
+ #
103
+ # 無効かどうか
104
+ #
105
+ # @param [AbstractRemainder] param 自クラスのインスタンス(デフォルトは自身の参照)
106
+ #
107
+ # @return [True] 無効
108
+ # @return [False] 有効
109
+ #
110
+ def invalid?(param: self)
111
+ raise ArgumentError, 'unmatch parameter type' unless param.is_a?(AbstractRemainder)
112
+
113
+ param.day == -1 || param.minute == -1 || param.second == -1
114
+ end
115
+
116
+ #
117
+ # 十干十二支名
118
+ #
119
+ # @return [String] 十干十二支名
120
+ #
121
+ def zodiac_name
122
+ Cycle::Zodiac.day_name(day: @day)
123
+ end
124
+
125
+ #
126
+ # 日が同じ十干かどうか(大小の月判定)
127
+ #
128
+ # @param [Integer] other 大余
129
+ #
130
+ # @return [True] 当月朔日と翌月朔日が同じ十干(「大」の月)
131
+ # @return [False] 当月朔日と翌月朔日が異なる十干(「小」の月)
132
+ #
133
+ def same_remainder_divided_by_ten?(other:)
134
+ day = @day % LIMIT
135
+
136
+ (day % 10) == (other % 10)
137
+ end
138
+
139
+ #
140
+ # (非破壊的に)加算する
141
+ #
142
+ # @param [AbstractRemainder] other 他の大余小余
143
+ #
144
+ # @return [AbstractRemainder] 加算結果
145
+ #
146
+ def add(other)
147
+ invalid?(param: other)
148
+ day = @day + other.day
149
+ minute = @minute + other.minute
150
+ second = @second + other.second
151
+ day, minute, second = carry(day, minute, second)
152
+
153
+ clone.set(day: day, minute: minute, second: second)
154
+ end
155
+
156
+ #
157
+ # (破壊的に)加算する
158
+ #
159
+ # @param [AbstractRemainder] other 他の大余小余
160
+ #
161
+ # @return [AbstractRemainder] 加算結果
162
+ #
163
+ def add!(other)
164
+ result = add(other)
165
+ @day = result.day
166
+ @minute = result.minute
167
+ @second = result.second
168
+
169
+ self
170
+ end
171
+
172
+ #
173
+ # (非破壊的に)除算する
174
+ #
175
+ # @param [AbstractRemainder] other 他の大余小余
176
+ #
177
+ # @return [AbstractRemainder] 除算結果
178
+ #
179
+ def sub(other)
180
+ invalid?(param: other)
181
+ day = @day - other.day
182
+ minute = @minute - other.minute
183
+ second = @second - other.second
184
+ day, minute, second = carry(day, minute, second)
185
+
186
+ clone.set(day: day, minute: minute, second: second)
187
+ end
188
+
189
+ #
190
+ # (破壊的に)除算する
191
+ #
192
+ # @param [AbstractRemainder] other 他の大余小余
193
+ #
194
+ # @return [AbstractRemainder] 除算結果
195
+ #
196
+ def sub!(other)
197
+ result = sub(other)
198
+ @day = result.day
199
+ @minute = result.minute
200
+ @second = result.second
201
+
202
+ self
203
+ end
204
+
205
+ #
206
+ # 大小比較(>)
207
+ #
208
+ # @param [AbstractRemainder] other 他の大余小余
209
+ #
210
+ # @return [True] より大きい
211
+ # @return [False] 以下
212
+ #
213
+ def >(other)
214
+ up?(other)
215
+ end
216
+
217
+ #
218
+ # 大小比較(>=)
219
+ #
220
+ # @param [AbstractRemainder] other 他の大余小余
221
+ #
222
+ # @return [True] 以上
223
+ # @return [False] より小さい
224
+ #
225
+ def >=(other)
226
+ up?(other) || \
227
+ (@day == other.day && @minute == other.minute && @second == other.second)
228
+ end
229
+
230
+ #
231
+ # 大小比較(<)
232
+ #
233
+ # @param [AbstractRemainder] other 他の大余小余
234
+ #
235
+ # @return [True] より小さい
236
+ # @return [False] 以上
237
+ #
238
+ def <(other)
239
+ down?(other)
240
+ end
241
+
242
+ #
243
+ # 大小比較(<=)
244
+ #
245
+ # @param [AbstractRemainder] other 他の大余小余
246
+ #
247
+ # @return [True] 以下
248
+ # @return [False] より大きい
249
+ #
250
+ def <=(other)
251
+ down?(other) || \
252
+ (@day == other.day && @minute == other.minute && @second == other.second)
253
+ end
254
+
255
+ #
256
+ # 大小比較(==)
257
+ #
258
+ # @param [AbstractRemainder] other 他の大余小余
259
+ #
260
+ # @return [True] 等しい
261
+ # @return [False] 等しくない
262
+ #
263
+ def ==(other)
264
+ eql?(other)
265
+ end
266
+
267
+ #
268
+ # 大小比較(!=)
269
+ #
270
+ # @param [AbstractRemainder] other 他の大余小余
271
+ #
272
+ # @return [True] 等しくない
273
+ # @return [False] 等しい
274
+ #
275
+ def !=(other)
276
+ !eql?(other)
277
+ end
278
+
279
+ # 進朔
280
+ # @see 進朔 http://eco.mtk.nao.ac.jp/koyomi/wiki/C2C0B1A2C2C0CDDBCEF12FBFCABAF3.html
281
+ # 進朔とは、朔の瞬間が1日の3/4すなわち夕方以降となる場合に、その日ではなく1日進めて翌日を1日目にする方法のことです。
282
+ # 進朔するかどうかの基準時刻を進朔限といいます。宣明暦では1日8400分ですから、進朔限は6300分で、それ以降だと進朔されます。
283
+
284
+ #
285
+ # (非破壊的に)進朔する
286
+ #
287
+ # @see http://eco.mtk.nao.ac.jp/koyomi/wiki/C2C0B1A2C2C0CDDBCEF12FBFCABAF3.html
288
+ #
289
+ # 進朔とは、朔の瞬間が1日の3/4すなわち夕方以降となる場合に、その日ではなく1日進めて翌日を1日目にする方法のことです。
290
+ # 進朔するかどうかの基準時刻を進朔限といいます。宣明暦では1日8400分ですから、進朔限は6300分で、それ以降だと進朔されます。
291
+ #
292
+ # @return [AbstractRemainder] 進朔結果
293
+ #
294
+ def up_on_new_moon
295
+ cloned = clone
296
+ limit = (base_day * 3) / 4
297
+ if @minute >= limit
298
+ day, minute, second = carry((@day + 1), @minute, @second)
299
+ return cloned.set(day: day, minute: minute, second: second)
300
+ end
301
+
302
+ cloned
303
+ end
304
+
305
+ #
306
+ # (破壊的に)進朔する
307
+ #
308
+ # @see http://eco.mtk.nao.ac.jp/koyomi/wiki/C2C0B1A2C2C0CDDBCEF12FBFCABAF3.html
309
+ #
310
+ # 進朔とは、朔の瞬間が1日の3/4すなわち夕方以降となる場合に、その日ではなく1日進めて翌日を1日目にする方法のことです。
311
+ # 進朔するかどうかの基準時刻を進朔限といいます。宣明暦では1日8400分ですから、進朔限は6300分で、それ以降だと進朔されます。
312
+ #
313
+ # @return [AbstractRemainder] 進朔結果
314
+ #
315
+ def up_on_new_moon!
316
+ result = up_on_new_moon
317
+ @day = result.day
318
+ @minute = result.minute
319
+ @second = result.second
320
+
321
+ self
322
+ end
323
+
324
+ #
325
+ # 小余に揃えた結果を返す(秒は除外する)
326
+ #
327
+ # @return [Integer] 小余
328
+ #
329
+ def to_minute
330
+ @day * @base_day + @minute
331
+ end
332
+
333
+ #
334
+ # 大余に四捨五入した結果を返す(秒は除外する)
335
+ #
336
+ # @return [AbstractRemainder] 大余
337
+ #
338
+ def round
339
+ day = @day
340
+ day += 1 if @minute >= (@base_day / 2)
341
+
342
+ initialize(day, 0, 0)
343
+ end
344
+
345
+ #
346
+ # 文字化する
347
+ #
348
+ # @return [String] 文字化
349
+ #
350
+ def to_s
351
+ "大余(日): #{@day}, 小余(分): #{@minute}, 小余(秒): #{@second}"
352
+ end
353
+
354
+ #
355
+ # 特定の文字フォーマットにして出力する
356
+ #
357
+ # @param [String] form フォーマット(大余、小余、秒それぞれを%dで指定する)
358
+ #
359
+ # @return [String] フォーマットした結果
360
+ #
361
+ def format(form: '%d-%d')
362
+ return '' if invalid?
363
+
364
+ super(form, @day, @minute, @second)
365
+ end
366
+
367
+ private
368
+
369
+ def carry!(day, minute, second)
370
+ @day, @minute, @second = carry(day, minute, second)
371
+
372
+ self
373
+ end
374
+
375
+ # 繰り上げ、繰り下げ
376
+ def carry(param_day, param_minute, param_second)
377
+ # NOTE: 計算方法としてマイナスでも徐算・剰余算の結果をプラス同様に扱う
378
+ minute, second = carry_second(param_minute, param_second)
379
+
380
+ day, minute = carry_minute(param_day, minute)
381
+
382
+ day = carry_day(day, @limited)
383
+
384
+ [day, minute, second]
385
+ end
386
+
387
+ def carry_second(param_minute, param_second)
388
+ sign = param_second.negative? ? -1 : 1
389
+ abs = sign * param_second
390
+ minute = param_minute + (sign * (abs / @base_minute).floor)
391
+ second = sign * (abs % @base_minute)
392
+
393
+ if sign.negative?
394
+ second += @base_minute
395
+ minute -= 1
396
+ end
397
+
398
+ [minute, second]
399
+ end
400
+
401
+ def carry_minute(param_day, param_minute)
402
+ sign = param_minute.negative? ? -1 : 1
403
+ abs = sign * param_minute
404
+
405
+ day = param_day + (sign * (abs / @base_day).floor)
406
+ minute = sign * (abs % @base_day)
407
+
408
+ if sign.negative?
409
+ minute += @base_day
410
+ day -= 1
411
+ end
412
+
413
+ [day, minute]
414
+ end
415
+
416
+ def carry_day(day, limited)
417
+ sign = day.negative? ? -1 : 1
418
+ abs = sign * day
419
+ carried = sign * (abs % @base_limit) if limited
420
+ carried += @base_limit if sign.negative?
421
+ carried
422
+ end
423
+
424
+ def up?(other)
425
+ invalid?(param: other)
426
+ day = other.day
427
+ minute = other.minute
428
+ return true if @day > day
429
+ return false if @day < day
430
+
431
+ return true if @minute > minute
432
+ return false if @minute < minute
433
+
434
+ @second > other.second
435
+ end
436
+
437
+ def eql?(other)
438
+ invalid?(param: other)
439
+
440
+ (@day == other.day && @minute == other.minute && @second == other.second)
441
+ end
442
+
443
+ def down?(other)
444
+ invalid?(param: other)
445
+ day = other.day
446
+ minute = other.minute
447
+ return true if @day < day
448
+ return false if @day > day
449
+
450
+ return true if @minute < minute
451
+ return false if @minute > minute
452
+
453
+ @second < other.second
454
+ end
455
+ end
456
+ end
457
+ end