when_exe 0.3.8 → 0.3.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|