zakuro 0.0.0 → 0.1.1

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 (73) hide show
  1. checksums.yaml +4 -4
  2. data/.editorconfig +4 -0
  3. data/.gitignore +7 -1
  4. data/.rubocop.yml +3 -0
  5. data/Gemfile +2 -0
  6. data/Makefile +2 -0
  7. data/README.md +156 -10
  8. data/Rakefile +1 -1
  9. data/doc/gengou.md +315 -0
  10. data/doc/operation.md +25 -0
  11. data/doc/operation/csv/month.csv +202 -0
  12. data/doc/operation/operation.xlsx +0 -0
  13. data/doc/operation/transfer.rb +77 -0
  14. data/lib/zakuro/condition.rb +19 -15
  15. data/lib/zakuro/cycle/abstract_remainder.rb +3 -4
  16. data/lib/zakuro/era/japan/gengou.rb +106 -0
  17. data/lib/zakuro/era/japan/gengou/parser.rb +167 -0
  18. data/lib/zakuro/era/japan/gengou/type.rb +178 -0
  19. data/lib/zakuro/era/japan/gengou/validator.rb +236 -0
  20. data/lib/zakuro/era/japan/reki.rb +91 -0
  21. data/lib/zakuro/era/japan/yaml/set-001-until-south.yaml +1121 -0
  22. data/lib/zakuro/era/japan/yaml/set-002-from-north.yaml +485 -0
  23. data/lib/zakuro/era/japan/yaml/set-003-modern.yaml +28 -0
  24. data/lib/zakuro/era/western.rb +11 -1
  25. data/lib/zakuro/merchant.rb +3 -1
  26. data/lib/zakuro/operation/month/parser.rb +373 -0
  27. data/lib/zakuro/operation/month/type.rb +458 -0
  28. data/lib/zakuro/operation/month/validator.rb +802 -0
  29. data/lib/zakuro/operation/operation.rb +66 -0
  30. data/lib/zakuro/operation/yaml/month.yaml +6452 -0
  31. data/lib/zakuro/output/error.rb +2 -0
  32. data/lib/zakuro/output/logger.rb +2 -0
  33. data/lib/zakuro/output/response.rb +21 -19
  34. data/lib/zakuro/result/core.rb +52 -0
  35. data/lib/zakuro/result/data.rb +187 -0
  36. data/lib/zakuro/result/operation.rb +114 -0
  37. data/lib/zakuro/result/result.rb +37 -0
  38. data/lib/zakuro/{output → tools}/stringifier.rb +16 -9
  39. data/lib/zakuro/tools/typeof.rb +33 -0
  40. data/lib/zakuro/version.rb +1 -1
  41. data/lib/zakuro/version/senmyou/README.md +3 -1
  42. data/lib/zakuro/version/senmyou/base/era.rb +3 -1
  43. data/lib/zakuro/version/senmyou/base/multi_gengou.rb +98 -0
  44. data/lib/zakuro/version/senmyou/base/multi_gengou_roller.rb +217 -0
  45. data/lib/zakuro/version/senmyou/base/remainder.rb +4 -4
  46. data/lib/zakuro/version/senmyou/base/solar_term.rb +20 -0
  47. data/lib/zakuro/version/senmyou/base/year.rb +52 -6
  48. data/lib/zakuro/version/senmyou/monthly/first_day.rb +44 -0
  49. data/lib/zakuro/version/senmyou/monthly/initialized_month.rb +48 -0
  50. data/lib/zakuro/version/senmyou/monthly/lunar_phase.rb +1 -1
  51. data/lib/zakuro/version/senmyou/monthly/month.rb +136 -67
  52. data/lib/zakuro/version/senmyou/monthly/month_label.rb +87 -0
  53. data/lib/zakuro/version/senmyou/monthly/operated_month.rb +167 -0
  54. data/lib/zakuro/version/senmyou/{summary/annual_data.rb → range/annual_range.rb} +38 -40
  55. data/lib/zakuro/version/senmyou/range/full_range.rb +324 -0
  56. data/lib/zakuro/version/senmyou/range/operated_range.rb +126 -0
  57. data/lib/zakuro/version/senmyou/range/operated_solar_terms.rb +181 -0
  58. data/lib/zakuro/version/senmyou/senmyou.rb +2 -2
  59. data/lib/zakuro/version/senmyou/specifier/single_day_specifier.rb +102 -0
  60. data/lib/zakuro/version/senmyou/stella/lunar_orbit.rb +1 -1
  61. data/lib/zakuro/version/senmyou/stella/solar_average.rb +54 -32
  62. data/lib/zakuro/version/senmyou/stella/solar_orbit.rb +3 -7
  63. data/lib/zakuro/version/senmyou/summary/single.rb +125 -0
  64. data/lib/zakuro/version_factory.rb +1 -1
  65. metadata +40 -13
  66. data/.travis.yml +0 -6
  67. data/lib/zakuro/era/gengou/set-001-until-south.yaml +0 -375
  68. data/lib/zakuro/era/gengou/set-002-from-north.yaml +0 -166
  69. data/lib/zakuro/era/gengou/set-003-modern.yaml +0 -12
  70. data/lib/zakuro/era/japan.rb +0 -630
  71. data/lib/zakuro/output/result.rb +0 -219
  72. data/lib/zakuro/version/senmyou/base/gengou.rb +0 -210
  73. data/lib/zakuro/version/senmyou/summary/gengou_data.rb +0 -294
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ require_relative './core'
6
+ require_relative './data'
7
+ require_relative './operation'
8
+
9
+ # :nodoc:
10
+ module Zakuro
11
+ #
12
+ # Result 演算結果
13
+ #
14
+ module Result
15
+ #
16
+ # Single 1日検索結果
17
+ #
18
+ class Single < Core
19
+ # @return [Data::SingleDay] 1日
20
+ attr_reader :data
21
+ # @return [Operation::Bundle] 運用情報
22
+ attr_reader :operation
23
+
24
+ #
25
+ # 初期化
26
+ #
27
+ # @param [Data::SingleDay] data 1日
28
+ # @param [Operation::Bundle] operation 運用情報
29
+ #
30
+ def initialize(data:, operation:)
31
+ super
32
+ @data = data
33
+ @operation = operation
34
+ end
35
+ end
36
+ end
37
+ end
@@ -1,11 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative './typeof'
4
+
3
5
  # :nodoc:
4
6
  module Zakuro
5
7
  #
6
- # Result 演算結果
8
+ # Tools 汎用メソッド群
7
9
  #
8
- module Result
10
+ module Tools
9
11
  #
10
12
  # Stringifier 文字列処理
11
13
  #
@@ -18,16 +20,18 @@ module Zakuro
18
20
  #
19
21
  # @return [Hash<String, Objcet>] ハッシュ
20
22
  #
21
- def self.to_h(obj:, class_prefix:)
23
+ def self.to_h(obj:, class_prefix:, formatted: true)
22
24
  hash = {}
23
25
  obj.instance_variables.each do |var|
24
26
  key = var.to_s.delete('@')
25
- hash[key] = value_to_hash(obj: obj.instance_variable_get(var), class_prefix: class_prefix)
27
+ hash[key] = value_to_hash(
28
+ obj: obj.instance_variable_get(var), class_prefix: class_prefix, formatted: formatted
29
+ )
26
30
  end
27
31
  hash
28
32
  end
29
33
 
30
- # :reek:TooManyStatements { max_statements: 7 } and :reek:NilCheck
34
+ # :reek:TooManyStatements { max_statements: 7 }
31
35
 
32
36
  #
33
37
  # 対象インスタンスをハッシュ化する(再帰処理)
@@ -37,19 +41,22 @@ module Zakuro
37
41
  #
38
42
  # @return [Hash<String, Objcet>] ハッシュ
39
43
  #
40
- def self.value_to_hash(obj:, class_prefix:)
41
- return obj if obj.nil?
44
+ def self.value_to_hash(obj:, class_prefix:, formatted:)
45
+ return obj unless obj
46
+
47
+ # 日付をフォーマットする
48
+ return obj.format if formatted && Tools::Typeof.time?(obj: obj)
42
49
 
43
50
  # 同じモジュール内のオブジェクトは再帰する
44
51
  if obj.class.name.start_with?(class_prefix)
45
- return to_h(obj: obj, class_prefix: class_prefix)
52
+ return to_h(obj: obj, class_prefix: class_prefix, formatted: formatted)
46
53
  end
47
54
 
48
55
  # 配列は要素一つずつで再帰する
49
56
  if obj.is_a?(Array)
50
57
  arr = []
51
58
  obj.each do |item|
52
- arr.push(to_h(obj: item, class_prefix: class_prefix))
59
+ arr.push(to_h(obj: item, class_prefix: class_prefix, formatted: formatted))
53
60
  end
54
61
  return arr
55
62
  end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../cycle/abstract_remainder'
4
+ require_relative '../era/western'
5
+
6
+ # :nodoc:
7
+ module Zakuro
8
+ #
9
+ # Tools 汎用メソッド群
10
+ #
11
+ module Tools
12
+ #
13
+ # Typeof 型判定
14
+ #
15
+ module Typeof
16
+ #
17
+ # 時間を表す型か
18
+ #
19
+ # @param [Object] obj 引数
20
+ #
21
+ # @return [True] 時間型である
22
+ # @return [False] 時間型ではない
23
+ #
24
+ def self.time?(obj:)
25
+ return true if obj.is_a?(Western::Calendar)
26
+
27
+ return true if obj.is_a?(Cycle::AbstractRemainder)
28
+
29
+ false
30
+ end
31
+ end
32
+ end
33
+ end
@@ -3,5 +3,5 @@
3
3
  # :nodoc:
4
4
  module Zakuro
5
5
  # @return [String] library version
6
- VERSION = '0.0.0'
6
+ VERSION = '0.1.1'
7
7
  end
@@ -1,6 +1,6 @@
1
1
  # 宣明暦
2
2
 
3
- 貞観4年1月1日(859/02/07)-貞享2年12月29日(1686/01/23
3
+ 貞観4年1月1日(862/02/03)-貞享1年12月30日(1685/02/03
4
4
 
5
5
  # 著者
6
6
 
@@ -100,6 +100,8 @@
100
100
 
101
101
  日本の旧暦(太陰太陽暦)において、元号は1月1日を境に改元または継続する
102
102
 
103
+ NOTE: これは『日本暦日原典』をベースにした場合であり、多くの場合、実際の改元は1月1日ではない [返却される元号が実際の存在期間と一致しない](https://github.com/pldb/zakuro/issues/3)
104
+
103
105
  ここで問題となるのは、元号2年目以降はその前年までの計算結果が必要になることである
104
106
 
105
107
  西暦(太陽暦)のように1年あたりの日数は一定しない
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative '../../../era/japan'
3
+ require_relative '../../../era/japan/gengou'
4
4
  require_relative '../../../era/western'
5
5
  require_relative '../../../cycle/zodiac'
6
6
 
@@ -12,6 +12,8 @@ module Zakuro
12
12
  # Era 宣明暦時代
13
13
  #
14
14
  module Era
15
+ # FIXME: JOUGAN_START_DATE は不要。'貞観' かどうかだけで良い
16
+
15
17
  # @return [Western::Calendar] 貞観1年1月1日
16
18
  JOUGAN_START_DATE = Western::Calendar.new(year: 859, month: 2, day: 7)
17
19
  # @return [Western::Calendar] 貞観4年1月1日
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../../era/japan/gengou'
4
+ require_relative '../../../era/western'
5
+
6
+ # :nodoc:
7
+ module Zakuro
8
+ # :nodoc:
9
+ module Senmyou
10
+ #
11
+ # MultiGengou 複数元号
12
+ #
13
+ class MultiGengou
14
+ # @return [Japan::Gengou] 元号(1行目)
15
+ attr_reader :first_line
16
+ # @return [Japan::Gengou] 元号(2行目)
17
+ attr_reader :second_line
18
+ # @return [Western::Calendar] 元旦
19
+ attr_reader :new_year_date
20
+
21
+ def initialize(first_line: Japan::Gengou.new, second_line: Japan::Gengou.new,
22
+ new_year_date: Western::Calendar.new)
23
+ @first_line = first_line
24
+ @second_line = second_line
25
+ @new_year_date = new_year_date
26
+ end
27
+
28
+ # :reek:TooManyStatements { max_statements: 7 }
29
+
30
+ #
31
+ # 改元する
32
+ #
33
+ # @param [Japan::Gengou] first_line 元号(1行目)
34
+ # @param [Japan::Gengou] second_line 元号(2行目)
35
+ #
36
+ # @return [MultiGengou] 自身
37
+ #
38
+ def transfer(first_line: Japan::Gengou.new, second_line: Japan::Gengou.new)
39
+ cloned_first_line = first_line.clone
40
+ cloned_second_line = second_line.clone
41
+
42
+ if integrated?(first_line: cloned_first_line, second_line: cloned_second_line)
43
+ @first_line = @second_line.clone
44
+ @second_line = cloned_second_line
45
+ end
46
+
47
+ @first_line = cloned_first_line if @first_line.name != first_line.name
48
+ @second_line = cloned_second_line if @second_line.name != second_line.name
49
+
50
+ self
51
+ end
52
+
53
+ #
54
+ # 次年にする
55
+ #
56
+ # @param [Japan::Gengou] first_line 元号(1行目)
57
+ # @param [Japan::Gengou] second_line 元号(2行目)
58
+ #
59
+ # @return [MultiGengou] 自身
60
+ #
61
+ def next_year
62
+ @first_line.next_year
63
+ @second_line.next_year
64
+
65
+ self
66
+ end
67
+
68
+ #
69
+ # ディープコピー
70
+ #
71
+ # @param [MultiGengou] obj 自身
72
+ #
73
+ def initialize_copy(obj)
74
+ @first_line = obj.first_line.clone
75
+ @second_line = obj.second_line.clone
76
+ end
77
+
78
+ private
79
+
80
+ #
81
+ # 複数元号を統一するかどうか
82
+ #
83
+ # @param [Japan::Gengou] first_line 元号(1行目)
84
+ # @param [Japan::Gengou] second_line 元号(2行目)
85
+ #
86
+ # @return [True] 統一する
87
+ # @return [False] 統一しない
88
+ #
89
+ def integrated?(first_line: Japan::Gengou.new, second_line: Japan::Gengou.new)
90
+ return false if @second_line.name != first_line.name
91
+
92
+ return false unless second_line.invalid?
93
+
94
+ true
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,217 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './era'
4
+ require_relative './multi_gengou'
5
+
6
+ require_relative '../../../era/japan/gengou'
7
+
8
+ # :nodoc:
9
+ module Zakuro
10
+ # :nodoc:
11
+ module Senmyou
12
+ # FIXME: 宣明暦に依存しない共通処理にする
13
+
14
+ #
15
+ # MultiGengouRoller 改元処理
16
+ #
17
+ class MultiGengouRoller
18
+ # @return [MultiGengou] 複数元号
19
+ attr_reader :multi_gengou
20
+ # @return [Western::Calendar] 元旦(元号が2つある場合は再過去の日付になる)
21
+ attr_reader :oldest_date
22
+ # @return [Western::Calendar] 元号内での最未来日(元号が2つある場合は再未来の日付になる)
23
+ attr_reader :newest_date
24
+ # @return [Western::Calendar] 現在日
25
+ attr_reader :current_date
26
+
27
+ def initialize(start_date: Era::START_DATE, end_date: Western::Calendar.new)
28
+ end_date = start_date if end_date.invalid?
29
+
30
+ @oldest_date = MultiGengouRoller.choise_oldest_gengou_date(
31
+ first_line: Era.first(start_date: start_date),
32
+ second_line: Era.second(start_date: start_date)
33
+ )
34
+ @current_date = @oldest_date.clone
35
+ @newest_date = MultiGengouRoller.choise_newest_gengou_date(
36
+ first_line: Era.first(start_date: end_date),
37
+ second_line: Era.second(start_date: end_date)
38
+ )
39
+
40
+ @multi_gengou = MultiGengou.new(
41
+ first_line: current_first_line,
42
+ second_line: current_second_line,
43
+ new_year_date: @oldest_date
44
+ )
45
+ end
46
+
47
+ #
48
+ # 現在日付を未来に進める
49
+ #
50
+ # @param [<Type>] days <description>
51
+ #
52
+ # @return [<Type>] <description>
53
+ #
54
+ def next(days: 0)
55
+ @current_date += days
56
+ end
57
+
58
+ #
59
+ # 現在日から元号(1行目)を取得する
60
+ #
61
+ # @return [Japan::Gengou] 元号(1行目)
62
+ #
63
+ def current_first_line
64
+ MultiGengouRoller.first_line(date: @current_date)
65
+ end
66
+
67
+ #
68
+ # 現在日から元号(2行目)を取得する
69
+ #
70
+ # @return [Japan::Gengou] 元号(2行目)
71
+ #
72
+ def current_second_line
73
+ MultiGengouRoller.second_line(date: @current_date)
74
+ end
75
+
76
+ #
77
+ # 改元する
78
+ #
79
+ # @return [MultiGengou] 複数元号
80
+ #
81
+ def transfer
82
+ MultiGengouRoller.transfer(multi_gengou: @multi_gengou, date: @current_date)
83
+ end
84
+
85
+ #
86
+ # 次年にする
87
+ #
88
+ # @return [MultiGengou] 複数元号
89
+ #
90
+ def next_year
91
+ @multi_gengou.next_year
92
+ end
93
+
94
+ #
95
+ # 元号(1行目)を取得する
96
+ #
97
+ # @return [Japan::Gengou] 元号(1行目)
98
+ #
99
+ def self.first_line(date: Western::Calender.new)
100
+ Era.first(start_date: date)
101
+ end
102
+
103
+ #
104
+ # 元号(2行目)を取得する
105
+ #
106
+ # @return [Japan::Gengou] 元号(2行目)
107
+ #
108
+ def self.second_line(date: Western::Calender.new)
109
+ Era.second(start_date: date)
110
+ end
111
+
112
+ #
113
+ # 改元する
114
+ #
115
+ # @param [MultiGengou] multi_gengou 複数元号
116
+ # @param [Western::Calendar] date 対象日
117
+ #
118
+ # @return [MultiGengou] 改元済み複数元号
119
+ #
120
+ def self.transfer(multi_gengou:, date:)
121
+ multi_gengou.transfer(
122
+ first_line: first_line(date: date),
123
+ second_line: second_line(date: date)
124
+ )
125
+
126
+ multi_gengou
127
+ end
128
+
129
+ #
130
+ # 現在日からみて直近の未来に対する元号の切替前日を求める
131
+ # @note 2つの元号が重複した場合はより過去の日となる
132
+ #
133
+ # @param [Japan::Gengou] first_line 元号(1行目)
134
+ # @param [Japan::Gengou] second_line 元号(2行目)
135
+ #
136
+ # @return [Western::Calendar] 元号の切替前日
137
+ #
138
+ def choise_nearest_end_date
139
+ condition = lambda do |first_date, second_date|
140
+ first_date < second_date ? first_date : second_date
141
+ end
142
+
143
+ second_line = current_second_line
144
+
145
+ MultiGengouRoller.choise_date(condition: condition, second_line: second_line,
146
+ first_date: current_first_line.end_date.clone,
147
+ second_date: second_line.end_date.clone)
148
+ end
149
+
150
+ #
151
+ # 最過去の元旦を求める
152
+ # @note 2つの元号が重複した場合はより過去の日となる
153
+ #
154
+ # @param [Japan::Gengou] first_line 元号(1行目)
155
+ # @param [Japan::Gengou] second_line 元号(2行目)
156
+ #
157
+ # @return [Western::Calendar] 最過去の元旦
158
+ #
159
+ def self.choise_oldest_gengou_date(first_line:, second_line:)
160
+ condition = lambda do |first_date, second_date|
161
+ first_date < second_date ? first_date : second_date
162
+ end
163
+ choise_date(condition: condition, second_line: second_line,
164
+ first_date: first_line.new_year_date.clone,
165
+ second_date: second_line.new_year_date.clone)
166
+ end
167
+
168
+ #
169
+ # 元号内での最未来日を求める
170
+ # @note 2つの元号が重複した場合はより未来の日となる
171
+ #
172
+ # @param [Japan::Gengou] first_line 元号(1行目)
173
+ # @param [Japan::Gengou] second_line 元号(2行目)
174
+ #
175
+ # @return [Western::Calendar] 最未来日
176
+ #
177
+ def self.choise_newest_gengou_date(first_line:, second_line:)
178
+ condition = lambda do |first_date, second_date|
179
+ first_date > second_date ? first_date : second_date
180
+ end
181
+ choise_date(condition: condition, second_line: second_line,
182
+ first_date: first_line.end_date.clone, second_date: second_line.end_date.clone)
183
+ end
184
+
185
+ # :reek:LongParameterList {max_params: 4}
186
+
187
+ #
188
+ # 条件を元に日付を求める
189
+ #
190
+ # @param [Proc] condition 比較条件
191
+ # @param [Japan::Gengou] second_line 元号(2行目)
192
+ # @param [Western::Calendar] first_date 比較対象(1行目)
193
+ # @param [Western::Calendar] second_date 比較対象(2行目)
194
+ #
195
+ # @return [Western::Calendar] 比較結果
196
+ #
197
+ def self.choise_date(condition:, second_line:, first_date:, second_date:)
198
+ # first_lineは常に存在する
199
+ return first_date if second_line.invalid?
200
+
201
+ condition.call(first_date, second_date)
202
+ end
203
+
204
+ #
205
+ # ディープコピー
206
+ #
207
+ # @param [MultiGengou] obj 自身
208
+ #
209
+ def initialize_copy(obj)
210
+ @oldest_date = obj.oldest_date.clone
211
+ @current_date = obj.current_date.clone
212
+ @newest_date = obj.newest_date.clone
213
+ @multi_gengou = obj.multi_gengou.clone
214
+ end
215
+ end
216
+ end
217
+ end