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,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../../era/japan'
4
+ require_relative '../../../era/western'
5
+ require_relative '../../../cycle/zodiac'
6
+
7
+ # :nodoc:
8
+ module Zakuro
9
+ # :nodoc:
10
+ module Senmyou
11
+ #
12
+ # Era 宣明暦時代
13
+ #
14
+ module Era
15
+ # @return [Western::Calendar] 貞観1年1月1日
16
+ JOUGAN_START_DATE = Western::Calendar.new(year: 859, month: 2, day: 7)
17
+ # @return [Western::Calendar] 貞観4年1月1日
18
+ START_DATE = Western::Calendar.new(year: 862, month: 2, day: 3)
19
+ # @return [Integer] (貞観)4年
20
+ START_GENGOU_YEAR = 4
21
+ # @return [Western::Calendar] 貞享2年12月29日
22
+ END_DATE = Western::Calendar.new(year: 1686, month: 1, day: 23)
23
+
24
+ #
25
+ # 元号(1行目)を取得する
26
+ #
27
+ # @param [Western::Calendar] start_date 開始日
28
+ #
29
+ # @return [Japan::Gengou] 元号(1行目)
30
+ #
31
+ def self.first(start_date:)
32
+ first_gengou = Japan::GengouResource.first_line(date: start_date)
33
+ # 宣明暦の初めの元号であれば、起算年を4年とする
34
+ if JOUGAN_START_DATE == first_gengou.start_date
35
+ first_gengou = Japan::Gengou.new(
36
+ name: first_gengou.name,
37
+ start_date: START_DATE,
38
+ end_date: first_gengou.end_date,
39
+ year: START_GENGOU_YEAR
40
+ )
41
+ end
42
+
43
+ first_gengou
44
+ end
45
+
46
+ #
47
+ # 元号(2行目)を取得する
48
+ #
49
+ # @param [Western::Calendar] start_date 開始日
50
+ #
51
+ # @return [Japan::Gengou] 元号(2行目)
52
+ #
53
+ def self.second(start_date:)
54
+ Japan::GengouResource.second_line(date: start_date)
55
+ end
56
+
57
+ #
58
+ # 宣明暦に含まれるかを確認する
59
+ #
60
+ # @param [Western::Calendar] date 日付
61
+ #
62
+ # @return [True] 含まれる
63
+ # @return [False] 含まれない
64
+ #
65
+ def self.include?(date:)
66
+ (START_DATE <= date && date <= END_DATE)
67
+ end
68
+
69
+ #
70
+ # 十干十二支を引き当てる
71
+ #
72
+ # @param [String] western_year 西暦年
73
+ #
74
+ # @return [String] 十干十二支
75
+ #
76
+ def self.zodiac_name(western_year: 0)
77
+ Cycle::Zodiac.year_name(western_year: western_year)
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,210 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './era'
4
+
5
+ # :nodoc:
6
+ module Zakuro
7
+ # :nodoc:
8
+ module Senmyou
9
+ #
10
+ # Gengou 元号
11
+ #
12
+ class Gengou
13
+ # @return [Japan::Gengou] 元号(1行目)
14
+ attr_reader :first_line
15
+ # @return [Japan::Gengou] 元号(2行目)
16
+ attr_reader :second_line
17
+ # @return [Integer] 年の日数
18
+ attr_reader :total_days
19
+ # @return [Western::Calendar] 元号内での最過去日(2つの元号が重複した場合はより過去の日となる)/ 次の元号年の年初(1月1日)
20
+ attr_reader :first_date
21
+
22
+ #
23
+ # 初期化
24
+ #
25
+ # @note (see #next_year)
26
+ # 次年度以降の first_date はその元号の1年目の最初の日を設定する
27
+ #
28
+ # @param [Western::Calendar] date 対象日
29
+ # @param [Japan::Gengou] first_line 元号(1行目)
30
+ # * 計算結果を持ち越すため、自クラスでの初期化時のみ使用する
31
+ # @param [Japan::Gengou] second_line 元号(2行目)
32
+ # * 計算結果を持ち越すため、自クラスでの初期化時のみ使用する
33
+ #
34
+ def initialize(date: Era::START_DATE, first_line: Japan::Gengou.new,
35
+ second_line: Japan::Gengou.new)
36
+ @total_days = 0
37
+
38
+ if Gengou.first_called?(first_line: first_line,
39
+ second_line: second_line)
40
+ initialize_first_called(date: date)
41
+ return
42
+ end
43
+ @first_line = first_line
44
+ @second_line = second_line
45
+ @first_date = date.clone
46
+ end
47
+
48
+ #
49
+ # 初期化で最初の呼び出しかどうかを判定する
50
+ #
51
+ # @note 以下の前提がある
52
+ # * 初回呼び出しでは first_line/second_line を引数に指定しない(情報がないのでできない)
53
+ # * 次回以降の呼び出し( next_year ) では計算済みのfirst_line/second_lineを渡す
54
+ #
55
+ # @param [Japan::Gengou] first_line 元号(1行目)
56
+ # @param [Japan::Gengou] second_line 元号(2行目)
57
+ #
58
+ # @return [True] 初回呼び出し
59
+ # @return [False] 次回以降の呼び出し
60
+ #
61
+ def self.first_called?(first_line:, second_line:)
62
+ first_line.invalid? && second_line.invalid?
63
+ end
64
+
65
+ #
66
+ # 初期化(初回呼び出し)
67
+ #
68
+ # @param [Western::Calendar] date 日付
69
+ #
70
+ def initialize_first_called(date:)
71
+ raise ArgumentError, 'invalid senmyou date' unless Era.include?(date: date)
72
+
73
+ # 2つの元号が重なった時に、元号の開始日が最も古い日
74
+ @first_date = choise_oldest_gengou_date(
75
+ first_line: Era.first(start_date: date),
76
+ second_line: Era.second(start_date: date)
77
+ )
78
+ @first_line = Era.first(start_date: @first_date)
79
+ @second_line = Era.second(start_date: @first_date)
80
+
81
+ nil
82
+ end
83
+
84
+ #
85
+ # 十干十二支を取得する
86
+ #
87
+ # @return [String] 十干十二支
88
+ #
89
+ def zodiac_name
90
+ Era.zodiac_name(western_year: @first_date.year)
91
+ end
92
+
93
+ #
94
+ # 年の日数に加算する
95
+ #
96
+ # @param [Integer] days 日数
97
+ #
98
+ def add_days(days: 0)
99
+ @total_days += days
100
+
101
+ nil
102
+ end
103
+
104
+ #
105
+ # 次の年にする
106
+ #
107
+ # @return [Gengou] 次の年の元号
108
+ #
109
+ def next_year
110
+ next_date = @first_date.clone + @total_days
111
+ first = Gengou.next_first_line(gengou: @first_line, date: next_date)
112
+ second = Gengou.next_second_line(gengou: @second_line, date: next_date)
113
+
114
+ first, second = Gengou.swap_two_gengou_on_last_period(first: first,
115
+ second: second)
116
+
117
+ Gengou.new(date: next_date,
118
+ first_line: first, second_line: second)
119
+ end
120
+
121
+ #
122
+ # 南北朝の終末処理をする
123
+ #
124
+ # @note 特別対応。北朝の "明徳" を4年から主流にする(2行目から1行目にする)
125
+ #
126
+ # @param [Japan::Gengou] first 元号(1行目)
127
+ # @param [Japan::Gengou] second 元号(2行目)
128
+ #
129
+ # @return [Array<Japan::Gengou>] 元号(1行目), 元号(2行目)
130
+ #
131
+ def self.swap_two_gengou_on_last_period(first:, second:)
132
+ if first.name == second.name
133
+ first = second
134
+ second = Japan::Gengou.new
135
+ end
136
+ [first, second]
137
+ end
138
+
139
+ #
140
+ # 元号(1行目)を次の年にする
141
+ #
142
+ # @param [Japan::Gengou] gengou 元号(1行目)
143
+ # @param [Western::Calendar] date 日付
144
+ #
145
+ # @return [Japan::Gengou] 翌年の元号(1行目)
146
+ #
147
+ def self.next_first_line(gengou:, date:)
148
+ return Era.first(start_date: date) unless gengou.include?(date: date)
149
+
150
+ next_gengou = gengou.clone
151
+ next_gengou.next_year
152
+ next_gengou
153
+ end
154
+
155
+ #
156
+ # 元号(2行目)を次の年にする
157
+ #
158
+ # @param [Japan::Gengou] gengou 元号(2行目)
159
+ # @param [Western::Calendar] date 日付
160
+ #
161
+ # @return [Japan::Gengou] 翌年の元号(2行目)
162
+ #
163
+ def self.next_second_line(gengou:, date:)
164
+ return Era.second(start_date: date) unless gengou.include?(date: date)
165
+
166
+ next_gengou = gengou.clone
167
+ next_gengou.next_year
168
+ next_gengou
169
+ end
170
+
171
+ #
172
+ # 元号内での最過去日を求める
173
+ # @note 2つの元号が重複した場合はより過去の日となる
174
+ #
175
+ # @param [Japan::Gengou] first_line 元号(1行目)
176
+ # @param [Japan::Gengou] second_line 元号(2行目)
177
+ #
178
+ # @return [Western::Calendar] 最過去日
179
+ #
180
+ def choise_oldest_gengou_date(first_line: @first_line,
181
+ second_line: @second_line)
182
+ first_start_date = first_line.start_date.clone
183
+ second_start_date = second_line.start_date.clone
184
+ # first_lineは常に存在する
185
+ return first_start_date if second_line.invalid?
186
+
187
+ first_start_date < second_start_date ? first_start_date : second_start_date
188
+ end
189
+
190
+ #
191
+ # 元号内での最未来日を求める
192
+ # @note 2つの元号が重複した場合はより未来の日となる
193
+ #
194
+ # @param [Japan::Gengou] first_line 元号(1行目)
195
+ # @param [Japan::Gengou] second_line 元号(2行目)
196
+ #
197
+ # @return [Western::Calendar] 最未来日
198
+ #
199
+ def choise_newest_gengou_date(first_line: @first_line,
200
+ second_line: @second_line)
201
+ first_end_date = first_line.end_date.clone
202
+ second_end_date = second_line.end_date.clone
203
+ # first_lineは常に存在する
204
+ return first_end_date if second_line.invalid?
205
+
206
+ first_end_date > second_end_date ? first_end_date : second_end_date
207
+ end
208
+ end
209
+ end
210
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../../cycle/abstract_remainder'
4
+
5
+ # :nodoc:
6
+ module Zakuro
7
+ # :nodoc:
8
+ module Senmyou
9
+ #
10
+ # Remainder 宣明暦の時刻情報(大余小余)
11
+ #
12
+ # * 「15日1835分5秒」のような形式で表される
13
+ # * 分は8400で一日に繰り上げる
14
+ # * 秒は基本的に1/8分で、8秒で1分に繰り上げる。ただし、月補正値は1分に100秒とするなど基数の変更がありえる
15
+ # * 十干十二支(60日)を上限とした「日時分秒」の情報で、日付(date)/時刻(time)と部分的に重なる概念
16
+ #
17
+ class Remainder < Cycle::AbstractRemainder
18
+ # @return [Integer] 統法(1日=8400分)
19
+ DAY = 8400
20
+ # @return [Integer] 分(1分=8秒)
21
+ MINUTE = 8
22
+
23
+ #
24
+ # 初期化
25
+ #
26
+ # @param [Integer] day 大余("日"に相当)
27
+ # @param [Integer] minute 小余("分"に相当)
28
+ # @param [Integer] second 秒
29
+ # @param [Integer] total 繰り上げなしの小余
30
+ #
31
+ def initialize(day: -1, minute: -1, second: -1, total: -1)
32
+ super(day: day, minute: minute, second: second, total: total,
33
+ base_day: DAY, base_mitune: MINUTE)
34
+ end
35
+ end
36
+
37
+ #
38
+ # LunarRemainder 月の位相計算向け時刻情報(大余小余)
39
+ #
40
+ class LunarRemainder < Cycle::AbstractRemainder
41
+ # @return [Integer] 統法(1日=8400分)
42
+ DAY = 8400
43
+ # @return [Integer] 分(1分=100秒)
44
+ MINUTE = 100
45
+
46
+ #
47
+ # 初期化
48
+ #
49
+ # @param [Integer] day 大余("日"に相当)
50
+ # @param [Integer] minute 小余("分"に相当)
51
+ # @param [Integer] second 秒
52
+ # @param [Integer] total 繰り上げなしの小余
53
+ #
54
+ def initialize(day: -1, minute: -1, second: -1, total: -1)
55
+ super(day: day, minute: minute, second: second, total: total,
56
+ base_day: DAY, base_mitune: MINUTE)
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :nodoc:
4
+ module Zakuro
5
+ # :nodoc:
6
+ module Senmyou
7
+ #
8
+ # SolarTerm 二十四節気
9
+ #
10
+ class SolarTerm
11
+ # @return [Integer] 連番
12
+ attr_reader :index
13
+ # @return [Remainder] 時刻情報(大余小余)
14
+ attr_reader :remainder
15
+
16
+ # @return [Hash<Integer, Symbol>] 順序
17
+ ORDER = {
18
+ 0 => :touji,
19
+ 1 => :shoukan,
20
+ 2 => :daikan,
21
+ 3 => :risshun,
22
+ 4 => :usui,
23
+ 5 => :keichitsu,
24
+ 6 => :shunbun,
25
+ 7 => :seimei,
26
+ 8 => :kokuu,
27
+ 9 => :rikka,
28
+ 10 => :shouman,
29
+ 11 => :boushu,
30
+ 12 => :geshi,
31
+ 13 => :shousho,
32
+ 14 => :taisho,
33
+ 15 => :risshuu,
34
+ 16 => :shosho,
35
+ 17 => :hakuro,
36
+ 18 => :shuubun,
37
+ 19 => :kanro,
38
+ 20 => :soukou,
39
+ 21 => :rittou,
40
+ 22 => :shousetsu,
41
+ 23 => :taisetsu
42
+ }.freeze
43
+
44
+ #
45
+ # 初期化
46
+ #
47
+ # @param [Integer] index 連番
48
+ # @param [Remainder] remainder 時刻情報(大余小余)
49
+ #
50
+ def initialize(index: -1, remainder: Remainder.new)
51
+ @index = index
52
+ @remainder = remainder
53
+ end
54
+
55
+ #
56
+ # 不正かどうか検証する
57
+ #
58
+ # @return [True] 正しくない
59
+ # @return [False] 正しい
60
+ #
61
+ def invalid?
62
+ (@index == -1 || @remainder.invalid?)
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :nodoc:
4
+ module Zakuro
5
+ # :nodoc:
6
+ module Senmyou
7
+ #
8
+ # Year 年
9
+ #
10
+ class Year
11
+ # @return [Gengou] 元号
12
+ attr_reader :gengou
13
+ # @return [Array<Month>] 年内の全ての月
14
+ attr_reader :months
15
+
16
+ #
17
+ # 初期化
18
+ #
19
+ # @param [Gengou] gengou 元号
20
+ #
21
+ def initialize(gengou:)
22
+ @gengou = gengou
23
+ @months = []
24
+ end
25
+
26
+ #
27
+ # 月を追加する
28
+ #
29
+ # @param [Month] month 月
30
+ #
31
+ def push(month:)
32
+ return if duplicated?(month: month)
33
+
34
+ @months.push(month)
35
+ @gengou.add_days(days: month.days)
36
+
37
+ nil
38
+ end
39
+
40
+ #
41
+ # すでに登録済みの月と重複しているか判定する
42
+ #
43
+ # @note 昨年11月1日から今年1月1日の前日までで、去年データと重複する場合は登録スキップする
44
+ #
45
+ # @param [Month] month 月
46
+ #
47
+ # @return [True] 重複している
48
+ # @return [True] 重複していない
49
+ #
50
+ def duplicated?(month:)
51
+ @months.each do |existed|
52
+ return true if existed.same?(other: month)
53
+ end
54
+ false
55
+ end
56
+ end
57
+ end
58
+ end