zakuro 0.0.0 → 0.1.1

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