when_exe 0.4.1 → 0.4.2

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