zakuro 0.0.3 → 0.1.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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +85 -43
  3. data/doc/operation.md +25 -0
  4. data/doc/operation/csv/month.csv +202 -0
  5. data/doc/operation/operation.xlsx +0 -0
  6. data/doc/operation/transfer.rb +73 -0
  7. data/lib/zakuro/era/japan/gengou.rb +106 -0
  8. data/lib/zakuro/era/japan/gengou/parser.rb +169 -0
  9. data/lib/zakuro/era/japan/gengou/type.rb +178 -0
  10. data/lib/zakuro/era/japan/gengou/validator.rb +234 -0
  11. data/lib/zakuro/era/japan/reki.rb +91 -0
  12. data/lib/zakuro/era/{gengou → japan/yaml}/set-001-until-south.yaml +0 -0
  13. data/lib/zakuro/era/{gengou → japan/yaml}/set-002-from-north.yaml +0 -0
  14. data/lib/zakuro/era/{gengou → japan/yaml}/set-003-modern.yaml +0 -0
  15. data/lib/zakuro/era/western.rb +1 -1
  16. data/lib/zakuro/operation/month/parser.rb +277 -0
  17. data/lib/zakuro/operation/month/type.rb +452 -0
  18. data/lib/zakuro/operation/month/validator.rb +498 -0
  19. data/lib/zakuro/operation/operation.rb +45 -0
  20. data/lib/zakuro/operation/yaml/month.yaml +6452 -0
  21. data/lib/zakuro/output/error.rb +2 -0
  22. data/lib/zakuro/output/logger.rb +2 -0
  23. data/lib/zakuro/output/response.rb +17 -15
  24. data/lib/zakuro/result/core.rb +52 -0
  25. data/lib/zakuro/result/data.rb +187 -0
  26. data/lib/zakuro/result/operation.rb +86 -0
  27. data/lib/zakuro/result/result.rb +37 -0
  28. data/lib/zakuro/{output → tools}/stringifier.rb +14 -7
  29. data/lib/zakuro/tools/typeof.rb +33 -0
  30. data/lib/zakuro/version.rb +1 -1
  31. data/lib/zakuro/version/senmyou/base/era.rb +1 -1
  32. data/lib/zakuro/version/senmyou/base/multi_gengou.rb +1 -1
  33. data/lib/zakuro/version/senmyou/base/multi_gengou_roller.rb +13 -1
  34. data/lib/zakuro/version/senmyou/base/solar_term.rb +10 -0
  35. data/lib/zakuro/version/senmyou/monthly/first_day.rb +44 -0
  36. data/lib/zakuro/version/senmyou/monthly/initialized_month.rb +48 -0
  37. data/lib/zakuro/version/senmyou/monthly/month.rb +127 -68
  38. data/lib/zakuro/version/senmyou/monthly/month_label.rb +87 -0
  39. data/lib/zakuro/version/senmyou/monthly/operated_month.rb +167 -0
  40. data/lib/zakuro/version/senmyou/{summary → range}/annual_range.rb +20 -23
  41. data/lib/zakuro/version/senmyou/{summary → range}/full_range.rb +102 -2
  42. data/lib/zakuro/version/senmyou/range/operated_range.rb +105 -0
  43. data/lib/zakuro/version/senmyou/range/operated_solar_terms.rb +163 -0
  44. data/lib/zakuro/version/senmyou/senmyou.rb +2 -2
  45. data/lib/zakuro/version/senmyou/{summary/specifier.rb → specifier/single_day_specifier.rb} +13 -14
  46. data/lib/zakuro/version/senmyou/stella/solar_average.rb +3 -7
  47. data/lib/zakuro/version/senmyou/summary/single.rb +71 -0
  48. data/lib/zakuro/version_factory.rb +1 -1
  49. metadata +35 -11
  50. data/lib/zakuro/era/japan.rb +0 -664
  51. data/lib/zakuro/output/result.rb +0 -225
@@ -1,664 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative './western'
4
- require 'yaml'
5
-
6
- # :nodoc:
7
- module Zakuro
8
- #
9
- # Japan 和暦
10
- #
11
- module Japan
12
- #
13
- # Reki 暦
14
- #
15
- module Reki
16
- #
17
- # Range 暦(範囲)
18
- #
19
- class Range
20
- # @return [String] 暦のクラス名
21
- # version 以下を参照
22
- attr_reader :class_name
23
- # @return [Western::Calendar] 暦の開始日
24
- attr_reader :start_date
25
-
26
- #
27
- # 初期化
28
- #
29
- # @param [String] class_name 暦のクラス名
30
- # @param [Western::Calendar] start_date 暦の開始日
31
- #
32
- def initialize(class_name:, start_date:)
33
- @class_name = class_name
34
- @start_date = start_date
35
- end
36
- end
37
-
38
- LIST = [
39
- Range.new(
40
- class_name: 'Zakuro::Genka::Gateway',
41
- start_date: Western::Calendar.new(year: 445, month: 1, day: 24)
42
- ),
43
- Range.new(
44
- class_name: 'Zakuro::Gihou::Gateway',
45
- start_date: Western::Calendar.new(year: 698, month: 2, day: 16)
46
- ),
47
- Range.new(
48
- class_name: 'Zakuro::Taien::Gateway',
49
- start_date: Western::Calendar.new(year: 764, month: 2, day: 7)
50
- ),
51
- Range.new(
52
- class_name: 'Zakuro::Senmyou::Gateway',
53
- start_date: Western::Calendar.new(year: 862, month: 2, day: 3)
54
- ),
55
- Range.new(
56
- class_name: 'Zakuro::Joukyou::Gateway',
57
- start_date: Western::Calendar.new(year: 1685, month: 2, day: 4)
58
- ),
59
- Range.new(
60
- class_name: 'Zakuro::Houryaku::Gateway',
61
- start_date: Western::Calendar.new(year: 1755, month: 2, day: 11)
62
- ),
63
- Range.new(
64
- class_name: 'Zakuro::Kansei::Gateway',
65
- start_date: Western::Calendar.new(year: 1798, month: 2, day: 16)
66
- ),
67
- Range.new(
68
- class_name: 'Zakuro::Tenpou::Gateway',
69
- start_date: Western::Calendar.new(year: 1844, month: 2, day: 18)
70
- ),
71
- Range.new(
72
- class_name: 'Zakuro::Gregorio::Gateway',
73
- start_date: Western::Calendar.new(year: 1872, month: 12, day: 9)
74
- )
75
- ].freeze
76
-
77
- #
78
- # 指定した日付から対象の暦を引き当てる
79
- #
80
- # @param [Western::Calendar] date 日付
81
- #
82
- # @return [String] 暦のクラス名
83
- #
84
- def self.class_name(date: Western::Calendar.new)
85
- LIST.reverse_each do |range|
86
- return range.class_name if date >= range.start_date
87
- end
88
- raise ArgumentError, "invalid date: #{date.format}"
89
- end
90
- end
91
-
92
- # :reek:TooManyInstanceVariables { max_instance_variables: 5 }
93
-
94
- #
95
- # Gengou 元号情報
96
- #
97
- class Gengou
98
- # @return [String] 元号名
99
- attr_reader :name
100
- # @return [Western::Calendar] 開始日
101
- attr_reader :start_date
102
- # @return [Western::Calendar] 元旦
103
- attr_reader :new_year_date
104
- # @return [Western::Calendar] 終了日
105
- attr_reader :end_date
106
- # @return [Integer] 元号年
107
- attr_reader :year
108
-
109
- #
110
- # 初期化
111
- #
112
- # @param [String] name 元号名
113
- # @param [Western::Calendar] start_date 開始日
114
- # @param [Western::Calendar] new_year_date 元旦
115
- # @param [Western::Calendar] end_date 終了日
116
- # @param [Integer] year 元号年
117
- #
118
- def initialize(name: '', start_date: Western::Calendar.new,
119
- new_year_date: Western::Calendar.new,
120
- end_date: Western::Calendar.new, year: -1)
121
- @name = name
122
- @start_date = start_date
123
- @new_year_date = new_year_date
124
- @end_date = end_date
125
- @year = year
126
- end
127
-
128
- #
129
- # 終了日を更新する
130
- #
131
- # @param [Western::Calendar] end_date 終了日
132
- #
133
- def write_end_date(end_date:)
134
- unless Gengou.valid_date(date: end_date)
135
- raise ArgumentError, "invalid date format. [#{end_date}]"
136
- end
137
-
138
- @end_date = end_date
139
- nil
140
- end
141
-
142
- # :reek:NilCheck
143
-
144
- #
145
- # 日付が有効かどうかを確認する
146
- #
147
- # @param [Western::Calendar] date 日付
148
- #
149
- # @return [True] 有効
150
- # @return [False] 無効
151
- #
152
- def self.valid_date(date:)
153
- !date.nil? && date.is_a?(Western::Calendar)
154
- end
155
-
156
- #
157
- # 次の元号の開始日から、元号の終了日に変換する
158
- #
159
- # @param [String] next_start_date_string 次回開始日
160
- #
161
- def convert_next_start_date_to_end_date(next_start_date_string: '')
162
- raise ArgumentError, 'empty string cannot convert' if next_start_date_string.empty?
163
-
164
- start_date = Western::Calendar.parse(str: next_start_date_string)
165
- @end_date = start_date - 1
166
- nil
167
- end
168
-
169
- #
170
- # 指定した日が元号に含まれるか
171
- #
172
- # @param [Western::Calendar] date 日
173
- #
174
- # @return [True] 含まれる
175
- # @return [False] 含まれない
176
- #
177
- def include?(date:)
178
- date >= @start_date && date <= @end_date
179
- end
180
-
181
- #
182
- # 不正な元号データかを確認する
183
- #
184
- # @return [True] 正しくない
185
- # @return [True] 正しい
186
- #
187
- def invalid?
188
- @year == -1
189
- end
190
-
191
- #
192
- # 1元号年を追加する
193
- #
194
- def next_year
195
- @year += 1 unless invalid?
196
- nil
197
- end
198
-
199
- def to_s
200
- "name: #{@name}, start_date: #{@start_date.format}, " \
201
- "end_date: #{@end_date.format}, year: #{@year}"
202
- end
203
- end
204
-
205
- #
206
- # Set 元号セット
207
- #
208
- class Set
209
- # @return [Integer] 元号セットID
210
- attr_reader :id
211
- # @return [String] 元号セット名
212
- attr_reader :name
213
- # @return [Western::Calendar] 元号セットでの終了日
214
- attr_reader :end_date
215
- # @return [Array<Gengou>] 元号リスト
216
- attr_reader :list
217
-
218
- #
219
- # 初期化
220
- #
221
- # @param [Integer] id 元号セットID
222
- # @param [String] name 元号セット名
223
- # @param [Western::Calendar] end_date 元号セットでの終了日
224
- # @param [Array<Gengou>] list 元号リスト
225
- #
226
- def initialize(id: -1, name: '', end_date: Western::Calendar.new, list: [])
227
- @id = id
228
- @name = name
229
- @end_date = end_date
230
- @list = list
231
- end
232
-
233
- #
234
- # 指定した日付を含む元号を返す
235
- #
236
- # @param [Western::Calendar] date 日
237
- #
238
- # @return [Gengou] 元号
239
- #
240
- def include_item(date:)
241
- @list.each do |item|
242
- return item if item.include?(date: date)
243
- end
244
-
245
- Gengou.new
246
- end
247
-
248
- #
249
- # 元号セットが不正かどうかを確認する
250
- #
251
- # @return [True] 正しくない
252
- # @return [False] 正しい
253
- #
254
- def invalid?
255
- @id == -1
256
- end
257
- end
258
-
259
- #
260
- # Parser yaml解析
261
- #
262
- module Parser
263
- #
264
- # 検証する
265
- #
266
- # @param [Hash<String, Object>] yaml_hash yaml取得結果
267
- #
268
- # @return [Array<String>] 不正メッセージ
269
- #
270
- def self.validate(yaml_hash)
271
- SetParser.new(hash: yaml_hash).validate
272
- end
273
-
274
- # :reek:TooManyInstanceVariables { max_instance_variables: 5 }
275
-
276
- #
277
- # GengouParser 元号情報の検証/展開を行う
278
- #
279
- class GengouParser
280
- # @return [Integer] 要素位置
281
- attr_reader :index
282
- # @return [String] 元号名
283
- attr_reader :name
284
- # @return [String] 開始日
285
- attr_reader :start_date
286
- # @return [String] 元旦
287
- attr_reader :new_year_date
288
- # @return [String] 開始年
289
- attr_reader :start_year
290
-
291
- #
292
- # 初期化
293
- #
294
- # @param [Hash<String, Strin>] hash 元号情報
295
- # @param [Integer] index (元号セット内での)元号の要素位置
296
- #
297
- def initialize(hash:, index:)
298
- @index = index
299
- @name = hash['name']
300
- @start_date = hash['start_date']
301
- @new_year_date = hash['new_year_date']
302
- @start_year = hash['start_year']
303
- end
304
-
305
- # :reek:TooManyStatements { max_statements: 7 }
306
-
307
- #
308
- # 検証する
309
- #
310
- # @return [Array<String>] 不正メッセージ
311
- #
312
- def validate
313
- prefix = "list[#{index}]. "
314
- failed = []
315
-
316
- failed.push(prefix + "invalid name. #{@name}") unless valid_name_type?
317
-
318
- failed.push(prefix + "invalid start_date. #{@start_date}") unless valid_start_date_type?
319
-
320
- failed.push(prefix + "invalid start_year. #{@start_year}") unless valid_year_type?
321
-
322
- unless valid_new_year_date_type?
323
- failed.push(prefix + "invalid new_year_date. #{@new_year_date}")
324
- end
325
-
326
- failed
327
- end
328
-
329
- # :reek:NilCheck
330
-
331
- #
332
- # 元号名を検証する
333
- #
334
- # @return [True] 正しい
335
- # @return [False] 正しくない
336
- #
337
- def valid_name_type?
338
- !(@name.nil? || !@name.is_a?(String))
339
- end
340
-
341
- #
342
- # 開始日文字列を検証する
343
- #
344
- # @return [True] 正しい
345
- # @return [False] 正しくない
346
- #
347
- def valid_start_date_type?
348
- Western::Calendar.valid_date_string(str: @start_date)
349
- end
350
-
351
- #
352
- # 元旦文字列を検証する
353
- #
354
- # @return [True] 正しい
355
- # @return [False] 正しくない
356
- #
357
- def valid_new_year_date_type?
358
- Western::Calendar.valid_date_string(str: @new_year_date)
359
- end
360
-
361
- # :reek:NilCheck
362
-
363
- #
364
- # 元号年を検証する
365
- #
366
- # @return [True] 正しい
367
- # @return [False] 正しくない
368
- #
369
- def valid_year_type?
370
- return true if @start_year.nil?
371
-
372
- @start_year.is_a?(Integer)
373
- end
374
-
375
- # :reek:NilCheck
376
-
377
- #
378
- # 元号情報を生成する
379
- #
380
- # @return [Gengou] 元号情報
381
- #
382
- def create
383
- start_date = Western::Calendar.parse(str: @start_date)
384
- new_year_date = Western::Calendar.parse(str: @new_year_date)
385
- start_year = @start_year.nil? ? 1 : @start_year
386
-
387
- Gengou.new(name: @name, start_date: start_date, new_year_date: new_year_date,
388
- year: start_year)
389
- end
390
- end
391
-
392
- #
393
- # SetParser 元号セット情報の検証/展開
394
- #
395
- class SetParser
396
- # @return [String] 元号セットID
397
- attr_reader :id
398
- # @return [String] 元号セット名
399
- attr_reader :name
400
- # @return [String] 終了日
401
- attr_reader :end_date
402
- # @return [Array<Hash<String, String>>] 元号情報
403
- attr_reader :list
404
-
405
- #
406
- # 初期化
407
- #
408
- # @param [Hash<String, Object>] hash 元号セット情報
409
- #
410
- def initialize(hash:)
411
- @id = hash['id']
412
- @name = hash['name']
413
- @end_date = hash['end_date']
414
- @list = hash['list']
415
- end
416
-
417
- # :reek:TooManyStatements { max_statements: 6 }
418
-
419
- #
420
- # 検証する
421
- #
422
- # @return [Array<String>] 不正メッセージ
423
- #
424
- def validate
425
- failed = []
426
- failed.push("invalid id. #{id}") unless valid_id_type?
427
-
428
- failed.push("invalid name. #{name}") unless valid_name_type?
429
-
430
- failed.push("invalid end_date. #{end_date}") unless valid_date_type?
431
-
432
- failed |= validate_list
433
- failed
434
- end
435
-
436
- # :reek:NilCheck
437
-
438
- #
439
- # IDを検証する
440
- #
441
- # @return [True] 正しい
442
- # @return [False] 正しくない
443
- #
444
- def valid_id_type?
445
- !(@id.nil? || !@id.is_a?(Integer))
446
- end
447
-
448
- #
449
- # 元号セット名を検証する
450
- #
451
- # @return [True] 正しい
452
- # @return [False] 正しくない
453
- #
454
- def valid_name_type?
455
- !(@name.nil? || !@name.is_a?(String))
456
- end
457
-
458
- #
459
- # 日付文字列を検証する
460
- #
461
- # @return [True] 正しい
462
- # @return [False] 正しくない
463
- #
464
- def valid_date_type?
465
- Western::Calendar.valid_date_string(str: @end_date)
466
- end
467
-
468
- # :reek:NilCheck
469
-
470
- #
471
- # 元号情報を検証する
472
- #
473
- # @return [True] 正しい
474
- # @return [False] 正しくない
475
- #
476
- def valid_list_type?
477
- (!@list.nil? || @list.is_a?(Array))
478
- end
479
-
480
- #
481
- # 元号情報を検証する
482
- #
483
- # @return [True] 正しい
484
- # @return [False] 正しくない
485
- #
486
- def validate_list
487
- return ["invalid list. #{@list.class}"] unless valid_list_type?
488
-
489
- failed = []
490
- list.each_with_index do |li, index|
491
- failed |= GengouParser.new(hash: li, index: index).validate
492
- end
493
- failed
494
- end
495
-
496
- #
497
- # 元号セット情報を生成する
498
- #
499
- # @return [Set] 元号セット情報
500
- #
501
- def create
502
- end_date = Western::Calendar.parse(str: @end_date)
503
- list = create_list
504
- Set.new(
505
- id: @id, name: @name, end_date: end_date, list: list
506
- )
507
- end
508
-
509
- # :reek:TooManyStatements { max_statements: 7 }
510
-
511
- #
512
- # 元号情報を生成する
513
- #
514
- # @return [Array<Gengou>] 元号情報
515
- #
516
- def create_list
517
- result = []
518
- @list.each_with_index do |li, index|
519
- gengou = GengouParser.new(hash: li, index: index).create
520
- next_index = index + 1
521
- gengou = calc_end_date_on_gengou_data(next_index: next_index,
522
- gengou: gengou)
523
- result.push(gengou)
524
- end
525
-
526
- result
527
- end
528
-
529
- # :reek:TooManyStatements { max_statements: 6 }
530
-
531
- #
532
- # 次の元号の開始日から、元号の終了日に変換する
533
- #
534
- # @param [Integer] next_index 次の元号の要素位置
535
- # @param [String] gengou 次回開始日
536
- #
537
- # @return [Gengou] 元号情報
538
- #
539
- def calc_end_date_on_gengou_data(next_index:, gengou:)
540
- if next_index >= @list.size
541
- end_date = Western::Calendar.parse(str: @end_date)
542
- gengou.write_end_date(end_date: end_date)
543
- return gengou
544
- end
545
- next_start_date = @list[next_index]['start_date']
546
- gengou.convert_next_start_date_to_end_date(
547
- next_start_date_string: next_start_date
548
- )
549
- gengou
550
- end
551
- end
552
-
553
- #
554
- # 解析/展開する
555
- #
556
- # @param [String] filepath 元号セットファイルパス
557
- #
558
- # @return [Set] 元号セット情報
559
- #
560
- def self.parse(filepath: '')
561
- yaml = YAML.load_file(filepath)
562
-
563
- parser = SetParser.new(hash: yaml)
564
- failed = parser.validate
565
- raise YAML::ParseError, failed.join('\n') unless failed.empty?
566
-
567
- parser.create
568
- end
569
- end
570
-
571
- #
572
- # GengouResource 元号情報
573
- #
574
- module GengouResource
575
- # @return [Array<Set>] 元号セット情報リスト
576
- LIST = [
577
- Parser.parse(filepath: File.expand_path(
578
- './gengou/set-001-until-south.yaml',
579
- __dir__
580
- )),
581
- Parser.parse(filepath: File.expand_path(
582
- './gengou/set-002-from-north.yaml',
583
- __dir__
584
- )),
585
- Parser.parse(filepath: File.expand_path(
586
- './gengou/set-003-modern.yaml',
587
- __dir__
588
- ))
589
- ].freeze
590
-
591
- # :reek:TooManyStatements { max_statements: 9 }
592
-
593
- #
594
- # 元号(1行目,2行目)を引き当てる
595
- #
596
- # * LINE配列の元号情報を配列順で「x行目」(1始まり)とする
597
- # * 1行目にデータがあれば、第一要素に1行目のデータが設定される
598
- # * 1行目と2行目にデータがあれば、第二要素に2行目のデータが設定される
599
- # * 1行目にデータがなく、2行目以降に1つだけデータがあれば、第一要素にそのデータを設定してそれ以外の要素は未設定
600
- # * 1行目にデータがなく、2行目以降に2つ以上のデータがあれば、第一要素に末尾行に一番近いデータを設定してそれ以外の要素は未設定
601
- #
602
- # @param [Western::Calendar] date 日
603
- #
604
- # @return [Array<Gengou>] 元号情報(1行目, 2行目)
605
- #
606
- def self.lines(date:)
607
- lines = native_lines(date: date)
608
- return lines unless lines[0].invalid?
609
-
610
- first = Japan::Gengou.new
611
- lines[1..].each.with_index(1) do |item, index|
612
- next if item.invalid?
613
-
614
- first = item
615
- lines[index] = Japan::Gengou.new
616
- end
617
- lines[0] = first
618
- lines
619
- end
620
-
621
- #
622
- # 元号を引き当てる
623
- #
624
- # * LISTから単純に元号を引き当てる
625
- # * 1行目,2行目といった概念は無視する
626
- #
627
- # @param [Western::Calendar] date 日
628
- #
629
- # @return [Array<Gengou>] 元号情報
630
- #
631
- def self.native_lines(date:)
632
- result = Array.new(LIST.size)
633
- LIST.each_with_index do |set, index|
634
- result[index] = set.include_item(date: date)
635
- end
636
- result
637
- end
638
-
639
- #
640
- # 「日本暦日原典」1行目の元号を返す
641
- #
642
- # @param [Western::Calendar] date 日
643
- #
644
- # @return [Gengou] 元号情報(1行目)
645
- #
646
- def self.first_line(date:)
647
- lines = lines(date: date)
648
- lines[0].clone
649
- end
650
-
651
- #
652
- # 「日本暦日原典」2行目の元号を返す
653
- #
654
- # @param [Western::Calendar] date 日
655
- #
656
- # @return [Gengou] 元号情報(2行目)
657
- #
658
- def self.second_line(date:)
659
- lines = lines(date: date)
660
- lines[1].clone
661
- end
662
- end
663
- end
664
- end