when_exe 0.4.1 → 0.4.2

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