zakuro 0.0.3 → 0.1.0

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