zakuro 0.0.1 → 0.0.2

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.
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../../era/western'
4
+ require_relative './full_range'
5
+ require_relative '../base/multi_gengou_roller'
6
+ require_relative '../base/year'
7
+ require_relative '../../../output/response'
8
+ require_relative '../../../output/logger'
9
+
10
+ # :nodoc:
11
+ module Zakuro
12
+ # :nodoc:
13
+ module Senmyou
14
+ #
15
+ # SingleDaySpecifier 一日検索
16
+ #
17
+ module SingleDaySpecifier
18
+ # @return [Logger] ロガー
19
+ LOGGER = Logger.new(location: 'specifier')
20
+
21
+ #
22
+ # 取得する
23
+ #
24
+ # @param [Western::Calendar] date 西暦日
25
+ #
26
+ # @return [Response::SingleDay] 和暦日
27
+ #
28
+ def self.get(date:)
29
+ years = FullRange.new(start_date: date).get
30
+
31
+ year = specify_year(years: years, date: date)
32
+
33
+ year = transfer(year: year, date: date)
34
+
35
+ month, first_date = specify_month(year: year, date: date)
36
+
37
+ Response::SingleDay.save_single_day(
38
+ param: Response::SingleDay::Param.new(
39
+ year: year, month: month,
40
+ date: date, days: date - first_date
41
+ )
42
+ )
43
+ end
44
+
45
+ #
46
+ # 年を特定する
47
+ #
48
+ # @param [Array<Year>] years 範囲
49
+ # @param [Western::Calendar] date 西暦日
50
+ #
51
+ # @return [Year] 対象年
52
+ #
53
+ def self.specify_year(years:, date:)
54
+ years.reverse_each do |year|
55
+ return year if date >= year.new_year_date
56
+ end
57
+
58
+ raise ArgumentError, "invalid year range. date: #{date.format}"
59
+ end
60
+
61
+ #
62
+ # 改元する
63
+ #
64
+ # @param [Year] year 年
65
+ # @param [Western::Calendar] date 西暦日
66
+ #
67
+ # @return [Year] 改元後の年
68
+ #
69
+ def self.transfer(year:, date:)
70
+ multi_gengou = MultiGengouRoller.transfer(multi_gengou: year.multi_gengou, date: date)
71
+ Year.new(multi_gengou: multi_gengou, new_year_date: year.new_year_date,
72
+ months: year.months, total_days: year.total_days)
73
+ end
74
+
75
+ # :reek:TooManyStatements { max_statements: 7 }
76
+
77
+ #
78
+ # 月を特定する
79
+ #
80
+ # @param [Year] year 年
81
+ # @param [Western::Calendar] date 西暦日
82
+ #
83
+ # @return [Month] 対象月
84
+ # @return [Western::Calendar] 月初日
85
+ #
86
+ def self.specify_month(year:, date:)
87
+ current_month_date = year.new_year_date.clone
88
+ next_month_date = current_month_date.clone
89
+ year.months.each do |month|
90
+ next_month_date += month.days
91
+ return month, current_month_date if next_month_date > date
92
+
93
+ current_month_date = next_month_date.clone
94
+ end
95
+
96
+ raise ArgumentError, "invalid month range. date: #{date.format}"
97
+ end
98
+ end
99
+ end
100
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zakuro
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - pldb
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-08-01 00:00:00.000000000 Z
11
+ date: 2020-10-05 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: mainly lunar solar calendar
14
14
  email:
@@ -23,10 +23,12 @@ files:
23
23
  - ".rubocop.yml"
24
24
  - Gemfile
25
25
  - LICENSE.txt
26
+ - Makefile
26
27
  - README.md
27
28
  - Rakefile
28
29
  - bin/console
29
30
  - bin/setup
31
+ - doc/gengou.md
30
32
  - images/12月以降の入定気.png
31
33
  - images/12月以降の月の進退.png
32
34
  - images/source/description.numbers
@@ -58,7 +60,8 @@ files:
58
60
  - lib/zakuro/version/kansei/kansei.rb
59
61
  - lib/zakuro/version/senmyou/README.md
60
62
  - lib/zakuro/version/senmyou/base/era.rb
61
- - lib/zakuro/version/senmyou/base/gengou.rb
63
+ - lib/zakuro/version/senmyou/base/multi_gengou.rb
64
+ - lib/zakuro/version/senmyou/base/multi_gengou_roller.rb
62
65
  - lib/zakuro/version/senmyou/base/remainder.rb
63
66
  - lib/zakuro/version/senmyou/base/solar_term.rb
64
67
  - lib/zakuro/version/senmyou/base/year.rb
@@ -69,8 +72,9 @@ files:
69
72
  - lib/zakuro/version/senmyou/stella/solar_average.rb
70
73
  - lib/zakuro/version/senmyou/stella/solar_orbit.rb
71
74
  - lib/zakuro/version/senmyou/stella/winter_solstice.rb
72
- - lib/zakuro/version/senmyou/summary/annual_data.rb
73
- - lib/zakuro/version/senmyou/summary/gengou_data.rb
75
+ - lib/zakuro/version/senmyou/summary/annual_range.rb
76
+ - lib/zakuro/version/senmyou/summary/full_range.rb
77
+ - lib/zakuro/version/senmyou/summary/specifier.rb
74
78
  - lib/zakuro/version/taien/taien.rb
75
79
  - lib/zakuro/version/tenpou/tenpou.rb
76
80
  - lib/zakuro/version_factory.rb
@@ -83,7 +87,7 @@ metadata:
83
87
  homepage_uri: https://github.com/pldb/zakuro
84
88
  source_code_uri: https://github.com/pldb/zakuro
85
89
  changelog_uri: https://github.com/pldb/zakuro
86
- post_install_message:
90
+ post_install_message:
87
91
  rdoc_options: []
88
92
  require_paths:
89
93
  - lib
@@ -98,8 +102,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
98
102
  - !ruby/object:Gem::Version
99
103
  version: '0'
100
104
  requirements: []
101
- rubygems_version: 3.0.3
102
- signing_key:
105
+ rubygems_version: 3.1.2
106
+ signing_key:
103
107
  specification_version: 4
104
108
  summary: japanese calendar library.
105
109
  test_files: []
@@ -1,210 +0,0 @@
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
@@ -1,294 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../../../era/western'
4
- require_relative 'annual_data'
5
- require_relative '../../../output/response'
6
- require_relative '../base/era'
7
- require_relative '../base/gengou'
8
- require_relative '../base/year'
9
-
10
- # :nodoc:
11
- module Zakuro
12
- # :nodoc:
13
- module Senmyou
14
- #
15
- # GengouData 元号の年情報
16
- #
17
- module GengouData
18
- def self.get_ancient_date(date: Western::Calendar.new)
19
- SingleDay.get_ancient_date(date: date)
20
- end
21
-
22
- #
23
- # SingleDay 1日データ
24
- #
25
- module SingleDay
26
- #
27
- # 1日データを取得する
28
- #
29
- # @param [Western::Calendar] date 年月日情報(西暦)
30
- #
31
- # @return [Response::SingleDay] 1日データ
32
- #
33
- def self.get_ancient_date(date: Western::Calendar.new)
34
- raise ArgumentError, 'invalid senmyou date' unless Era.include?(date: date)
35
-
36
- target = get_target(year_list: get_year_list(date: date), date: date)
37
-
38
- Response::SingleDay.save_single_day(
39
- param: Response::SingleDay::Param.new(
40
- year: target.year, month: target.month,
41
- date: target.date, days: target.days
42
- )
43
- )
44
- end
45
-
46
- #
47
- # Target 対象
48
- #
49
- class Target
50
- # @return [Year] 年
51
- attr_reader :year
52
- # @return [Month] 月
53
- attr_reader :month
54
- # @return [Western::Calendar] 日
55
- attr_reader :date
56
- # @return [Integer] 月初からの日数
57
- attr_reader :days
58
-
59
- #
60
- # 初期化
61
- #
62
- # @param [Year] year 年
63
- # @param [Month] month 月
64
- # @param [Western::Calendar] date 日
65
- # @param [Integer] days 月初からの日数
66
- #
67
- def initialize(year:, month:, date:, days:)
68
- @year = year
69
- @month = month
70
- @date = date
71
- @days = days
72
- end
73
- end
74
-
75
- #
76
- # MonthSearchResult 1年内に該当する月を検索した結果
77
- #
78
- class MonthSearchResult
79
- # @return [Month] 月
80
- attr_reader :target_month
81
- # @return [Western::Calendar] 月初日
82
- attr_reader :first_date
83
- # @return [True] 該当データ引き当て済
84
- # @return [False] 該当データ引き当てなし
85
- attr_reader :breaked
86
-
87
- #
88
- # 初期化
89
- #
90
- # @param [Month] target_month 月
91
- # @param [Western::Calendar] first_date 月初日
92
- # @param [True, False] breaked 該当データ引き当て
93
- #
94
- def initialize(target_month: Month.new,
95
- first_date: Western::Calendar.new, breaked:)
96
- @target_month = target_month
97
- @first_date = first_date
98
- @breaked = breaked
99
- end
100
- end
101
-
102
- #
103
- # 指定日に関連する暦の範囲だけ年データを生成する
104
- #
105
- # @param [Western::Calendar] date 西暦日
106
- #
107
- # @return [Array<Year>] 年データ
108
- #
109
- def self.get_year_list(date:)
110
- # 元号の最初の年月日を取る
111
- gengou = Gengou.new(date: date.clone)
112
-
113
- # 南北朝には元号が2つ並び、必ずしも範囲が重ならないケースもある
114
- # 対象日付に重なる元号から論理和の範囲を取り、処理漏れがないようにする
115
- start_date = gengou.first_date.clone
116
- # 最後の年は翌年から今年の冬至を求めるため範囲を1年広げる
117
- newest_date = gengou.choise_newest_gengou_date.next_year
118
-
119
- Series.get_year_list(
120
- start_gengou: gengou, start_date: start_date, end_date: newest_date
121
- )
122
- end
123
-
124
- #
125
- # 対象を引き当てる
126
- #
127
- # @param [Array<Year>] year_list 年データ
128
- # @param [Western::Calendar] date 西暦日
129
- #
130
- # @return [Target] 対象
131
- #
132
- def self.get_target(year_list:, date:)
133
- # 対象年/対象月を引き当てる
134
- year_list.each do |year|
135
- result = get_target_month(date: date, year: year)
136
-
137
- next unless result.breaked
138
-
139
- return Target.new(
140
- year: year, month: result.target_month, date: date,
141
- # 対象日に調整する
142
- days: date - result.first_date
143
- )
144
- end
145
-
146
- raise ArgumentError, "invalid range: #{date.format}"
147
- end
148
-
149
- # :reek:TooManyStatements { max_statements: 6 }
150
-
151
- #
152
- # 対象の月を引き当てる
153
- #
154
- # @param [Western::Calendar] date 西暦日
155
- # @param [Year] year 年
156
- #
157
- # @return [MonthSearchResult] 1年内に該当する月を検索した結果
158
- #
159
- def self.get_target_month(date:, year:)
160
- first_date = year.gengou.first_date.clone
161
- year.months.each do |month|
162
- # 月末の日付を超える場合
163
- next_first_date = first_date.clone + month.days
164
- if date < next_first_date
165
- return MonthSearchResult.new(target_month: month,
166
- first_date: first_date, breaked: true)
167
- end
168
- first_date = next_first_date
169
- end
170
- MonthSearchResult.new(breaked: false)
171
- end
172
- end
173
-
174
- #
175
- # Series 和暦時系列データ
176
- #
177
- module Series
178
- # :reek:TooManyInstanceVariables { max_instance_variables: 6 }
179
-
180
- #
181
- # TimeAdvance 時間進行
182
- #
183
- class TimeAdvance
184
- #
185
- # 初期化
186
- #
187
- # @param [Gengou] start_gengou 開始元号
188
- # @param [Western::Calendar] start_date 開始日
189
- # @param [Western::Calendar] end_date 終了日
190
- #
191
- def initialize(start_gengou:, start_date:, end_date:)
192
- @current_date = start_date.clone
193
- @end_date = end_date
194
- @year_list = []
195
- @western_year = start_date.year
196
- @year = Year.new(gengou: start_gengou)
197
- end
198
-
199
- #
200
- # 年データを収集する
201
- #
202
- # @return [Array<Year>] 年データ
203
- #
204
- def collect_year_list
205
- push_current_year
206
-
207
- # 2年目以降
208
- while @current_date <= @end_date
209
- compensate_last_year
210
-
211
- push_current_year
212
- end
213
-
214
- @year_list
215
- end
216
-
217
- private
218
-
219
- #
220
- # 1年データを収集する
221
- #
222
- # @return [Array<Month>] 1年データ
223
- #
224
- def collect_annual_data
225
- AnnualData.collect_annual_data_after_last_november_1st(
226
- western_year: @western_year
227
- )
228
- end
229
-
230
- #
231
- # 昨年データの不足分を補完する
232
- # 昨年11月1日から今年1月1日の前日のデータを1年前データとする
233
- #
234
- # @return [<Type>] <description>
235
- #
236
- def compensate_last_year
237
- last_year = @year_list[@year_list.size - 1]
238
- collect_annual_data.each do |month|
239
- next unless month.is_last_year
240
-
241
- # 昨年の月データのみ
242
- last_year.push(month: month)
243
- @current_date += month.days
244
- end
245
- end
246
-
247
- # :reek:TooManyStatements { max_statements: 7 }
248
-
249
- #
250
- # 当年データを生成する
251
- #
252
- def push_current_year
253
- next_year
254
- collect_annual_data.each do |month|
255
- next if month.is_last_year
256
-
257
- @year.push(month: month)
258
- @current_date += month.days
259
- end
260
- @year_list.push(@year)
261
-
262
- @western_year += 1
263
- end
264
-
265
- #
266
- # 次の元号年を取得する
267
- #
268
- def next_year
269
- return if @year_list.empty?
270
-
271
- @year = Year.new(gengou: @year.gengou.next_year)
272
- end
273
- end
274
-
275
- #
276
- # 期間内の年データ全てを返す
277
- #
278
- # @param [Gengou] start_gengou 開始元号
279
- # @param [Western::Calendar] start_date 開始日
280
- # @param [Western::Calendar] end_date 終了日
281
- #
282
- # @return [Array<Year>] 年データ
283
- #
284
- def self.get_year_list(start_gengou:, start_date:, end_date:)
285
- advance = TimeAdvance.new(
286
- start_gengou: start_gengou, start_date: start_date, end_date: end_date
287
- )
288
-
289
- advance.collect_year_list
290
- end
291
- end
292
- end
293
- end
294
- end