when_exe 0.3.8 → 0.3.9

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 (49) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +210 -210
  3. data/lib/when_exe.rb +923 -919
  4. data/lib/when_exe/basictypes.rb +1 -1
  5. data/lib/when_exe/calendartypes.rb +4 -4
  6. data/lib/when_exe/coordinates.rb +5 -1
  7. data/lib/when_exe/ephemeris.rb +1 -1
  8. data/lib/when_exe/locales/locale.rb +3 -2
  9. data/lib/when_exe/region/bahai.rb +2 -2
  10. data/lib/when_exe/region/chinese.rb +1030 -1030
  11. data/lib/when_exe/region/chinese/epochs.rb +887 -919
  12. data/lib/when_exe/region/discordian.rb +5 -5
  13. data/lib/when_exe/region/east_asian.rb +256 -0
  14. data/lib/when_exe/region/french.rb +1 -1
  15. data/lib/when_exe/region/indian.rb +7 -7
  16. data/lib/when_exe/region/international_fixed.rb +2 -2
  17. data/lib/when_exe/region/iranian.rb +1 -1
  18. data/lib/when_exe/region/islamic.rb +102 -103
  19. data/lib/when_exe/region/japanese/epochs.rb +426 -426
  20. data/lib/when_exe/region/japanese/nihon_shoki.rb +46 -47
  21. data/lib/when_exe/region/japanese/notes.rb +1482 -1482
  22. data/lib/when_exe/region/japanese/twins.rb +3 -3
  23. data/lib/when_exe/region/japanese/weeks.rb +2 -2
  24. data/lib/when_exe/region/jewish.rb +5 -0
  25. data/lib/when_exe/region/korean.rb +209 -203
  26. data/lib/when_exe/region/positivist.rb +2 -2
  27. data/lib/when_exe/region/roman.rb +1 -1
  28. data/lib/when_exe/region/ryukyu.rb +50 -48
  29. data/lib/when_exe/region/shire.rb +2 -2
  30. data/lib/when_exe/region/thai.rb +1 -1
  31. data/lib/when_exe/region/tibetan.rb +15 -15
  32. data/lib/when_exe/region/tranquility.rb +2 -2
  33. data/lib/when_exe/region/vietnamese.rb +167 -167
  34. data/lib/when_exe/region/world.rb +3 -3
  35. data/lib/when_exe/region/world_season.rb +2 -2
  36. data/lib/when_exe/region/yerm.rb +4 -2
  37. data/lib/when_exe/region/zoroastrian.rb +1 -1
  38. data/lib/when_exe/tmreference.rb +140 -128
  39. data/lib/when_exe/version.rb +1 -1
  40. data/test/examples/Spatial.m17n +3 -3
  41. data/test/test.rb +2 -1
  42. data/test/test/coordinates.rb +2 -2
  43. data/test/test/region/chinese.rb +2 -2
  44. data/test/test/region/islamic.rb +38 -2
  45. data/test/test/region/japanese.rb +2 -2
  46. data/test/test/region/vietnamese.rb +2 -2
  47. data/test/test/region/yerm.rb +156 -146
  48. metadata +3 -3
  49. data/lib/when_exe/region/far_east.rb +0 -188
@@ -282,7 +282,7 @@ module When
282
282
  def _completion(digits, base)
283
283
  case digits
284
284
  when nil ; return nil
285
- when /\A\d{5}/ ; raise ArgumentError, "Wrong date format: #{digits}"
285
+ when /\A\d{5}/ ; raise ArgumentError, "Wrong date format: #{digits}" if base
286
286
  else ; return digits.to_i unless base
287
287
  end
288
288
 
@@ -1063,7 +1063,7 @@ module When::CalendarTypes
1063
1063
  #
1064
1064
  # 年初を太陽黄経または別の暦で決定する暦
1065
1065
  #
1066
- class YearLengthTableBased < TableBased
1066
+ class SolarYearTableBased < TableBased
1067
1067
 
1068
1068
  module CalendarBased
1069
1069
 
@@ -1125,7 +1125,7 @@ module When::CalendarTypes
1125
1125
 
1126
1126
  # オブジェクトの正規化
1127
1127
  #
1128
- # YearLengthTableBased オブジェクトの性質定義を初期設定します。
1128
+ # SolarYearTableBased オブジェクトの性質定義を初期設定します。
1129
1129
  #
1130
1130
  def _normalize(args=[], options={})
1131
1131
 
@@ -1138,7 +1138,7 @@ module When::CalendarTypes
1138
1138
  #
1139
1139
  # 年初を特定の日の日の出で決定する暦
1140
1140
  #
1141
- class TableBasedWithSunrise < YearLengthTableBased
1141
+ class SolarYearTableBasedWithSunrise < SolarYearTableBased
1142
1142
 
1143
1143
  # 年初の通日(天体暦使用)
1144
1144
  #
@@ -1158,7 +1158,7 @@ module When::CalendarTypes
1158
1158
  #
1159
1159
  # 年初を特定の日の日の入りで決定する暦
1160
1160
  #
1161
- class TableBasedWithSunset < YearLengthTableBased
1161
+ class SolarYearTableBasedWithSunset < SolarYearTableBased
1162
1162
 
1163
1163
  # 年初の通日(天体暦使用)
1164
1164
  #
@@ -1598,7 +1598,11 @@ module When::Coordinates
1598
1598
  instance_eval('class << self; attr_reader :formula; end') if @location && @border
1599
1599
  if respond_to?(:formula)
1600
1600
  extend When::Ephemeris::Formula::ForwardedFormula
1601
- @formula ||= When::Ephemeris::Formula.new(@location ? {:location=>@location} : {})
1601
+ unless @formula
1602
+ options = {:formula => kind_of?(When::CalendarTypes::SolarYearTableBased) ? '1S' : '1L'}
1603
+ options[:location] = @location if @location
1604
+ @formula = When::Ephemeris::Formula.new(options)
1605
+ end
1602
1606
  @formula = When.Resource(Array(@formula), '_ep:')
1603
1607
  end
1604
1608
  end
@@ -1597,7 +1597,7 @@ module When::Ephemeris
1597
1597
  @long, @lat, @alt = [@location.long / When::Coordinates::Spatial::DEGREE,
1598
1598
  @location.lat / When::Coordinates::Spatial::DEGREE,
1599
1599
  @location.alt] if @location
1600
- @formula ||= '1S'
1600
+ @formula ||= '1L'
1601
1601
  @time_standard ||= 'dynamical'
1602
1602
  @is_dynamical = (@time_standard[0..0].downcase == 'd')
1603
1603
 
@@ -36,7 +36,8 @@ module When
36
36
  '應'=>'応', '觀'=>'観', '龜'=>'亀', '齊'=>'斉',
37
37
  '靈'=>'霊', '攝'=>'摂', '壽'=>'寿', '萬'=>'万',
38
38
  '廢'=>'廃', '顯'=>'顕', '會'=>'会', '聰'=>'聡',
39
- '總'=>'総', '證'=>'証', '禮'=>'礼', ''=>''
39
+ '總'=>'総', '證'=>'証', '禮'=>'礼', ''=>'',
40
+ '竜'=>'龍'
40
41
  }
41
42
 
42
43
  # Escape
@@ -702,7 +703,7 @@ module When
702
703
  prefix = namespace[$1] || Locale.send(:_namespaces)[$1]
703
704
  ref.sub!(/\A.+:/, prefix) if prefix
704
705
  end
705
- ref += '%%<' + name + '>' if ref =~ /[\/#:]\z/
706
+ ref += name =~ /\A<.+>\z/ ? '%%' + name : '%%<' + name + '>' if ref =~ /[\/#:]\z/
706
707
  unless ref == ''
707
708
  @link[locale] = _encode(ref)
708
709
  # When.logger.info("%s[%s]->%s" % [@names[locale], locale, @link[locale]]) if When.logger
@@ -52,7 +52,7 @@ module When
52
52
  "names:[Bahai]",
53
53
 
54
54
  [Residue,
55
- "label:[YearName]", "divisor:19", "year:0", "format:[%1$s(%3$d)=]",
55
+ "label:[YearName=]", "divisor:19", "year:0", "format:[%1$s(%3$d)=]",
56
56
  [Residue, "label:[Alif=, ألف=, A= ]", "remainder: 0"],
57
57
  [Residue, "label:[Bá=, باء=, B= ]", "remainder: 1"],
58
58
  [Residue, "label:[Ab=, أب=, Father= ]", "remainder: 2"],
@@ -89,7 +89,7 @@ module When
89
89
  #
90
90
  # Bahá'í Calendar
91
91
  #
92
- Bahai = [TableBasedWithSunset, {
92
+ Bahai = [SolarYearTableBasedWithSunset, {
93
93
  'label' => 'Bahai::Bahai',
94
94
  'indices' => _Indices,
95
95
  'origin_of_MSC' => -1844 + 19*19,
@@ -1,1030 +1,1030 @@
1
- # -*- coding: utf-8 -*-
2
- =begin
3
- Copyright (C) 2011-2014 Takashi SUGA
4
-
5
- You may use and/or modify this file according to the license described in the LICENSE.txt file included in this archive.
6
- =end
7
-
8
- module When
9
-
10
- class BasicTypes::M17n
11
-
12
- Chinese = [self, [
13
- "locale:[=ja:, en=en:, alias]",
14
- "names:[Chinese=]",
15
- "[中国太陽暦(節月)=ja:%%<二十四節気>#%.<暦月と節月>, *ChineseSolar=en:Solar_term]",
16
- "[中国太陰太陽暦=ja:%%<中国暦>, *ChineseLuniSolar=en:Chinese_calendar]",
17
- "[彝暦=ja:%%<イ族>, *Yi=en:Yi_people]",
18
-
19
- [self,
20
- "names:[月=ja:%%<月_(暦)>, *Month]",
21
- "[正月, Month 1= ]",
22
- "[二月, Month 2= ]",
23
- "[三月, Month 3= ]",
24
- "[四月, Month 4= ]",
25
- "[五月, Month 5= ]",
26
- "[六月, Month 6= ]",
27
- "[七月, Month 7= ]",
28
- "[八月, Month 8= ]",
29
- "[九月, Month 9= ]",
30
- "[十月, Month 10=]",
31
- "[十一月, Month 11=]",
32
- "[十二月, Month 12=]"
33
- ],
34
-
35
- [self,
36
- "names:[月=ja:%%<月_(暦)>, *MonthA=en:Month]",
37
- "[一月, Month 1= ]",
38
- "[二月, Month 2= ]",
39
- "[三月, Month 3= ]",
40
- "[四月, Month 4= ]",
41
- "[五月, Month 5= ]",
42
- "[六月, Month 6= ]",
43
- "[七月, Month 7= ]",
44
- "[八月, Month 8= ]",
45
- "[九月, Month 9= ]",
46
- "[十月, Month 10=]",
47
- "[正月, New Year Month=]",
48
- "[臘月, Month 12=]"
49
- ],
50
-
51
- [self,
52
- "names:[月=ja:%%<月_(暦)>, *MonthB=en:Month]",
53
- "[建寅月, Month 3= ]",
54
- "[建卯月, Month 4= ]",
55
- "[建辰月, Month 5= ]",
56
- "[建巳月, Month 6= ]",
57
- "[建午月, Month 7= ]",
58
- "[建未月, Month 8= ]",
59
- "[建申月, Month 9= ]",
60
- "[建酉月, Month 10=]",
61
- "[建戌月, Month 11=]",
62
- "[建亥月, Month 12=]",
63
- "[建子月, Month 1= ]",
64
- "[建丑月, Month 2= ]"
65
- ]
66
- ]]
67
-
68
- Yi = [self, [
69
- "locale:[=ja:, en=en:, alias]",
70
- "names:[Yi=]",
71
-
72
- [self,
73
- "names:[月=ja:%%<月_(暦)>, *Month]",
74
- "[木公月, Month 1= ]",
75
- "[木母月, Month 2= ]",
76
- "[火公月, Month 3= ]",
77
- "[火母月, Month 4= ]",
78
- "[土公月, Month 5= ]",
79
- "[土母月, Month 6= ]",
80
- "[銅公月, Month 7= ]",
81
- "[銅母月, Month 8= ]",
82
- "[水公月, Month 9= ]",
83
- "[水母月, Month 10=]",
84
- "[過年日, end of year days=]"
85
- ]
86
- ]]
87
- end
88
-
89
- module Coordinates
90
-
91
- # Yi years
92
- Yi = [When::BasicTypes::M17n, [
93
- "locale:[=ja:, en=en:, alias]",
94
- "names:[Yi]",
95
-
96
- [Residue,
97
- "label:[YearName]", "divisor:8", "year:0",
98
- [Residue, "label:[東北之年=, NorthEastYear=]", "remainder: 0"],
99
- [Residue, "label:[東方之年=, EastYear= ]", "remainder: 1"],
100
- [Residue, "label:[東南之年=, SouthEastYear=]", "remainder: 2"],
101
- [Residue, "label:[南方之年=, SouthYear= ]", "remainder: 3"],
102
- [Residue, "label:[西南之年=, SouthWestYear=]", "remainder: 4"],
103
- [Residue, "label:[西方之年=, WestYear= ]", "remainder: 5"],
104
- [Residue, "label:[西北之年=, NorthWestYear=]", "remainder: 6"],
105
- [Residue, "label:[北方之年=, NorthYear= ]", "remainder: 7"]
106
- ]
107
- ]]
108
- end
109
-
110
- class CalendarNote
111
- Yis = [['Yi::YearName'], ['_m:Calendar::Month'], ['Common::Week']]
112
- end
113
-
114
- module Ephemeris
115
-
116
- #
117
- # Chinese Luni-Solar Calendar Formula for True Lunation Type
118
- #
119
- class ChineseTrueLunation < MeanLunation
120
-
121
- #
122
- # 唐代のアルゴリズム
123
- #
124
- # @private
125
- module TangMethods
126
-
127
- # 太陽の位置補正表
128
- # @return [Array<Array< 入気定日加減数, 朓朒数, 損益率, 損益率増分 >>]
129
- #attr_reader :s
130
-
131
- # 月の位置補正表
132
- # @return [Array<Array< 区間の時間/分, 損益率 >>]
133
- #attr_reader :m
134
-
135
- #
136
- # 立成の初期化
137
- #
138
- def _initialize_rissei
139
-
140
- # 近点月
141
- @anomalistic_month_length = @anomalistic_month_length.to_r
142
-
143
- # 計算式 C) のための繰り返し回数
144
- @repeat_count ||= @method.upcase == 'C' ? 2 : 1
145
- @repeat_count = @repeat_count.to_i
146
-
147
- # 太陽の盈縮表の生成
148
- # [先後數, 朓朒数, (立成b, 立成c)]
149
- # ↓
150
- # [区間の始めの冬至からの経過日数, 朓朒数, 立成b, 立成c]
151
- @s = @s.map {|item| item.dup}
152
- if @rissei # 立成の計算・比較
153
- puts "\n ["+ @denominator.to_s + "]" if @rissei == @rissei.upcase
154
- (0...@s.size).each do |i|
155
- bc = send('_rissei_' + @rissei.downcase, i)
156
- @s[i] += bc if @s[i].size <= 2
157
- if @rissei == @rissei.upcase
158
- sq = (bc[0]-@s[i][2])**2 + (bc[1]-@s[i][3])**2
159
- puts '%9.1f,%5d,%9.4f,%8.4f,%6.2f' %
160
- (@s[i] + [sq == 0 ? -Float::INFINITY : Math.log(sq)/Math.log(100)])
161
- end
162
- end
163
- end
164
- (0...@s.size).each do |i|
165
- @s[i-1][1,0] = @year_length / @s.size + (@s[i][0]-@s[i-1][0]) / @denominator
166
- end
167
- (0...@s.size).each do |i|
168
- @s[i].shift
169
- end
170
-
171
- # 月の遅速表の生成
172
- @m = @m.map {|item| item.dup}
173
- sum = [0,0]
174
- (0...@m.size).each do |i|
175
- @m[i] = _rissei_m(i, sum)
176
- end
177
- end
178
-
179
- # 月の立成 - 月の遅速表の生成 一行分
180
- # [変日差, 損益率]
181
- # ↓
182
- # [変日(区間の終わりの遠/近地点からの経過日数), 区間の終わりの朓朒積, 区間の変日差/日, 区間の損益率]
183
- def _rissei_m(i, sum)
184
- [0,1].each {|k| sum[k] += @m[i][k]}
185
- [sum[0] / @denominator, sum[1], @m[i][0] / @denominator, @m[i][1]]
186
- end
187
-
188
- # 太陽の立成 - 戊寅元暦 1次補間
189
- def _rissei_a(k)
190
- tv = [0,1].map {|i| _tv_s(k+i)}
191
- [(tv[1][1]-tv[0][1]) / (tv[1][0]-tv[0][0]), 0.0]
192
- end
193
-
194
- # 太陽の立成 - 儀鳳暦
195
- def _rissei_b(k)
196
- v =
197
- if k % 3 < 2
198
- t = [0,1,2].map {|n| @s[(k+n) % @s.size][1]}
199
- t01 = t[1] - t[0]
200
- t12 = t[2] - t[1]
201
- (t01 + t12) / 2.0 + t01 - t12
202
- else
203
- t = [-1,0,1].map {|n| @s[(k+n) % @s.size][1]}
204
- t01 = t[1] - t[0]
205
- t12 = t[2] - t[1]
206
- t02 = t[2] - t[0]
207
- t02 / 2.0
208
- end
209
- r = v < 0 ? 12.0/(17*11) : 12.0/(16*11)
210
- [v * r, (t12-t01) * r * r]
211
- end
212
-
213
- # 太陽の立成 - 宣明暦 2次補間
214
- def _rissei_c(k)
215
- i = [k, k+1, k+2, k % 6 == 5 ? -1 : 0]
216
- t0, v0 = _tv_s(i[0]+i[3])
217
- t1, v1 = _tv_s(i[1]+i[3])
218
- t2, v2 = _tv_s(i[2]+i[3])
219
- t01 = t1 - t0
220
- t02 = t2 - t0
221
- t12 = t2 - t1
222
- v01 = v1 - v0
223
- v02 = v2 - v0
224
- c = (v02*t01 - v01*t02) / (t01*t02*t12) * 2
225
- b = (v01 - t01*(t01-1)/2*c) / t01
226
- [b-t01*c*i[3], c]
227
- end
228
-
229
- # 日行盈縮
230
- #
231
- # @param [Integer] i 区間の番号
232
- #
233
- # @return [区間の始めの冬至からの経過日数, 朓朒数]
234
- #
235
- def _tv_s(i)
236
- [@year_length * i / @s.size + @s[i % @s.size][0] / @denominator, @s[i % @s.size][1]]
237
- end
238
-
239
- # 月行遅速
240
- #
241
- # @param [Numeric] t 直前の遠/近地点からの経過日数
242
- #
243
- # @return [区間の始めからの経過日数, 区間の始めの朓朒積, 区間の変日差/日, 区間の損益率, 次の区間の損益率]
244
- #
245
- def _tv_m(t)
246
- (0...@m.size).each do |i|
247
- next if t > @m[i][0]
248
- return [t - (@m[i][0] - @m[i][2]), @m[i][1] - @m[i][3], @m[i][2], @m[i][3], @m[(i+1) % @m.size][3]]
249
- end
250
- end
251
- end
252
-
253
- #
254
- # 日本暦日原典 計算 A)
255
- #
256
- # @private
257
- module MethodA
258
-
259
- include TangMethods
260
-
261
- private
262
-
263
- # 周期番号 -> 日時
264
- #
265
- # @param [Numeric] cn 周期番号
266
- #
267
- # @return [Numeric] ユリウス日
268
- #
269
- def cn_to_time_(cn, time0=nil)
270
- time = super
271
- t = time - @day_epoch
272
- time + (delta_s(t.divmod(@year_length)[1]) + delta_m(t.divmod(@anomalistic_month_length)[1])).to_r / @denominator
273
- end
274
-
275
- #
276
- # 朔の日時の太陽運動の不斉による補正
277
- #
278
- # @param [Numeric] t 直前の冬至からの日数
279
- #
280
- # @return [Numeric] 補正量 / @denominator
281
- #
282
- def delta_s(t)
283
-
284
- t0, a, b, c = nil
285
- @s.each do |v|
286
- t0, a, b, c = v
287
- break if t <= t0
288
- t -= t0
289
- end
290
-
291
- # 24気からの日数 (大余, 小余)
292
- t, dt = t.divmod(1)
293
- dt = (dt * @denominator).to_i
294
-
295
- # 損益率
296
- b0 = (b + c * t).to_i
297
-
298
- # 朓朒数
299
- a0 = (a + b * t + c * t * (t-1.0)/2).to_i
300
-
301
- # 補正値
302
- a0 + (b0.to_f * dt / @denominator + 0.5).floor
303
- end
304
-
305
- #
306
- # 朔の日時の月運動の不斉による補正
307
- #
308
- # @param [Numeric] t 直前の遠/近地点からの日数
309
- #
310
- # @return [Numeric] 補正量 / @denominator
311
- #
312
- def delta_m(t)
313
-
314
- dt, a0, t0, b0, b1 = _tv_m(t)
315
-
316
- # 補正値 (A式)
317
- a0 + (b0.to_f * dt / t0 + 0.5).floor
318
- end
319
- end
320
-
321
- #
322
- # 日本暦日原典 計算 C)
323
- #
324
- # @private
325
- module MethodC
326
-
327
- include TangMethods
328
-
329
- private
330
-
331
- # 周期番号 -> 日時
332
- #
333
- # @param [Numeric] cn 周期番号
334
- #
335
- # @return [Numeric] ユリウス日
336
- #
337
- def cn_to_time_(cn, time0=nil)
338
- time = super
339
- t = time - @day_epoch
340
- t += delta_s(t.divmod(@year_length)[1]) / @denominator
341
- d = 0
342
- @repeat_count.times do
343
- d = delta_m((t+d/@denominator).divmod(@anomalistic_month_length)[1])
344
- end
345
- t + @day_epoch + d / @denominator
346
- end
347
-
348
- #
349
- # 朔の日時の太陽運動の不斉による補正
350
- #
351
- # @param [Numeric] t 直前の冬至からの日数
352
- #
353
- # @return [Numeric] 補正量 / @denominator
354
- #
355
- def delta_s(t)
356
-
357
- t0, a, b, c = nil
358
- @s.each do |v|
359
- t0, a, b, c = v
360
- break if t <= t0
361
- t -= t0
362
- end
363
-
364
- # 24気からの日数 (大余, 小余)
365
- t, dt = t.divmod(1)
366
-
367
- # 損益率
368
- b0 = b + c * t
369
-
370
- # 朓朒数
371
- a0 = a + b * t + c * t * (t-1)/2
372
-
373
- # 補正値
374
- a0 + b0 * dt
375
- end
376
-
377
- #
378
- # 朔の日時の月運動の不斉による補正
379
- #
380
- # @param [Numeric] t 直前の遠/近地点からの日数
381
- #
382
- # @return [Numeric] 補正量 / @denominator
383
- #
384
- def delta_m(t)
385
-
386
- #Sm, 遅速積, 区間長, Δ1, Δ2
387
- dt, a0, t0, b0, b1 = _tv_m(t)
388
-
389
- # 補正値 (B,C式)
390
- a0 + dt / t0 * ((b0+b1)/2.0 + 0.5*(1+t0-dt)*(b0-b1))
391
- end
392
- end
393
-
394
- #
395
- # 日本暦日原典 計算 B)
396
- #
397
- # @private
398
- MethodB = MethodC
399
-
400
- #
401
- # 戊寅元暦
402
- #
403
- # @private
404
- module MethodW
405
-
406
- include MethodA
407
-
408
- private
409
-
410
- # 太陽の立成 - 戊寅元暦 1次補間
411
- def _rissei_a(k)
412
- tv = [0,1].map {|i| _tv_s(k+i)}
413
- [(tv[1][1]-tv[0][1]) / (tv[1][0]-tv[0][0]).round.to_f, 0.0]
414
- end
415
-
416
- # 月の立成 - 月の遅速表の生成 一行分
417
- # [変日差, 盈縮率]
418
- # ↓
419
- # [変日(区間の終わりの遠/近地点からの経過日数), 区間の始まりの盈縮積分, 区間の始まりの経過日数, 区間の損益率]
420
- def _rissei_m(i, sum)
421
- progress_difference = (-@m[i][1]*9037 / @m[i][0]).round.to_f
422
- progress = progress_difference + 8361
423
- line = [sum[1]*9037/progress, sum[0]/@denominator,
424
- -(progress_difference*13006/28968).round * 28968 / progress]
425
- [0,1].each {|k| sum[k] += @m[i][k]}
426
- line.unshift(sum[0] / @denominator)
427
- end
428
-
429
- # 月行遅速
430
- #
431
- # @param [Numeric] t 直前の遠/近地点からの経過日数
432
- #
433
- # @return [区間の始めからの経過日数, 区間の始めの盈縮積分, 区間の変日差/日, 区間の損益率]
434
- #
435
- def _tv_m(t)
436
- (0...@m.size).each do |i|
437
- next if t > @m[i][0]
438
- return [t - @m[i][2], @m[i][1], 1.0, @m[i][3]]
439
- end
440
- end
441
- end
442
-
443
- #
444
- # 元明代のアルゴリズム
445
- #
446
- # @private
447
- module JujiMethods
448
-
449
- # 授時暦・大統暦
450
- module C
451
- def _shift_l(year); @year_span * (year / @year_span) end
452
- alias :_shift_s :_shift_l
453
- end
454
-
455
- # 貞享暦・宝暦暦
456
- module Y
457
- def _shift_l(year); year end
458
- def _shift_s(year); year-1 end
459
- end
460
-
461
- # 寛政暦?
462
- module D
463
- def _shift_l(year); 5 + year.div(10) * 10 end
464
- alias :_shift_s :_shift_l
465
- end
466
-
467
- # 暦元天正冬至から当該年の天正冬至までの日数
468
- def _winter_solstice_(year)
469
- year * (@year_length - @year_delta * _shift_s(year))
470
- end
471
-
472
- # 暦元天正冬至から当該年の近日点通過までの日数
473
- def _perihelion_(year)
474
- _winter_solstice(year) + @anomalistic_year_shift
475
- end
476
-
477
- # 歳周(当該年の日数)
478
- def _year_length_(year)
479
- @year_length - 2 * @year_delta * _shift_l(year)
480
- end
481
- end
482
-
483
- #
484
- # 授時暦の平均太陽の計算
485
- #
486
- # @private
487
- module MethodS
488
-
489
- include JujiMethods
490
-
491
- # 日時 -> 周期番号
492
- #
493
- # @param [Numeric] t ユリウス日(Terrestrial Time)
494
- # @param [When::TM::TemporalPosition] t
495
- #
496
- # @return [Numeric] 周期番号
497
- #
498
- def time_to_cn(t, cn0=nil)
499
- cn0 ||= (t.to_f - @day_epoch) / @year_length + @year_epoch + @longitude_shift
500
- root(cn0 * 12, t.to_f) {|cn| cn_to_time(cn) }
501
- end
502
-
503
- # 周期番号 -> 日時(平気)
504
- #
505
- # @param [Numeric] cn 周期番号
506
- # @param [Numeric] time0 日時の初期近似値(ダミー)
507
- #
508
- # @return [Numeric] ユリウス日
509
- #
510
- def cn_to_time_(cn, time0=nil)
511
- year, mean_term = (cn / 12.0 - @longitude_shift - @year_epoch).divmod(1)
512
- @day_epoch + _winter_solstice(year) + _year_length_(year) * mean_term
513
- end
514
- end
515
-
516
- #
517
- # 授時暦の定朔の計算
518
- #
519
- # @private
520
- module MethodJ
521
-
522
- include JujiMethods
523
-
524
- # 周期番号 -> 日時(定朔)
525
- #
526
- # @param [Numeric] cn 周期番号
527
- # @param [Numeric] time0 日時の初期近似値(ダミー)
528
- #
529
- # @return [Numeric] ユリウス日
530
- #
531
- def cn_to_time_(cn, time0=nil)
532
- # 暦元天正冬至から当該経朔までの日数
533
- mean_lunation = cn * @lunation_length - @lunation_shift
534
-
535
- # 当該経朔を含む近点年の暦元からの年数
536
- year = (mean_lunation / @year_length).floor
537
- until (_perihelion(year)..._perihelion(year+1)).include?(mean_lunation)
538
- year += _perihelion(year) > mean_lunation ? -1 : +1
539
- end
540
-
541
- # 定朔
542
- solar_unit = _year_length(year) / @year_length
543
- mean_motion = (@lunar_mean_motion - @solar_weight / solar_unit) * 10000_0000
544
- @day_epoch + mean_lunation - send('_anomaly_' + @anomaly_method.downcase, mean_lunation, year, solar_unit, mean_motion)
545
- end
546
-
547
- # 経朔 - 定朔 ( A 方式 - 階差)
548
- def _anomaly_a(mean_lunation, year, solar_unit, mean_motion)
549
-
550
- # 遅速差(月の中心差) / (日 / 10000_0000)
551
- gen = ((mean_lunation + @anomalistic_month_shift) % @anomalistic_month_length) / @lunar_unit
552
- minus = gen - gen.floor
553
- plus = 1 - minus
554
- lunar_anomalies = [-minus, 0, +plus].map {|diff|
555
- equation_of_centre(gen+diff, @m)
556
- }
557
-
558
- # 盈縮差(太陽の中心差) / (日 / 10000_0000)
559
- solar_anomalies = (@solar_weight == 0 ? [0] : [-minus * @lunar_unit, 0, plus * @lunar_unit]).map {|diff|
560
- solar_unit * equation_of_centre(((mean_lunation - _perihelion(year) + diff) / solar_unit) % @year_length, @s)
561
- }
562
- solar_anomalies = solar_anomalies * 3 if @solar_weight == 0
563
-
564
- # 経朔 - 定朔
565
- (lunar_anomalies[1] - solar_anomalies[1]) / (((lunar_anomalies[2] - lunar_anomalies[0]) -
566
- (solar_anomalies[2] - solar_anomalies[0])) / @lunar_unit + mean_motion)
567
- end
568
-
569
- # 経朔 - 定朔 ( D 方式 - 差分)
570
- def _anomaly_d(mean_lunation, year, solar_unit, mean_motion)
571
-
572
- # 遅速差(月の中心差) / (日 / 10000_0000)
573
- lunar_anomalies = [0,1].map {|day|
574
- equation_of_centre(((mean_lunation + day + @anomalistic_month_shift) % @anomalistic_month_length) / @lunar_unit, @m)
575
- }
576
-
577
- # 盈縮差(太陽の中心差) / (日 / 10000_0000)
578
- solar_anomalies = (0..@solar_weight).to_a.map {|day|
579
- solar_unit * equation_of_centre(((mean_lunation + day - _perihelion(year)) / solar_unit) % @year_length, @s)
580
- }
581
- solar_anomalies[1] ||= solar_anomalies[0]
582
-
583
- # 経朔 - 定朔
584
- (lunar_anomalies[0] - solar_anomalies[0]) / ((lunar_anomalies[1] - lunar_anomalies[0]) -
585
- (solar_anomalies[1] - solar_anomalies[0]) + mean_motion)
586
- end
587
-
588
- # 経朔 - 定朔 ( B 方式 - 微分)
589
- def _anomaly_b(mean_lunation, year, solar_unit, mean_motion)
590
-
591
- # 遅速差(月の中心差) / (日 / 10000_0000)
592
- lunar_anomalies = [0,1].map {|diff|
593
- equation_of_centre(((mean_lunation + @anomalistic_month_shift) % @anomalistic_month_length) / @lunar_unit, @m, diff)
594
- }
595
-
596
- # 盈縮差(太陽の中心差) / (日 / 10000_0000)
597
- solar_anomalies = (0..@solar_weight).to_a.map {|diff|
598
- solar_unit * equation_of_centre(((mean_lunation - _perihelion(year)) / solar_unit) % @year_length, @s, diff)
599
- }
600
- solar_anomalies[1] ||= 0
601
-
602
- # 経朔 - 定朔
603
- (lunar_anomalies[0] - solar_anomalies[0]) / (lunar_anomalies[1] / @lunar_unit -
604
- solar_anomalies[1] / solar_unit + mean_motion)
605
- end
606
-
607
- # 経朔 - 定朔 ( C 方式 - 幾何学的補正)
608
- def _anomaly_c(mean_lunation, year, solar_unit, mean_motion)
609
- diff = 0
610
- loop do
611
-
612
- # 遅速差(月の中心差) / (日 / 10000_0000)
613
- lunar_anomaly = equation_of_centre(((mean_lunation - diff + @anomalistic_month_shift) % @anomalistic_month_length) / @lunar_unit, @m)
614
-
615
- # 盈縮差(太陽の中心差) / (日 / 10000_0000)
616
- solar_anomaly = solar_unit * equation_of_centre(((mean_lunation - diff - _perihelion(year)) / solar_unit) % @year_length, @s)
617
-
618
- # 次の差分
619
- next_diff = (lunar_anomaly - solar_anomaly) / mean_motion
620
- return next_diff if (next_diff - diff).abs < @anomaly_precision
621
- diff = next_diff
622
- end
623
- end
624
-
625
- # 中心差およびその時間微分
626
- def equation_of_centre(mean_anomaly, table, differential=0)
627
- table.each do |range, base, *coefficients|
628
- if range.include?(mean_anomaly)
629
- diff = mean_anomaly - base
630
- diff = diff.abs if coefficients[0].size[0] == 0
631
- return coefficients[differential].inject(0) {|sum, coefficient| sum * diff + coefficient}
632
- end
633
- end
634
- raise RangeError, 'Mean anomaly out of range: ' + mean_anomaly.to_s
635
- end
636
-
637
- # 立成の作成
638
- def _initialize_rissei
639
- @year_length = @year_length.to_f # 暦元の冬至年 / 日
640
- @year_span = (@year_span || 1).to_i # 冬至年の改訂周期 / 年
641
- @anomalistic_year_shift = (@anomalistic_year_shift || 0).to_f # 暦應(冬至から近日点通過までの日数)
642
- @lunation_length = @lunation_length.to_f # 朔実(朔望月)
643
- @lunation_shift = @lunation_shift.to_f # 閏應(暦元前経朔から暦元天正冬至までの日数)
644
- @lunar_mean_motion = @lunar_mean_motion.to_f # 月平行(恒星天に対する月の平均運動 / 日)
645
- @anomalistic_month_length = @anomalistic_month_length.to_f # 転終(近点月)
646
- @anomalistic_month_shift = @anomalistic_month_shift.to_f # 転應(暦元前近/遠地点通過から暦元天正冬至までの日数)
647
- @anomaly_method = @anomaly_method || 'a' # (経朔-定朔)の計算方法
648
- @anomaly_precision = (@anomaly_precision || 1.0E-5).to_f # c 方式 での収束判定誤差 / 日
649
- @solar_weight = @solar_weight || 0 # (経朔-定朔)の計算で用いる実行差での太陽盈縮の重み(0:非考慮,1:考慮)
650
- @lunar_unit = @lunar_unit.to_f # 太陰遅速計算用招差法定数の時間の単位(限)
651
- @m = _rissei_j(@m) # 太陰遅速計算用招差法定数
652
- @s = _rissei_j(@s) # 太陽盈縮計算用招差法定数
653
- end
654
-
655
- # 招差法用の表の生成
656
- def _rissei_j(table)
657
- table.map {|range, base, coefficients|
658
- sign = range.last == base ? -1 : +1
659
- [range, base, coefficients.reverse,
660
- (1...coefficients.size).to_a.reverse.map {|i| sign * i * coefficients[i]}]
661
- }
662
- end
663
- end
664
-
665
- # 近点月
666
- # @return [Numeric]
667
- #attr_reader :anomalistic_month_length
668
-
669
- # 元期の近点角
670
- # @return [Numeric]
671
- #attr_reader :anomalistic_month_shift
672
-
673
- # 日時 -> 周期番号(唐代の定朔の暦法用 cn_to_time(1L) を使用する)
674
- #
675
- # @param [Numeric] t ユリウス日(Terrestrial Time)
676
- # @param [When::TM::TemporalPosition] t
677
- #
678
- # @return [Numeric] 周期番号
679
- #
680
- def time_to_cn(t)
681
- return super unless @cycle_number_1m
682
- time = @is_dynamical ? +t : t.to_f
683
- cn0 = time * @cycle_number_1m + @cycle_number_0m
684
- root(cn0, time, 0, 5) {|cn| cn_to_time(cn)}
685
- end
686
-
687
- # 当該日付の月の位相の変化範囲(唐代の定朔の暦法用 cn_to_time(1L) を使用する)
688
- #
689
- # @param [When::TM::TemporalPosition] date 日付
690
- #
691
- # @return [Array<Numeric>] 当該日付の月の位相の変化範囲
692
- #
693
- def phase_range(date)
694
- date = date.floor
695
- [date, date.succ].map {|d|
696
- t = d.to_f
697
- c = (60.0 * ((t - CYCLE_0M) * @cycle_number_1m + @cycle_number_0m)).floor
698
- t0 = t1 = nil
699
- loop do
700
- t0 = cn_to_time( c / 60.0)
701
- t1 = cn_to_time((c+1)/ 60.0)
702
- d = ((t-t0) / (t1-t0)).round
703
- if d.abs > 1
704
- c += d
705
- elsif t0 > t
706
- c -= 1
707
- elsif t1 <= t
708
- c += 1
709
- else
710
- break
711
- end
712
- end
713
- (c + (t-t0) / (t1-t0)) / 60.0
714
- }
715
- end
716
-
717
- private
718
-
719
- # オブジェクトの正規化
720
- def _normalize(args=[], options={})
721
- super
722
-
723
- # 通法
724
- @denominator = @year_length.denominator if @year_length.kind_of?(Rational)
725
- @denominator = [@denominator||0, @lunation_length.denominator].max if @lunation_length.kind_of?(Rational)
726
-
727
- if @formula == '1L'
728
-
729
- # 月の位相の計算
730
- @method ||= @year_span ? 'J' : 'A'
731
- extend self.class.const_get("Method#{@method.upcase}")
732
-
733
- # 立成の初期化
734
- _initialize_rissei
735
-
736
- elsif @year_span
737
- # 太陽黄経の計算(消長あり)
738
- extend MethodS
739
- @year_span = @year_span.to_i
740
- end
741
-
742
- if self.kind_of?(JujiMethods)
743
- case @year_span
744
- when 0,1; extend JujiMethods::Y
745
- # when 10 ; extend JujiMethods::D
746
- else ; extend JujiMethods::C
747
- end
748
- end
749
- end
750
- end
751
- end
752
-
753
- module CalendarTypes
754
-
755
- #
756
- # Chinese Solar Calendar
757
- #
758
- class ChineseSolar < EphemerisBasedSolar
759
-
760
- class << self
761
- #
762
- # 太陰太陽暦の定義から太陰太陽暦と太陽暦(節月)の組を作る
763
- #
764
- # @private
765
- def twin(area, definition)
766
- definition.inject([]) {|list, cal|
767
- if cal.kind_of?(Array) && cal[0] == ChineseLuniSolar
768
- solar_name = cal[1].sub(/=?\]/, '(節月)=]')
769
- lunisolar = cal.dup << "twin:#{area}::" + solar_name.gsub(/(name:\[|=?\])/,'')
770
- solar = cal.dup << "twin:#{area}::" + cal[1].gsub(/(name:\[|=?\])/,'')
771
- solar[0..1] = [ChineseSolar, solar_name]
772
- list << lunisolar << solar
773
- else
774
- list << cal
775
- end
776
- }
777
- end
778
-
779
- #
780
- # 盈縮差の表の時間の単位を調整する
781
- #
782
- # @private
783
- def change_unit(unit, definition)
784
- definition.map {|line|
785
- line.map {|item|
786
- case item
787
- when Range ; Range.new(item.first*unit, item.last*unit, item.exclude_end?)
788
- when Numeric ; item*unit
789
- else ; item
790
- end
791
- }
792
- }
793
- end
794
- end
795
-
796
- #
797
- # @return [When::CalendarTypes::ChineseLuniSolar] 対で用いる太陰太陽暦の名前
798
- #
799
- attr_reader :twin
800
-
801
- # @private
802
- attr_reader :doyo
803
-
804
- private
805
-
806
- # オブジェクトの正規化
807
- #
808
- # @formula = 太陽黄経の計算に用いるEphemeris
809
- #
810
- def _normalize(args=[], options={})
811
- @label ||= 'Chinese::ChineseSolar'
812
- @formula ||= ['Formula']
813
- @formula = Array(@formula)
814
- @formula *= 2 if @formula.length == 1
815
- @formula[0] += (@formula[0] =~ /\?/ ? '&' : '?') + 'formula=12S' if @formula[0].kind_of?(String)
816
- @formula[1] += (@formula[1] =~ /\?/ ? '&' : '?') + 'formula=1L' if @formula[1].kind_of?(String)
817
- @note ||= When.CalendarNote('Chinese')
818
- @indices ||= [
819
- When.Index('Chinese::Month'),
820
- When::Coordinates::DefaultDayIndex
821
- ]
822
- super
823
- end
824
- end
825
-
826
- #
827
- # Chinese Luni-Solar Calendar
828
- #
829
- class ChineseLuniSolar < EphemerisBasedLuniSolar
830
-
831
- #
832
- # @return [When::CalendarTypes::ChineseSolar] 対で用いる太陽暦の名前
833
- #
834
- attr_reader :twin
835
-
836
- # 指定の年の天正冬至を含む月以降1年分の閏月のパターン
837
- #
838
- # @param [Numeric] y 年
839
- #
840
- # @return [Array<Numeric:月番号>, Hash<Numeric:含む中気の数=>Numeric:月番号>]
841
- #
842
- def intercalary_pattern(y)
843
- m = _base_month(y)
844
- l = _base_ids(y)
845
- c = {0=>[], 1=>[], 2=>[]}
846
- d0 = Residue.mod(_new_month(m)-1) {|n| _new_epoch(n)}[0]
847
- l.size.times do |i|
848
- d1 = Residue.mod(_new_month(m+i+1)-1) {|n| _new_epoch(n)}[0]
849
- c[d1-d0] << l[i]
850
- d0 = d1
851
- end
852
- c.delete(1)
853
- [l, c]
854
- end
855
-
856
- private
857
-
858
- # オブジェクトの正規化
859
- #
860
- # @cycle_offset = 雨水の場合 -1
861
- # @formula = 太陽黄経および月の位相の計算に用いるEphemeris
862
- #
863
- def _normalize(args=[], options={})
864
- @label ||= 'Chinese::ChineseLuniSolar'
865
- @formula ||= ['Formula']
866
- @formula = Array(@formula)
867
- @formula *= 2 if @formula.length == 1
868
- @formula[0] += (@formula[0] =~ /\?/ ? '&' : '?') + 'formula=12S' if @formula[0].kind_of?(String)
869
- @formula[1] += (@formula[1] =~ /\?/ ? '&' : '?') + 'formula=1L' if @formula[1].kind_of?(String)
870
- @vernal_month ||= 2
871
- @cycle_offset ||= @vernal_month - 3
872
- @base_month ||= 11
873
- @base_month = @base_month.to_i
874
- @intercalary_span ||= 12
875
- @intercalary_span = @intercalary_span.to_i
876
- @intercalary_month = (@intercalary_month.to_i - @base_month) % 12 + 1 if @intercalary_month
877
- @note ||= When.CalendarNote('Chinese')
878
- @indices ||= [
879
- When.Index('Chinese::Month', {:branch=>{1=>'_m:Calendar::閏'}}),
880
- When::Coordinates::DefaultDayIndex
881
- ]
882
- super
883
- end
884
-
885
- # 正月の通月
886
- #
887
- # @param [Integer] y 年
888
- #
889
- # @return [Numeric] 正月の通月
890
- #
891
- def _new_year_month_(y)
892
- return _base_month(y) if @base_month == 1
893
- intercalary = 0
894
- _ids([y-1]).each do |v|
895
- unless v.branch == 0
896
- intercalary = v.trunk
897
- break
898
- end
899
- end
900
- _base_month(y) - @base_month + (intercalary>=@base_month ? 14 : 13)
901
- end
902
-
903
- # 天正冬至月の通月
904
- #
905
- # @param [Integer] y 年
906
- #
907
- # @return [Numeric] 天正冬至月の通月
908
- #
909
- def _base_month_(y)
910
- (Residue.mod(solar_sdn(@formula[0].cn_to_time(12*(y-1) + @base_month - @vernal_month))) {|m| _new_month(m)})[0]
911
- end
912
-
913
- # 暦年の翻訳表の取得
914
- #
915
- # @param [Array<Numeric>] date ( 年 )
916
- #
917
- # @return [When::Coordinates::Pair] 暦年の翻訳表
918
- #
919
- def _ids_(date)
920
- y = +date[0]
921
- return _base_ids(y) if @base_month == 1
922
- (_base_ids(y).dup.delete_if {|v| v.trunk >= @base_month}) + (_base_ids(y+1).dup.delete_if {|v| v.trunk < @base_month})
923
- end
924
-
925
- # 天正冬至月から1年分の翻訳表の取得
926
- #
927
- # @param [Numeric] y 年
928
- #
929
- # @return [When::Coordinates::Pair]
930
- # 天正冬至月から1年分の翻訳表
931
- #
932
- def _base_ids_(y)
933
- _intercalary_pattern(y,12)[1..-1].inject([Pair._force_pair(@base_month, 0)]) do |base_ids, flag|
934
- base_ids << (flag ? Pair._force_pair(base_ids[-1].trunk, 1) : Pair._force_pair(base_ids[-1].trunk % 12 + 1, 0))
935
- end
936
- end
937
-
938
- # 天正冬至月から1年分の閏月のパターンの取得
939
- #
940
- # @param [Numeric] y 年
941
- #
942
- # @return [Boolean]
943
- # [ true - 閏月である ]
944
- # [ false - 閏月でない ]
945
- #
946
- def _intercalary_pattern(y, n)
947
- m0 = _base_month(y)
948
- m1 = _base_month(y + n/12.0)
949
- return Array.new(n, false) if m1-m0 == n
950
- return Array.new(n+1) {|i| i==@intercalary_month} if @intercalary_month # for 四分暦
951
- return _intercalary_pattern(y, n/2) + _intercalary_pattern(y + n/24.0, n/2) if n > @intercalary_span
952
- flags = Array.new(n+1, false)
953
- n.times do |i|
954
- m0 += 1
955
- if _intercalary?(m0)
956
- flags[i+1] = true
957
- return flags
958
- end
959
- end
960
- raise ArgumentError, "Intercalary month not found"
961
- end
962
-
963
- # 指定の月の中気の有無
964
- #
965
- # @param [Numeric] m 通月
966
- #
967
- # @return [Boolean]
968
- # [ true - 中気無し ]
969
- # [ false - 中気有り ]
970
- #
971
- def _intercalary?(m)
972
- e = _new_month(m+1) - 1
973
- d = Residue.mod(e) {|n| _new_epoch(n)}
974
- e - d[1] < _new_month(m)
975
- end
976
- end
977
-
978
- #
979
- # 太平天国 2.1.1-3.2.30
980
- #
981
- TenrekiA = [CyclicTableBased, {
982
- 'origin_of_LSC' => 2397523,
983
- 'origin_of_MSC' => 1852,
984
- 'indices' => [
985
- When.Index('Chinese::Month', {:unit =>12}),
986
- When::Coordinates::DefaultDayIndex
987
- ],
988
- 'rule_table' => {
989
- 'T' => {'Rule' =>[365]},
990
- 365 => {'Length'=>[31,30]*5 + [30]*2}
991
- }
992
- }]
993
-
994
- #
995
- # 太平天国 3.3.1-
996
- #
997
- TenrekiB = [CyclicTableBased, {
998
- 'origin_of_LSC' => 2397522,
999
- 'origin_of_MSC' => 1852,
1000
- 'indices' => [
1001
- When.Index('Chinese::Month', {:unit =>12}),
1002
- When.Index({:shift => 1})
1003
- ],
1004
- 'rule_table' => {
1005
- 'T' => {'Rule' =>[366]},
1006
- 366 => {'Length'=>[31,30]*6}
1007
- },
1008
- 'note' => 'Default'
1009
- }]
1010
-
1011
- #
1012
- # 彝
1013
- #
1014
- Yi = [CyclicTableBased, {
1015
- 'label' => 'Chinese::Yi',
1016
- 'origin_of_LSC' => 1721431,
1017
- 'origin_of_MSC' => 1,
1018
- 'indices' => [
1019
- When.Index('Yi::Month', {:unit =>11}),
1020
- When::Coordinates::DefaultDayIndex
1021
- ],
1022
- 'rule_table' => {
1023
- 'T' => {'Rule' =>[365, 365, 365, 366]},
1024
- 365 => {'Length'=>[36]*10 + [5]},
1025
- 366 => {'Length'=>[36]*10 + [6]}
1026
- },
1027
- 'note' => 'Yis'
1028
- }]
1029
- end
1030
- end
1
+ # -*- coding: utf-8 -*-
2
+ =begin
3
+ Copyright (C) 2011-2014 Takashi SUGA
4
+
5
+ You may use and/or modify this file according to the license described in the LICENSE.txt file included in this archive.
6
+ =end
7
+
8
+ module When
9
+
10
+ class BasicTypes::M17n
11
+
12
+ Chinese = [self, [
13
+ "locale:[=ja:, en=en:, alias]",
14
+ "names:[Chinese=]",
15
+ "[中国太陽暦(節月)=ja:%%<二十四節気>#%.<暦月と節月>, *ChineseSolar=en:Solar_term]",
16
+ "[中国太陰太陽暦=ja:%%<中国暦>, *ChineseLuniSolar=en:Chinese_calendar]",
17
+ "[彝暦=ja:%%<イ族>, *Yi=en:Yi_people]",
18
+
19
+ [self,
20
+ "names:[月=ja:%%<月_(暦)>, *Month]",
21
+ "[正月, Month 1= ]",
22
+ "[二月, Month 2= ]",
23
+ "[三月, Month 3= ]",
24
+ "[四月, Month 4= ]",
25
+ "[五月, Month 5= ]",
26
+ "[六月, Month 6= ]",
27
+ "[七月, Month 7= ]",
28
+ "[八月, Month 8= ]",
29
+ "[九月, Month 9= ]",
30
+ "[十月, Month 10=]",
31
+ "[十一月, Month 11=]",
32
+ "[十二月, Month 12=]"
33
+ ],
34
+
35
+ [self,
36
+ "names:[月=ja:%%<月_(暦)>, *MonthA=en:Month]",
37
+ "[一月, Month 1= ]",
38
+ "[二月, Month 2= ]",
39
+ "[三月, Month 3= ]",
40
+ "[四月, Month 4= ]",
41
+ "[五月, Month 5= ]",
42
+ "[六月, Month 6= ]",
43
+ "[七月, Month 7= ]",
44
+ "[八月, Month 8= ]",
45
+ "[九月, Month 9= ]",
46
+ "[十月, Month 10=]",
47
+ "[正月, New Year Month=]",
48
+ "[臘月, Month 12=]"
49
+ ],
50
+
51
+ [self,
52
+ "names:[月=ja:%%<月_(暦)>, *MonthB=en:Month]",
53
+ "[建寅月, Month 3= ]",
54
+ "[建卯月, Month 4= ]",
55
+ "[建辰月, Month 5= ]",
56
+ "[建巳月, Month 6= ]",
57
+ "[建午月, Month 7= ]",
58
+ "[建未月, Month 8= ]",
59
+ "[建申月, Month 9= ]",
60
+ "[建酉月, Month 10=]",
61
+ "[建戌月, Month 11=]",
62
+ "[建亥月, Month 12=]",
63
+ "[建子月, Month 1= ]",
64
+ "[建丑月, Month 2= ]"
65
+ ]
66
+ ]]
67
+
68
+ Yi = [self, [
69
+ "locale:[=ja:, en=en:, alias]",
70
+ "names:[Yi=]",
71
+
72
+ [self,
73
+ "names:[月=ja:%%<月_(暦)>, *Month]",
74
+ "[木公月=, Month 1= ]",
75
+ "[木母月=, Month 2= ]",
76
+ "[火公月=, Month 3= ]",
77
+ "[火母月=, Month 4= ]",
78
+ "[土公月=, Month 5= ]",
79
+ "[土母月=, Month 6= ]",
80
+ "[銅公月=, Month 7= ]",
81
+ "[銅母月=, Month 8= ]",
82
+ "[水公月=, Month 9= ]",
83
+ "[水母月=, Month 10=]",
84
+ "[過年日=, end of year days=]"
85
+ ]
86
+ ]]
87
+ end
88
+
89
+ module Coordinates
90
+
91
+ # Yi years
92
+ Yi = [When::BasicTypes::M17n, [
93
+ "locale:[=ja:, en=en:, alias]",
94
+ "names:[Yi]",
95
+
96
+ [Residue,
97
+ "label:[YearName=]", "divisor:8", "year:0",
98
+ [Residue, "label:[東北之年=, NorthEastYear=]", "remainder: 0"],
99
+ [Residue, "label:[東方之年=, EastYear= ]", "remainder: 1"],
100
+ [Residue, "label:[東南之年=, SouthEastYear=]", "remainder: 2"],
101
+ [Residue, "label:[南方之年=, SouthYear= ]", "remainder: 3"],
102
+ [Residue, "label:[西南之年=, SouthWestYear=]", "remainder: 4"],
103
+ [Residue, "label:[西方之年=, WestYear= ]", "remainder: 5"],
104
+ [Residue, "label:[西北之年=, NorthWestYear=]", "remainder: 6"],
105
+ [Residue, "label:[北方之年=, NorthYear= ]", "remainder: 7"]
106
+ ]
107
+ ]]
108
+ end
109
+
110
+ class CalendarNote
111
+ Yis = [['Yi::YearName'], ['_m:Calendar::Month'], ['Common::Week']]
112
+ end
113
+
114
+ module Ephemeris
115
+
116
+ #
117
+ # Chinese Luni-Solar Calendar Formula for True Lunation Type
118
+ #
119
+ class ChineseTrueLunation < MeanLunation
120
+
121
+ #
122
+ # 唐代のアルゴリズム
123
+ #
124
+ # @private
125
+ module TangMethods
126
+
127
+ # 太陽の位置補正表
128
+ # @return [Array<Array< 入気定日加減数, 朓朒数, 損益率, 損益率増分 >>]
129
+ #attr_reader :s
130
+
131
+ # 月の位置補正表
132
+ # @return [Array<Array< 区間の時間/分, 損益率 >>]
133
+ #attr_reader :m
134
+
135
+ #
136
+ # 立成の初期化
137
+ #
138
+ def _initialize_rissei
139
+
140
+ # 近点月
141
+ @anomalistic_month_length = @anomalistic_month_length.to_r
142
+
143
+ # 計算式 C) のための繰り返し回数
144
+ @repeat_count ||= @method.upcase == 'C' ? 2 : 1
145
+ @repeat_count = @repeat_count.to_i
146
+
147
+ # 太陽の盈縮表の生成
148
+ # [先後數, 朓朒数, (立成b, 立成c)]
149
+ # ↓
150
+ # [区間の始めの冬至からの経過日数, 朓朒数, 立成b, 立成c]
151
+ @s = @s.map {|item| item.dup}
152
+ if @rissei # 立成の計算・比較
153
+ puts "\n ["+ @denominator.to_s + "]" if @rissei == @rissei.upcase
154
+ (0...@s.size).each do |i|
155
+ bc = send('_rissei_' + @rissei.downcase, i)
156
+ @s[i] += bc if @s[i].size <= 2
157
+ if @rissei == @rissei.upcase
158
+ sq = (bc[0]-@s[i][2])**2 + (bc[1]-@s[i][3])**2
159
+ puts '%9.1f,%5d,%9.4f,%8.4f,%6.2f' %
160
+ (@s[i] + [sq == 0 ? -Float::INFINITY : Math.log(sq)/Math.log(100)])
161
+ end
162
+ end
163
+ end
164
+ (0...@s.size).each do |i|
165
+ @s[i-1][1,0] = @year_length / @s.size + (@s[i][0]-@s[i-1][0]) / @denominator
166
+ end
167
+ (0...@s.size).each do |i|
168
+ @s[i].shift
169
+ end
170
+
171
+ # 月の遅速表の生成
172
+ @m = @m.map {|item| item.dup}
173
+ sum = [0,0]
174
+ (0...@m.size).each do |i|
175
+ @m[i] = _rissei_m(i, sum)
176
+ end
177
+ end
178
+
179
+ # 月の立成 - 月の遅速表の生成 一行分
180
+ # [変日差, 損益率]
181
+ # ↓
182
+ # [変日(区間の終わりの遠/近地点からの経過日数), 区間の終わりの朓朒積, 区間の変日差/日, 区間の損益率]
183
+ def _rissei_m(i, sum)
184
+ [0,1].each {|k| sum[k] += @m[i][k]}
185
+ [sum[0] / @denominator, sum[1], @m[i][0] / @denominator, @m[i][1]]
186
+ end
187
+
188
+ # 太陽の立成 - 戊寅元暦 1次補間
189
+ def _rissei_a(k)
190
+ tv = [0,1].map {|i| _tv_s(k+i)}
191
+ [(tv[1][1]-tv[0][1]) / (tv[1][0]-tv[0][0]), 0.0]
192
+ end
193
+
194
+ # 太陽の立成 - 儀鳳暦
195
+ def _rissei_b(k)
196
+ v =
197
+ if k % 3 < 2
198
+ t = [0,1,2].map {|n| @s[(k+n) % @s.size][1]}
199
+ t01 = t[1] - t[0]
200
+ t12 = t[2] - t[1]
201
+ (t01 + t12) / 2.0 + t01 - t12
202
+ else
203
+ t = [-1,0,1].map {|n| @s[(k+n) % @s.size][1]}
204
+ t01 = t[1] - t[0]
205
+ t12 = t[2] - t[1]
206
+ t02 = t[2] - t[0]
207
+ t02 / 2.0
208
+ end
209
+ r = v < 0 ? 12.0/(17*11) : 12.0/(16*11)
210
+ [v * r, (t12-t01) * r * r]
211
+ end
212
+
213
+ # 太陽の立成 - 宣明暦 2次補間
214
+ def _rissei_c(k)
215
+ i = [k, k+1, k+2, k % 6 == 5 ? -1 : 0]
216
+ t0, v0 = _tv_s(i[0]+i[3])
217
+ t1, v1 = _tv_s(i[1]+i[3])
218
+ t2, v2 = _tv_s(i[2]+i[3])
219
+ t01 = t1 - t0
220
+ t02 = t2 - t0
221
+ t12 = t2 - t1
222
+ v01 = v1 - v0
223
+ v02 = v2 - v0
224
+ c = (v02*t01 - v01*t02) / (t01*t02*t12) * 2
225
+ b = (v01 - t01*(t01-1)/2*c) / t01
226
+ [b-t01*c*i[3], c]
227
+ end
228
+
229
+ # 日行盈縮
230
+ #
231
+ # @param [Integer] i 区間の番号
232
+ #
233
+ # @return [区間の始めの冬至からの経過日数, 朓朒数]
234
+ #
235
+ def _tv_s(i)
236
+ [@year_length * i / @s.size + @s[i % @s.size][0] / @denominator, @s[i % @s.size][1]]
237
+ end
238
+
239
+ # 月行遅速
240
+ #
241
+ # @param [Numeric] t 直前の遠/近地点からの経過日数
242
+ #
243
+ # @return [区間の始めからの経過日数, 区間の始めの朓朒積, 区間の変日差/日, 区間の損益率, 次の区間の損益率]
244
+ #
245
+ def _tv_m(t)
246
+ (0...@m.size).each do |i|
247
+ next if t > @m[i][0]
248
+ return [t - (@m[i][0] - @m[i][2]), @m[i][1] - @m[i][3], @m[i][2], @m[i][3], @m[(i+1) % @m.size][3]]
249
+ end
250
+ end
251
+ end
252
+
253
+ #
254
+ # 日本暦日原典 計算 A)
255
+ #
256
+ # @private
257
+ module MethodA
258
+
259
+ include TangMethods
260
+
261
+ private
262
+
263
+ # 周期番号 -> 日時
264
+ #
265
+ # @param [Numeric] cn 周期番号
266
+ #
267
+ # @return [Numeric] ユリウス日
268
+ #
269
+ def cn_to_time_(cn, time0=nil)
270
+ time = super
271
+ t = time - @day_epoch
272
+ time + (delta_s(t.divmod(@year_length)[1]) + delta_m(t.divmod(@anomalistic_month_length)[1])).to_r / @denominator
273
+ end
274
+
275
+ #
276
+ # 朔の日時の太陽運動の不斉による補正
277
+ #
278
+ # @param [Numeric] t 直前の冬至からの日数
279
+ #
280
+ # @return [Numeric] 補正量 / @denominator
281
+ #
282
+ def delta_s(t)
283
+
284
+ t0, a, b, c = nil
285
+ @s.each do |v|
286
+ t0, a, b, c = v
287
+ break if t <= t0
288
+ t -= t0
289
+ end
290
+
291
+ # 24気からの日数 (大余, 小余)
292
+ t, dt = t.divmod(1)
293
+ dt = (dt * @denominator).to_i
294
+
295
+ # 損益率
296
+ b0 = (b + c * t).to_i
297
+
298
+ # 朓朒数
299
+ a0 = (a + b * t + c * t * (t-1.0)/2).to_i
300
+
301
+ # 補正値
302
+ a0 + (b0.to_f * dt / @denominator + 0.5).floor
303
+ end
304
+
305
+ #
306
+ # 朔の日時の月運動の不斉による補正
307
+ #
308
+ # @param [Numeric] t 直前の遠/近地点からの日数
309
+ #
310
+ # @return [Numeric] 補正量 / @denominator
311
+ #
312
+ def delta_m(t)
313
+
314
+ dt, a0, t0, b0, b1 = _tv_m(t)
315
+
316
+ # 補正値 (A式)
317
+ a0 + (b0.to_f * dt / t0 + 0.5).floor
318
+ end
319
+ end
320
+
321
+ #
322
+ # 日本暦日原典 計算 C)
323
+ #
324
+ # @private
325
+ module MethodC
326
+
327
+ include TangMethods
328
+
329
+ private
330
+
331
+ # 周期番号 -> 日時
332
+ #
333
+ # @param [Numeric] cn 周期番号
334
+ #
335
+ # @return [Numeric] ユリウス日
336
+ #
337
+ def cn_to_time_(cn, time0=nil)
338
+ time = super
339
+ t = time - @day_epoch
340
+ t += delta_s(t.divmod(@year_length)[1]) / @denominator
341
+ d = 0
342
+ @repeat_count.times do
343
+ d = delta_m((t+d/@denominator).divmod(@anomalistic_month_length)[1])
344
+ end
345
+ t + @day_epoch + d / @denominator
346
+ end
347
+
348
+ #
349
+ # 朔の日時の太陽運動の不斉による補正
350
+ #
351
+ # @param [Numeric] t 直前の冬至からの日数
352
+ #
353
+ # @return [Numeric] 補正量 / @denominator
354
+ #
355
+ def delta_s(t)
356
+
357
+ t0, a, b, c = nil
358
+ @s.each do |v|
359
+ t0, a, b, c = v
360
+ break if t <= t0
361
+ t -= t0
362
+ end
363
+
364
+ # 24気からの日数 (大余, 小余)
365
+ t, dt = t.divmod(1)
366
+
367
+ # 損益率
368
+ b0 = b + c * t
369
+
370
+ # 朓朒数
371
+ a0 = a + b * t + c * t * (t-1)/2
372
+
373
+ # 補正値
374
+ a0 + b0 * dt
375
+ end
376
+
377
+ #
378
+ # 朔の日時の月運動の不斉による補正
379
+ #
380
+ # @param [Numeric] t 直前の遠/近地点からの日数
381
+ #
382
+ # @return [Numeric] 補正量 / @denominator
383
+ #
384
+ def delta_m(t)
385
+
386
+ #Sm, 遅速積, 区間長, Δ1, Δ2
387
+ dt, a0, t0, b0, b1 = _tv_m(t)
388
+
389
+ # 補正値 (B,C式)
390
+ a0 + dt / t0 * ((b0+b1)/2.0 + 0.5*(1+t0-dt)*(b0-b1))
391
+ end
392
+ end
393
+
394
+ #
395
+ # 日本暦日原典 計算 B)
396
+ #
397
+ # @private
398
+ MethodB = MethodC
399
+
400
+ #
401
+ # 戊寅元暦
402
+ #
403
+ # @private
404
+ module MethodW
405
+
406
+ include MethodA
407
+
408
+ private
409
+
410
+ # 太陽の立成 - 戊寅元暦 1次補間
411
+ def _rissei_a(k)
412
+ tv = [0,1].map {|i| _tv_s(k+i)}
413
+ [(tv[1][1]-tv[0][1]) / (tv[1][0]-tv[0][0]).round.to_f, 0.0]
414
+ end
415
+
416
+ # 月の立成 - 月の遅速表の生成 一行分
417
+ # [変日差, 盈縮率]
418
+ # ↓
419
+ # [変日(区間の終わりの遠/近地点からの経過日数), 区間の始まりの盈縮積分, 区間の始まりの経過日数, 区間の損益率]
420
+ def _rissei_m(i, sum)
421
+ progress_difference = (-@m[i][1]*9037 / @m[i][0]).round.to_f
422
+ progress = progress_difference + 8361
423
+ line = [sum[1]*9037/progress, sum[0]/@denominator,
424
+ -(progress_difference*13006/28968).round * 28968 / progress]
425
+ [0,1].each {|k| sum[k] += @m[i][k]}
426
+ line.unshift(sum[0] / @denominator)
427
+ end
428
+
429
+ # 月行遅速
430
+ #
431
+ # @param [Numeric] t 直前の遠/近地点からの経過日数
432
+ #
433
+ # @return [区間の始めからの経過日数, 区間の始めの盈縮積分, 区間の変日差/日, 区間の損益率]
434
+ #
435
+ def _tv_m(t)
436
+ (0...@m.size).each do |i|
437
+ next if t > @m[i][0]
438
+ return [t - @m[i][2], @m[i][1], 1.0, @m[i][3]]
439
+ end
440
+ end
441
+ end
442
+
443
+ #
444
+ # 元明代のアルゴリズム
445
+ #
446
+ # @private
447
+ module JujiMethods
448
+
449
+ # 授時暦・大統暦
450
+ module C
451
+ def _shift_l(year); @year_span * (year / @year_span) end
452
+ alias :_shift_s :_shift_l
453
+ end
454
+
455
+ # 貞享暦・宝暦暦
456
+ module Y
457
+ def _shift_l(year); year end
458
+ def _shift_s(year); year-1 end
459
+ end
460
+
461
+ # 寛政暦?
462
+ module D
463
+ def _shift_l(year); 5 + year.div(10) * 10 end
464
+ alias :_shift_s :_shift_l
465
+ end
466
+
467
+ # 暦元天正冬至から当該年の天正冬至までの日数
468
+ def _winter_solstice_(year)
469
+ year * (@year_length - @year_delta * _shift_s(year))
470
+ end
471
+
472
+ # 暦元天正冬至から当該年の近日点通過までの日数
473
+ def _perihelion_(year)
474
+ _winter_solstice(year) + @anomalistic_year_shift
475
+ end
476
+
477
+ # 歳周(当該年の日数)
478
+ def _year_length_(year)
479
+ @year_length - 2 * @year_delta * _shift_l(year)
480
+ end
481
+ end
482
+
483
+ #
484
+ # 授時暦の平均太陽の計算
485
+ #
486
+ # @private
487
+ module MethodS
488
+
489
+ include JujiMethods
490
+
491
+ # 日時 -> 周期番号
492
+ #
493
+ # @param [Numeric] t ユリウス日(Terrestrial Time)
494
+ # @param [When::TM::TemporalPosition] t
495
+ #
496
+ # @return [Numeric] 周期番号
497
+ #
498
+ def time_to_cn(t, cn0=nil)
499
+ cn0 ||= (t.to_f - @day_epoch) / @year_length + @year_epoch + @longitude_shift
500
+ root(cn0 * 12, t.to_f) {|cn| cn_to_time(cn) }
501
+ end
502
+
503
+ # 周期番号 -> 日時(平気)
504
+ #
505
+ # @param [Numeric] cn 周期番号
506
+ # @param [Numeric] time0 日時の初期近似値(ダミー)
507
+ #
508
+ # @return [Numeric] ユリウス日
509
+ #
510
+ def cn_to_time_(cn, time0=nil)
511
+ year, mean_term = (cn / 12.0 - @longitude_shift - @year_epoch).divmod(1)
512
+ @day_epoch + _winter_solstice(year) + _year_length_(year) * mean_term
513
+ end
514
+ end
515
+
516
+ #
517
+ # 授時暦の定朔の計算
518
+ #
519
+ # @private
520
+ module MethodJ
521
+
522
+ include JujiMethods
523
+
524
+ # 周期番号 -> 日時(定朔)
525
+ #
526
+ # @param [Numeric] cn 周期番号
527
+ # @param [Numeric] time0 日時の初期近似値(ダミー)
528
+ #
529
+ # @return [Numeric] ユリウス日
530
+ #
531
+ def cn_to_time_(cn, time0=nil)
532
+ # 暦元天正冬至から当該経朔までの日数
533
+ mean_lunation = cn * @lunation_length - @lunation_shift
534
+
535
+ # 当該経朔を含む近点年の暦元からの年数
536
+ year = (mean_lunation / @year_length).floor
537
+ until (_perihelion(year)..._perihelion(year+1)).include?(mean_lunation)
538
+ year += _perihelion(year) > mean_lunation ? -1 : +1
539
+ end
540
+
541
+ # 定朔
542
+ solar_unit = _year_length(year) / @year_length
543
+ mean_motion = (@lunar_mean_motion - @solar_weight / solar_unit) * 10000_0000
544
+ @day_epoch + mean_lunation - send('_anomaly_' + @anomaly_method.downcase, mean_lunation, year, solar_unit, mean_motion)
545
+ end
546
+
547
+ # 経朔 - 定朔 ( A 方式 - 階差)
548
+ def _anomaly_a(mean_lunation, year, solar_unit, mean_motion)
549
+
550
+ # 遅速差(月の中心差) / (日 / 10000_0000)
551
+ gen = ((mean_lunation + @anomalistic_month_shift) % @anomalistic_month_length) / @lunar_unit
552
+ minus = gen - gen.floor
553
+ plus = 1 - minus
554
+ lunar_anomalies = [-minus, 0, +plus].map {|diff|
555
+ equation_of_centre(gen+diff, @m)
556
+ }
557
+
558
+ # 盈縮差(太陽の中心差) / (日 / 10000_0000)
559
+ solar_anomalies = (@solar_weight == 0 ? [0] : [-minus * @lunar_unit, 0, plus * @lunar_unit]).map {|diff|
560
+ solar_unit * equation_of_centre(((mean_lunation - _perihelion(year) + diff) / solar_unit) % @year_length, @s)
561
+ }
562
+ solar_anomalies = solar_anomalies * 3 if @solar_weight == 0
563
+
564
+ # 経朔 - 定朔
565
+ (lunar_anomalies[1] - solar_anomalies[1]) / (((lunar_anomalies[2] - lunar_anomalies[0]) -
566
+ (solar_anomalies[2] - solar_anomalies[0])) / @lunar_unit + mean_motion)
567
+ end
568
+
569
+ # 経朔 - 定朔 ( D 方式 - 差分)
570
+ def _anomaly_d(mean_lunation, year, solar_unit, mean_motion)
571
+
572
+ # 遅速差(月の中心差) / (日 / 10000_0000)
573
+ lunar_anomalies = [0,1].map {|day|
574
+ equation_of_centre(((mean_lunation + day + @anomalistic_month_shift) % @anomalistic_month_length) / @lunar_unit, @m)
575
+ }
576
+
577
+ # 盈縮差(太陽の中心差) / (日 / 10000_0000)
578
+ solar_anomalies = (0..@solar_weight).to_a.map {|day|
579
+ solar_unit * equation_of_centre(((mean_lunation + day - _perihelion(year)) / solar_unit) % @year_length, @s)
580
+ }
581
+ solar_anomalies[1] ||= solar_anomalies[0]
582
+
583
+ # 経朔 - 定朔
584
+ (lunar_anomalies[0] - solar_anomalies[0]) / ((lunar_anomalies[1] - lunar_anomalies[0]) -
585
+ (solar_anomalies[1] - solar_anomalies[0]) + mean_motion)
586
+ end
587
+
588
+ # 経朔 - 定朔 ( B 方式 - 微分)
589
+ def _anomaly_b(mean_lunation, year, solar_unit, mean_motion)
590
+
591
+ # 遅速差(月の中心差) / (日 / 10000_0000)
592
+ lunar_anomalies = [0,1].map {|diff|
593
+ equation_of_centre(((mean_lunation + @anomalistic_month_shift) % @anomalistic_month_length) / @lunar_unit, @m, diff)
594
+ }
595
+
596
+ # 盈縮差(太陽の中心差) / (日 / 10000_0000)
597
+ solar_anomalies = (0..@solar_weight).to_a.map {|diff|
598
+ solar_unit * equation_of_centre(((mean_lunation - _perihelion(year)) / solar_unit) % @year_length, @s, diff)
599
+ }
600
+ solar_anomalies[1] ||= 0
601
+
602
+ # 経朔 - 定朔
603
+ (lunar_anomalies[0] - solar_anomalies[0]) / (lunar_anomalies[1] / @lunar_unit -
604
+ solar_anomalies[1] / solar_unit + mean_motion)
605
+ end
606
+
607
+ # 経朔 - 定朔 ( C 方式 - 幾何学的補正)
608
+ def _anomaly_c(mean_lunation, year, solar_unit, mean_motion)
609
+ diff = 0
610
+ loop do
611
+
612
+ # 遅速差(月の中心差) / (日 / 10000_0000)
613
+ lunar_anomaly = equation_of_centre(((mean_lunation - diff + @anomalistic_month_shift) % @anomalistic_month_length) / @lunar_unit, @m)
614
+
615
+ # 盈縮差(太陽の中心差) / (日 / 10000_0000)
616
+ solar_anomaly = solar_unit * equation_of_centre(((mean_lunation - diff - _perihelion(year)) / solar_unit) % @year_length, @s)
617
+
618
+ # 次の差分
619
+ next_diff = (lunar_anomaly - solar_anomaly) / mean_motion
620
+ return next_diff if (next_diff - diff).abs < @anomaly_precision
621
+ diff = next_diff
622
+ end
623
+ end
624
+
625
+ # 中心差およびその時間微分
626
+ def equation_of_centre(mean_anomaly, table, differential=0)
627
+ table.each do |range, base, *coefficients|
628
+ if range.include?(mean_anomaly)
629
+ diff = mean_anomaly - base
630
+ diff = diff.abs if coefficients[0].size[0] == 0
631
+ return coefficients[differential].inject(0) {|sum, coefficient| sum * diff + coefficient}
632
+ end
633
+ end
634
+ raise RangeError, 'Mean anomaly out of range: ' + mean_anomaly.to_s
635
+ end
636
+
637
+ # 立成の作成
638
+ def _initialize_rissei
639
+ @year_length = @year_length.to_f # 暦元の冬至年 / 日
640
+ @year_span = (@year_span || 1).to_i # 冬至年の改訂周期 / 年
641
+ @anomalistic_year_shift = (@anomalistic_year_shift || 0).to_f # 暦應(冬至から近日点通過までの日数)
642
+ @lunation_length = @lunation_length.to_f # 朔実(朔望月)
643
+ @lunation_shift = @lunation_shift.to_f # 閏應(暦元前経朔から暦元天正冬至までの日数)
644
+ @lunar_mean_motion = @lunar_mean_motion.to_f # 月平行(恒星天に対する月の平均運動 / 日)
645
+ @anomalistic_month_length = @anomalistic_month_length.to_f # 転終(近点月)
646
+ @anomalistic_month_shift = @anomalistic_month_shift.to_f # 転應(暦元前近/遠地点通過から暦元天正冬至までの日数)
647
+ @anomaly_method = @anomaly_method || 'a' # (経朔-定朔)の計算方法
648
+ @anomaly_precision = (@anomaly_precision || 1.0E-5).to_f # c 方式 での収束判定誤差 / 日
649
+ @solar_weight = @solar_weight || 0 # (経朔-定朔)の計算で用いる実行差での太陽盈縮の重み(0:非考慮,1:考慮)
650
+ @lunar_unit = @lunar_unit.to_f # 太陰遅速計算用招差法定数の時間の単位(限)
651
+ @m = _rissei_j(@m) # 太陰遅速計算用招差法定数
652
+ @s = _rissei_j(@s) # 太陽盈縮計算用招差法定数
653
+ end
654
+
655
+ # 招差法用の表の生成
656
+ def _rissei_j(table)
657
+ table.map {|range, base, coefficients|
658
+ sign = range.last == base ? -1 : +1
659
+ [range, base, coefficients.reverse,
660
+ (1...coefficients.size).to_a.reverse.map {|i| sign * i * coefficients[i]}]
661
+ }
662
+ end
663
+ end
664
+
665
+ # 近点月
666
+ # @return [Numeric]
667
+ #attr_reader :anomalistic_month_length
668
+
669
+ # 元期の近点角
670
+ # @return [Numeric]
671
+ #attr_reader :anomalistic_month_shift
672
+
673
+ # 日時 -> 周期番号(唐代の定朔の暦法用 cn_to_time(1L) を使用する)
674
+ #
675
+ # @param [Numeric] t ユリウス日(Terrestrial Time)
676
+ # @param [When::TM::TemporalPosition] t
677
+ #
678
+ # @return [Numeric] 周期番号
679
+ #
680
+ def time_to_cn(t)
681
+ return super unless @cycle_number_1m
682
+ time = @is_dynamical ? +t : t.to_f
683
+ cn0 = time * @cycle_number_1m + @cycle_number_0m
684
+ root(cn0, time, 0, 5) {|cn| cn_to_time(cn)}
685
+ end
686
+
687
+ # 当該日付の月の位相の変化範囲(唐代の定朔の暦法用 cn_to_time(1L) を使用する)
688
+ #
689
+ # @param [When::TM::TemporalPosition] date 日付
690
+ #
691
+ # @return [Array<Numeric>] 当該日付の月の位相の変化範囲
692
+ #
693
+ def phase_range(date)
694
+ date = date.floor
695
+ [date, date.succ].map {|d|
696
+ t = d.to_f
697
+ c = (60.0 * ((t - CYCLE_0M) * @cycle_number_1m + @cycle_number_0m)).floor
698
+ t0 = t1 = nil
699
+ loop do
700
+ t0 = cn_to_time( c / 60.0)
701
+ t1 = cn_to_time((c+1)/ 60.0)
702
+ d = ((t-t0) / (t1-t0)).round
703
+ if d.abs > 1
704
+ c += d
705
+ elsif t0 > t
706
+ c -= 1
707
+ elsif t1 <= t
708
+ c += 1
709
+ else
710
+ break
711
+ end
712
+ end
713
+ (c + (t-t0) / (t1-t0)) / 60.0
714
+ }
715
+ end
716
+
717
+ private
718
+
719
+ # オブジェクトの正規化
720
+ def _normalize(args=[], options={})
721
+ super
722
+
723
+ # 通法
724
+ @denominator = @year_length.denominator if @year_length.kind_of?(Rational)
725
+ @denominator = [@denominator||0, @lunation_length.denominator].max if @lunation_length.kind_of?(Rational)
726
+
727
+ if @formula == '1L'
728
+
729
+ # 月の位相の計算
730
+ @method ||= @year_span ? 'J' : 'A'
731
+ extend self.class.const_get("Method#{@method.upcase}")
732
+
733
+ # 立成の初期化
734
+ _initialize_rissei
735
+
736
+ elsif @year_span
737
+ # 太陽黄経の計算(消長あり)
738
+ extend MethodS
739
+ @year_span = @year_span.to_i
740
+ end
741
+
742
+ if self.kind_of?(JujiMethods)
743
+ case @year_span
744
+ when 0,1; extend JujiMethods::Y
745
+ # when 10 ; extend JujiMethods::D
746
+ else ; extend JujiMethods::C
747
+ end
748
+ end
749
+ end
750
+ end
751
+ end
752
+
753
+ module CalendarTypes
754
+
755
+ #
756
+ # Chinese Solar Calendar
757
+ #
758
+ class ChineseSolar < EphemerisBasedSolar
759
+
760
+ class << self
761
+ #
762
+ # 太陰太陽暦の定義から太陰太陽暦と太陽暦(節月)の組を作る
763
+ #
764
+ # @private
765
+ def twin(area, definition)
766
+ definition.inject([]) {|list, cal|
767
+ if cal.kind_of?(Array) && cal[0] == ChineseLuniSolar
768
+ solar_name = cal[1].sub(/=?\]/, '(節月)=]')
769
+ lunisolar = cal.dup << "twin:#{area}::" + solar_name.gsub(/(name:\[|=?\])/,'')
770
+ solar = cal.dup << "twin:#{area}::" + cal[1].gsub(/(name:\[|=?\])/,'')
771
+ solar[0..1] = [ChineseSolar, solar_name]
772
+ list << lunisolar << solar
773
+ else
774
+ list << cal
775
+ end
776
+ }
777
+ end
778
+
779
+ #
780
+ # 盈縮差の表の時間の単位を調整する
781
+ #
782
+ # @private
783
+ def change_unit(unit, definition)
784
+ definition.map {|line|
785
+ line.map {|item|
786
+ case item
787
+ when Range ; Range.new(item.first*unit, item.last*unit, item.exclude_end?)
788
+ when Numeric ; item*unit
789
+ else ; item
790
+ end
791
+ }
792
+ }
793
+ end
794
+ end
795
+
796
+ #
797
+ # @return [When::CalendarTypes::ChineseLuniSolar] 対で用いる太陰太陽暦の名前
798
+ #
799
+ attr_reader :twin
800
+
801
+ # @private
802
+ attr_reader :doyo
803
+
804
+ private
805
+
806
+ # オブジェクトの正規化
807
+ #
808
+ # @formula = 太陽黄経の計算に用いるEphemeris
809
+ #
810
+ def _normalize(args=[], options={})
811
+ @label ||= 'Chinese::ChineseSolar'
812
+ @formula ||= ['Formula']
813
+ @formula = Array(@formula)
814
+ @formula *= 2 if @formula.length == 1
815
+ @formula[0] += (@formula[0] =~ /\?/ ? '&' : '?') + 'formula=12S' if @formula[0].kind_of?(String)
816
+ @formula[1] += (@formula[1] =~ /\?/ ? '&' : '?') + 'formula=1L' if @formula[1].kind_of?(String)
817
+ @note ||= When.CalendarNote('Chinese')
818
+ @indices ||= [
819
+ When.Index('Chinese::Month'),
820
+ When::Coordinates::DefaultDayIndex
821
+ ]
822
+ super
823
+ end
824
+ end
825
+
826
+ #
827
+ # Chinese Luni-Solar Calendar
828
+ #
829
+ class ChineseLuniSolar < EphemerisBasedLuniSolar
830
+
831
+ #
832
+ # @return [When::CalendarTypes::ChineseSolar] 対で用いる太陽暦の名前
833
+ #
834
+ attr_reader :twin
835
+
836
+ # 指定の年の天正冬至を含む月以降1年分の閏月のパターン
837
+ #
838
+ # @param [Numeric] y 年
839
+ #
840
+ # @return [Array<Numeric:月番号>, Hash<Numeric:含む中気の数=>Numeric:月番号>]
841
+ #
842
+ def intercalary_pattern(y)
843
+ m = _base_month(y)
844
+ l = _base_ids(y)
845
+ c = {0=>[], 1=>[], 2=>[]}
846
+ d0 = Residue.mod(_new_month(m)-1) {|n| _new_epoch(n)}[0]
847
+ l.size.times do |i|
848
+ d1 = Residue.mod(_new_month(m+i+1)-1) {|n| _new_epoch(n)}[0]
849
+ c[d1-d0] << l[i]
850
+ d0 = d1
851
+ end
852
+ c.delete(1)
853
+ [l, c]
854
+ end
855
+
856
+ private
857
+
858
+ # オブジェクトの正規化
859
+ #
860
+ # @cycle_offset = 雨水の場合 -1
861
+ # @formula = 太陽黄経および月の位相の計算に用いるEphemeris
862
+ #
863
+ def _normalize(args=[], options={})
864
+ @label ||= 'Chinese::ChineseLuniSolar'
865
+ @formula ||= ['Formula']
866
+ @formula = Array(@formula)
867
+ @formula *= 2 if @formula.length == 1
868
+ @formula[0] += (@formula[0] =~ /\?/ ? '&' : '?') + 'formula=12S' if @formula[0].kind_of?(String)
869
+ @formula[1] += (@formula[1] =~ /\?/ ? '&' : '?') + 'formula=1L' if @formula[1].kind_of?(String)
870
+ @vernal_month ||= 2
871
+ @cycle_offset ||= @vernal_month - 3
872
+ @base_month ||= 11
873
+ @base_month = @base_month.to_i
874
+ @intercalary_span ||= 12
875
+ @intercalary_span = @intercalary_span.to_i
876
+ @intercalary_month = (@intercalary_month.to_i - @base_month) % 12 + 1 if @intercalary_month
877
+ @note ||= When.CalendarNote('Chinese')
878
+ @indices ||= [
879
+ When.Index('Chinese::Month', {:branch=>{1=>'_m:Calendar::閏'}}),
880
+ When::Coordinates::DefaultDayIndex
881
+ ]
882
+ super
883
+ end
884
+
885
+ # 正月の通月
886
+ #
887
+ # @param [Integer] y 年
888
+ #
889
+ # @return [Numeric] 正月の通月
890
+ #
891
+ def _new_year_month_(y)
892
+ return _base_month(y) if @base_month == 1
893
+ intercalary = 0
894
+ _ids([y-1]).each do |v|
895
+ unless v.branch == 0
896
+ intercalary = v.trunk
897
+ break
898
+ end
899
+ end
900
+ _base_month(y) - @base_month + (intercalary>=@base_month ? 14 : 13)
901
+ end
902
+
903
+ # 天正冬至月の通月
904
+ #
905
+ # @param [Integer] y 年
906
+ #
907
+ # @return [Numeric] 天正冬至月の通月
908
+ #
909
+ def _base_month_(y)
910
+ (Residue.mod(solar_sdn(@formula[0].cn_to_time(12*(y-1) + @base_month - @vernal_month))) {|m| _new_month(m)})[0]
911
+ end
912
+
913
+ # 暦年の翻訳表の取得
914
+ #
915
+ # @param [Array<Numeric>] date ( 年 )
916
+ #
917
+ # @return [When::Coordinates::Pair] 暦年の翻訳表
918
+ #
919
+ def _ids_(date)
920
+ y = +date[0]
921
+ return _base_ids(y) if @base_month == 1
922
+ (_base_ids(y).dup.delete_if {|v| v.trunk >= @base_month}) + (_base_ids(y+1).dup.delete_if {|v| v.trunk < @base_month})
923
+ end
924
+
925
+ # 天正冬至月から1年分の翻訳表の取得
926
+ #
927
+ # @param [Numeric] y 年
928
+ #
929
+ # @return [When::Coordinates::Pair]
930
+ # 天正冬至月から1年分の翻訳表
931
+ #
932
+ def _base_ids_(y)
933
+ _intercalary_pattern(y,12)[1..-1].inject([Pair._force_pair(@base_month, 0)]) do |base_ids, flag|
934
+ base_ids << (flag ? Pair._force_pair(base_ids[-1].trunk, 1) : Pair._force_pair(base_ids[-1].trunk % 12 + 1, 0))
935
+ end
936
+ end
937
+
938
+ # 天正冬至月から1年分の閏月のパターンの取得
939
+ #
940
+ # @param [Numeric] y 年
941
+ #
942
+ # @return [Boolean]
943
+ # [ true - 閏月である ]
944
+ # [ false - 閏月でない ]
945
+ #
946
+ def _intercalary_pattern(y, n)
947
+ m0 = _base_month(y)
948
+ m1 = _base_month(y + n/12.0)
949
+ return Array.new(n, false) if m1-m0 == n
950
+ return Array.new(n+1) {|i| i==@intercalary_month} if @intercalary_month # for 四分暦
951
+ return _intercalary_pattern(y, n/2) + _intercalary_pattern(y + n/24.0, n/2) if n > @intercalary_span
952
+ flags = Array.new(n+1, false)
953
+ n.times do |i|
954
+ m0 += 1
955
+ if _intercalary?(m0)
956
+ flags[i+1] = true
957
+ return flags
958
+ end
959
+ end
960
+ raise ArgumentError, "Intercalary month not found"
961
+ end
962
+
963
+ # 指定の月の中気の有無
964
+ #
965
+ # @param [Numeric] m 通月
966
+ #
967
+ # @return [Boolean]
968
+ # [ true - 中気無し ]
969
+ # [ false - 中気有り ]
970
+ #
971
+ def _intercalary?(m)
972
+ e = _new_month(m+1) - 1
973
+ d = Residue.mod(e) {|n| _new_epoch(n)}
974
+ e - d[1] < _new_month(m)
975
+ end
976
+ end
977
+
978
+ #
979
+ # 太平天国 2.1.1-3.2.30
980
+ #
981
+ TenrekiA = [CyclicTableBased, {
982
+ 'origin_of_LSC' => 2397523,
983
+ 'origin_of_MSC' => 1852,
984
+ 'indices' => [
985
+ When.Index('Chinese::Month', {:unit =>12}),
986
+ When::Coordinates::DefaultDayIndex
987
+ ],
988
+ 'rule_table' => {
989
+ 'T' => {'Rule' =>[365]},
990
+ 365 => {'Length'=>[31,30]*5 + [30]*2}
991
+ }
992
+ }]
993
+
994
+ #
995
+ # 太平天国 3.3.1-
996
+ #
997
+ TenrekiB = [CyclicTableBased, {
998
+ 'origin_of_LSC' => 2397522,
999
+ 'origin_of_MSC' => 1852,
1000
+ 'indices' => [
1001
+ When.Index('Chinese::Month', {:unit =>12}),
1002
+ When.Index({:shift => 1})
1003
+ ],
1004
+ 'rule_table' => {
1005
+ 'T' => {'Rule' =>[366]},
1006
+ 366 => {'Length'=>[31,30]*6}
1007
+ },
1008
+ 'note' => 'Default'
1009
+ }]
1010
+
1011
+ #
1012
+ # 彝
1013
+ #
1014
+ Yi = [CyclicTableBased, {
1015
+ 'label' => 'Chinese::Yi',
1016
+ 'origin_of_LSC' => 1721431,
1017
+ 'origin_of_MSC' => 1,
1018
+ 'indices' => [
1019
+ When.Index('Yi::Month', {:unit =>11}),
1020
+ When::Coordinates::DefaultDayIndex
1021
+ ],
1022
+ 'rule_table' => {
1023
+ 'T' => {'Rule' =>[365, 365, 365, 366]},
1024
+ 365 => {'Length'=>[36]*10 + [5]},
1025
+ 366 => {'Length'=>[36]*10 + [6]}
1026
+ },
1027
+ 'note' => 'Yis'
1028
+ }]
1029
+ end
1030
+ end