zakuro 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
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