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,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