when_exe 0.3.8 → 0.3.9

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