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