zakuro 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,10 +3,26 @@ name: "近代(一世一元)"
3
3
  end_date: "9999-12-31"
4
4
  list:
5
5
  - name: "明治"
6
- start_date: "1868-1-25"
6
+ # 1年9月8日
7
+ start_year: 1
8
+ start_date: "1868-10-23"
9
+ new_year_date: "1868-1-25"
10
+ note: ""
7
11
  - name: "大正"
12
+ # 1年7月30日
13
+ start_year: 1
8
14
  start_date: "1912-7-30"
15
+ new_year_date: "1912-1-1"
16
+ note: ""
9
17
  - name: "昭和"
18
+ # 1年12月25日
19
+ start_year: 1
10
20
  start_date: "1926-12-25"
21
+ new_year_date: "1926-1-1"
22
+ note: ""
11
23
  - name: "令和"
12
- start_date: "2019-5-1"
24
+ # -
25
+ start_year: 1
26
+ start_date: "2019-5-1"
27
+ new_year_date: "2019-1-1"
28
+ note: ""
@@ -97,6 +97,8 @@ module Zakuro
97
97
  attr_reader :name
98
98
  # @return [Western::Calendar] 開始日
99
99
  attr_reader :start_date
100
+ # @return [Western::Calendar] 元旦
101
+ attr_reader :new_year_date
100
102
  # @return [Western::Calendar] 終了日
101
103
  attr_reader :end_date
102
104
  # @return [Integer] 元号年
@@ -105,15 +107,18 @@ module Zakuro
105
107
  #
106
108
  # 初期化
107
109
  #
108
- # @param [<Type>] name 元号名
109
- # @param [<Type>] start_date 開始日
110
- # @param [<Type>] end_date 終了日
111
- # @param [<Type>] year 元号年
110
+ # @param [String] name 元号名
111
+ # @param [Western::Calendar] start_date 開始日
112
+ # @param [Western::Calendar] new_year_date 元旦
113
+ # @param [Western::Calendar] end_date 終了日
114
+ # @param [Integer] year 元号年
112
115
  #
113
116
  def initialize(name: '', start_date: Western::Calendar.new,
117
+ new_year_date: Western::Calendar.new,
114
118
  end_date: Western::Calendar.new, year: -1)
115
119
  @name = name
116
120
  @start_date = start_date
121
+ @new_year_date = new_year_date
117
122
  @end_date = end_date
118
123
  @year = year
119
124
  end
@@ -185,9 +190,14 @@ module Zakuro
185
190
  # 1元号年を追加する
186
191
  #
187
192
  def next_year
188
- @year += 1
193
+ @year += 1 unless invalid?
189
194
  nil
190
195
  end
196
+
197
+ def to_s
198
+ "name: #{@name}, start_date: #{@start_date.format}, " \
199
+ "end_date: #{@end_date.format}, year: #{@year}"
200
+ end
191
201
  end
192
202
 
193
203
  #
@@ -269,6 +279,8 @@ module Zakuro
269
279
  attr_reader :name
270
280
  # @return [String] 開始日
271
281
  attr_reader :start_date
282
+ # @return [String] 元旦
283
+ attr_reader :new_year_date
272
284
  # @return [String] 開始年
273
285
  attr_reader :start_year
274
286
 
@@ -282,6 +294,7 @@ module Zakuro
282
294
  @index = index
283
295
  @name = hash['name']
284
296
  @start_date = hash['start_date']
297
+ @new_year_date = hash['new_year_date']
285
298
  @start_year = hash['start_year']
286
299
  end
287
300
 
@@ -298,9 +311,14 @@ module Zakuro
298
311
 
299
312
  failed.push(prefix + "invalid name. #{@name}") unless valid_name_type?
300
313
 
301
- failed.push(prefix + "invalid start_date. #{@start_date}") unless valid_date_type?
314
+ failed.push(prefix + "invalid start_date. #{@start_date}") unless valid_start_date_type?
302
315
 
303
316
  failed.push(prefix + "invalid start_year. #{@start_year}") unless valid_year_type?
317
+
318
+ unless valid_new_year_date_type?
319
+ failed.push(prefix + "invalid new_year_date. #{@new_year_date}")
320
+ end
321
+
304
322
  failed
305
323
  end
306
324
 
@@ -317,15 +335,25 @@ module Zakuro
317
335
  end
318
336
 
319
337
  #
320
- # 日付文字列を検証する
338
+ # 開始日文字列を検証する
321
339
  #
322
340
  # @return [True] 正しい
323
341
  # @return [False] 正しくない
324
342
  #
325
- def valid_date_type?
343
+ def valid_start_date_type?
326
344
  Western::Calendar.valid_date_string(str: @start_date)
327
345
  end
328
346
 
347
+ #
348
+ # 元旦文字列を検証する
349
+ #
350
+ # @return [True] 正しい
351
+ # @return [False] 正しくない
352
+ #
353
+ def valid_new_year_date_type?
354
+ Western::Calendar.valid_date_string(str: @new_year_date)
355
+ end
356
+
329
357
  # :reek:NilCheck
330
358
 
331
359
  #
@@ -349,9 +377,11 @@ module Zakuro
349
377
  #
350
378
  def create
351
379
  start_date = Western::Calendar.parse(str: @start_date)
380
+ new_year_date = Western::Calendar.parse(str: @new_year_date)
352
381
  start_year = @start_year.nil? ? 1 : @start_year
353
382
 
354
- Gengou.new(name: @name, start_date: start_date, year: start_year)
383
+ Gengou.new(name: @name, start_date: start_date, new_year_date: new_year_date,
384
+ year: start_year)
355
385
  end
356
386
  end
357
387
 
@@ -344,6 +344,16 @@ module Zakuro
344
344
  self
345
345
  end
346
346
 
347
+ #
348
+ # 無効値(引数なし)かどうかを検証する
349
+ #
350
+ # @return [True] 無効値
351
+ # @return [False] 無効値以外
352
+ #
353
+ def invalid?
354
+ (@date == Date.new)
355
+ end
356
+
347
357
  #
348
358
  # 年月日をフォーマット化する
349
359
  #
@@ -68,15 +68,15 @@ module Zakuro
68
68
  # @return [Result::Year] 年データ
69
69
  #
70
70
  def self.save_year(year:)
71
- gengou = year.gengou
72
- first = gengou.first_line
73
- second = gengou.second_line
71
+ multi_gengou = year.multi_gengou
72
+ first = multi_gengou.first_line
73
+ second = multi_gengou.second_line
74
74
  Result::Year.new(
75
75
  first_gengou:
76
76
  Result::Gengou.new(name: first.name, number: first.year),
77
77
  second_gengou:
78
78
  Result::Gengou.new(name: second.name, number: second.year),
79
- zodiac_name: gengou.zodiac_name, total_days: gengou.total_days
79
+ zodiac_name: year.zodiac_name, total_days: year.total_days
80
80
  )
81
81
  end
82
82
  private_class_method :save_year
@@ -3,5 +3,5 @@
3
3
  # :nodoc:
4
4
  module Zakuro
5
5
  # @return [String] library version
6
- VERSION = '0.0.1'
6
+ VERSION = '0.0.2'
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年あたりの日数は一定しない
@@ -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'
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,205 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './era'
4
+ require_relative './multi_gengou'
5
+
6
+ require_relative '../../../era/japan'
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
+ end
204
+ end
205
+ end