zakuro 0.0.1 → 0.0.2

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.
@@ -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