mk_cal_jpl 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/Gemfile +9 -0
- data/Guardfile +70 -0
- data/LICENSE.txt +21 -0
- data/README.md +107 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/exe/mk_cal_jpl +34 -0
- data/lib/mk_cal_jpl.rb +14 -0
- data/lib/mk_cal_jpl/argument.rb +44 -0
- data/lib/mk_cal_jpl/calendar.rb +87 -0
- data/lib/mk_cal_jpl/compute.rb +746 -0
- data/lib/mk_cal_jpl/const.rb +61 -0
- data/lib/mk_cal_jpl/version.rb +3 -0
- data/mk_cal_jpl.gemspec +35 -0
- metadata +134 -0
@@ -0,0 +1,746 @@
|
|
1
|
+
require 'mk_time'
|
2
|
+
|
3
|
+
module MkCalJpl
|
4
|
+
module Compute
|
5
|
+
module_function
|
6
|
+
|
7
|
+
#=========================================================================
|
8
|
+
# 休日の計算
|
9
|
+
#
|
10
|
+
# @param: year
|
11
|
+
# @param: month
|
12
|
+
# @param: day
|
13
|
+
# @return: holiday (漢字1文字)
|
14
|
+
#=========================================================================
|
15
|
+
def compute_holiday(year, month, day)
|
16
|
+
holiday_0 = Array.new # 変動の祝日用
|
17
|
+
holiday_1 = Array.new # 国民の休日用
|
18
|
+
holiday_2 = Array.new # 振替休日用
|
19
|
+
|
20
|
+
# 変動の祝日の日付・曜日を計算 ( 振替休日,国民の休日を除く )
|
21
|
+
Const::HOLIDAY.each do |holiday|
|
22
|
+
unless holiday[1] == 99
|
23
|
+
unless holiday[2] == 99 # 月日が既定のもの
|
24
|
+
jd_jst = gc2jd(year, holiday[1], holiday[2]) + Const::JST_D
|
25
|
+
yobi = compute_yobi(jd_jst)
|
26
|
+
holiday_0 << [holiday[1], holiday[2], holiday[0], jd_jst, yobi]
|
27
|
+
else # 月日が不定のもの
|
28
|
+
if holiday[3] == 21 # 第2月曜日 ( 8 - 14 の月曜日)
|
29
|
+
8.upto(14) do |d|
|
30
|
+
jd_jst = gc2jd(year, holiday[1], d) + Const::JST_D
|
31
|
+
yobi = compute_yobi(jd_jst)
|
32
|
+
holiday_0 << [holiday[1], d, holiday[0], jd_jst, "月"] if yobi == "月"
|
33
|
+
end
|
34
|
+
elsif holiday[3] == 31 # 第3月曜日 ( 15 - 21 の月曜日)
|
35
|
+
15.upto(21) do |d|
|
36
|
+
jd_jst = gc2jd(year, holiday[1], d) + Const::JST_D
|
37
|
+
yobi = compute_yobi(jd_jst)
|
38
|
+
holiday_0 << [holiday[1], d, holiday[0], jd_jst, "月"] if yobi == "月"
|
39
|
+
end
|
40
|
+
elsif holiday[3] == 80 # 春分の日
|
41
|
+
jd_jst = gc2jd(year, holiday[1], 31) + Const::JST_D
|
42
|
+
nibun_jd = compute_last_nc(jd_jst, 90)[0]
|
43
|
+
d = jd2ymd(nibun_jd)[2]
|
44
|
+
wk_jd = gc2jd(year, holiday[1], d) + Const::JST_D
|
45
|
+
yobi = compute_yobi(wk_jd)
|
46
|
+
holiday_0 << [holiday[1], d, holiday[0], wk_jd, yobi]
|
47
|
+
elsif holiday[3] == 81 # 秋分の日
|
48
|
+
jd_jst = gc2jd(year, holiday[1], 30) + Const::JST_D
|
49
|
+
nibun_jd = compute_last_nc(jd_jst, 90)[0]
|
50
|
+
d = jd2ymd(nibun_jd)[2]
|
51
|
+
wk_jd = gc2jd(year, holiday[1], d) + Const::JST_D
|
52
|
+
yobi = compute_yobi(wk_jd)
|
53
|
+
holiday_0 << [holiday[1], d, holiday[0], wk_jd, yobi]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# 国民の休日計算
|
60
|
+
# ( 「国民の祝日」で前後を挟まれた「国民の祝日」でない日 )
|
61
|
+
# ( 年またぎは考慮していない(今のところ不要) )
|
62
|
+
0.upto(holiday_0.length - 2) do |i|
|
63
|
+
if holiday_0[i][3] + 2 == holiday_0[i + 1][3]
|
64
|
+
jd = holiday_0[i][3] + 1
|
65
|
+
yobi = Const::YOBI[Const::YOBI.index(holiday_0[i][4]) + 1]
|
66
|
+
wk_ary = Array.new
|
67
|
+
wk_ary << jd2ymd(jd)[1]
|
68
|
+
wk_ary << jd2ymd(jd)[2]
|
69
|
+
wk_ary << 90
|
70
|
+
wk_ary << jd
|
71
|
+
wk_ary << yobi
|
72
|
+
holiday_1 << wk_ary
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# 振替休日計算
|
77
|
+
# ( 「国民の祝日」が日曜日に当たるときは、
|
78
|
+
# その日後においてその日に最も近い「国民の祝日」でない日 )
|
79
|
+
0.upto(holiday_0.length - 1) do |i|
|
80
|
+
if holiday_0[i][4] == "日"
|
81
|
+
next_jd = holiday_0[i][3] + 1
|
82
|
+
next_yobi = Const::YOBI[Const::YOBI.index(holiday_0[i][4]) + 1]
|
83
|
+
if i == holiday_0.length - 1
|
84
|
+
wk_ary = Array.new
|
85
|
+
wk_ary << jd2ymd(next_jd)[1]
|
86
|
+
wk_ary << jd2ymd(next_jd)[2]
|
87
|
+
wk_ary << 91
|
88
|
+
wk_ary << next_jd
|
89
|
+
wk_ary << next_yobi
|
90
|
+
else
|
91
|
+
flg_furikae = 0
|
92
|
+
plus_day = 1
|
93
|
+
while flg_furikae == 0
|
94
|
+
if i + plus_day < holiday_0.length
|
95
|
+
if next_jd == holiday_0[i + plus_day][3]
|
96
|
+
next_jd += 1
|
97
|
+
next_yobi = next_yobi == "土" ? "日" : Const::YOBI[Const::YOBI.index(next_yobi) + 1]
|
98
|
+
plus_day += 1
|
99
|
+
else
|
100
|
+
flg_furikae = 1
|
101
|
+
wk_ary = Array.new
|
102
|
+
wk_ary << jd2ymd(next_jd)[1]
|
103
|
+
wk_ary << jd2ymd(next_jd)[2]
|
104
|
+
wk_ary << 91
|
105
|
+
wk_ary << next_jd
|
106
|
+
wk_ary << next_yobi
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
holiday_2 << wk_ary
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
# 配列整理
|
116
|
+
code = 99
|
117
|
+
(holiday_0 + holiday_1 + holiday_2).sort.each do |holiday|
|
118
|
+
if holiday[0] == month && holiday[1] == day
|
119
|
+
code = holiday[2]
|
120
|
+
break
|
121
|
+
end
|
122
|
+
end
|
123
|
+
holiday = ""
|
124
|
+
res = Const::HOLIDAY.select { |h| h[0] == code }
|
125
|
+
holiday = res[0][4] unless res == []
|
126
|
+
return holiday
|
127
|
+
end
|
128
|
+
|
129
|
+
#=========================================================================
|
130
|
+
# 二十四節気の計算
|
131
|
+
#
|
132
|
+
# @param: jd (ユリウス日(JST))
|
133
|
+
# @return: sekki_24 (二十四節気の文字列)
|
134
|
+
#=========================================================================
|
135
|
+
def compute_sekki_24(jd)
|
136
|
+
lsun_today = compute_lambda(jd)
|
137
|
+
lsun_tomorrow = compute_lambda(jd + 1)
|
138
|
+
lsun_today0 = 15 * (lsun_today / 15.0).truncate
|
139
|
+
lsun_tomorrow0 = 15 * (lsun_tomorrow / 15.0).truncate
|
140
|
+
return lsun_today0 == lsun_tomorrow0 ? "" : Const::SEKKI_24[lsun_tomorrow0 / 15]
|
141
|
+
end
|
142
|
+
|
143
|
+
#=========================================================================
|
144
|
+
# 雑節の計算
|
145
|
+
#
|
146
|
+
# @param: jd (ユリウス日(JST))
|
147
|
+
# @return: [雑節コード1, 雑節コード2]
|
148
|
+
#=========================================================================
|
149
|
+
def compute_zassetsu(jd)
|
150
|
+
zassetsu = Array.new
|
151
|
+
|
152
|
+
# 計算対象日の太陽の黄経
|
153
|
+
lsun_today = compute_lambda(jd)
|
154
|
+
# 計算対象日の翌日の太陽の黄経
|
155
|
+
lsun_tomorrow = compute_lambda(jd + 1)
|
156
|
+
# 計算対象日の5日前の太陽の黄経(社日計算用)
|
157
|
+
lsun_before_5 = compute_lambda(jd - 5)
|
158
|
+
# 計算対象日の4日前の太陽の黄経(社日計算用)
|
159
|
+
lsun_before_4 = compute_lambda(jd - 4)
|
160
|
+
# 計算対象日の5日後の太陽の黄経(社日計算用)
|
161
|
+
lsun_after_5 = compute_lambda(jd + 5)
|
162
|
+
# 計算対象日の6日後の太陽の黄経(社日計算用)
|
163
|
+
lsun_after_6 = compute_lambda(jd + 6)
|
164
|
+
# 太陽の黄経の整数部分( 土用, 入梅, 半夏生 計算用 )
|
165
|
+
lsun_today0 = lsun_today.truncate
|
166
|
+
lsun_tomorrow0 = lsun_tomorrow.truncate
|
167
|
+
|
168
|
+
#### ここから各種雑節計算
|
169
|
+
# 0:節分 ( 立春の前日 )
|
170
|
+
zassetsu << 0 if compute_sekki_24(jd + 1) == "立春"
|
171
|
+
# 1:彼岸入(春) ( 春分の日の3日前 )
|
172
|
+
zassetsu << 1 if compute_sekki_24(jd + 3) == "春分"
|
173
|
+
# 2:彼岸(春) ( 春分の日 )
|
174
|
+
zassetsu << 2 if compute_sekki_24(jd) == "春分"
|
175
|
+
# 3:彼岸明(春) ( 春分の日の3日後 )
|
176
|
+
zassetsu << 3 if compute_sekki_24(jd - 3) == "春分"
|
177
|
+
# 4:社日(春) ( 春分の日に最も近い戊(つちのえ)の日 )
|
178
|
+
# * 計算対象日が戊の日の時、
|
179
|
+
# * 4日後までもしくは4日前までに春分の日がある時、
|
180
|
+
# この日が社日
|
181
|
+
# * 5日後が春分の日の時、
|
182
|
+
# * 春分点(黄経0度)が午前なら
|
183
|
+
# この日が社日
|
184
|
+
# * 春分点(黄経0度)が午後なら
|
185
|
+
# この日の10日後が社日
|
186
|
+
if (jd % 10).truncate == 4 # 戊の日
|
187
|
+
# [ 当日から4日後 ]
|
188
|
+
0.upto(4) do |i|
|
189
|
+
if compute_sekki_24(jd + i) == "春分"
|
190
|
+
zassetsu << 4
|
191
|
+
break
|
192
|
+
end
|
193
|
+
end
|
194
|
+
# [ 1日前から4日前 ]
|
195
|
+
1.upto(4) do |i|
|
196
|
+
if compute_sekki_24(jd - i) == "春分"
|
197
|
+
zassetsu << 4
|
198
|
+
break
|
199
|
+
end
|
200
|
+
end
|
201
|
+
# [ 5日後 ]
|
202
|
+
if compute_sekki_24(jd + 5) == "春分"
|
203
|
+
# 春分の日の黄経(太陽)と翌日の黄経(太陽)の中間点が
|
204
|
+
# 0度(360度)以上なら、春分点が午前と判断
|
205
|
+
zassetsu << 4 if (lsun_after_5 + lsun_after_6 + 360) / 2.0 >= 360
|
206
|
+
end
|
207
|
+
# [ 5日前 ]
|
208
|
+
if compute_sekki_24(jd - 5) == "春分"
|
209
|
+
# 春分の日の黄経(太陽)と翌日の黄経(太陽)の中間点が
|
210
|
+
# 0度(360度)未満なら、春分点が午後と判断
|
211
|
+
zassetsu << 4 if (lsun_before_4 + lsun_before_5 + 360) / 2.0 < 360
|
212
|
+
end
|
213
|
+
end
|
214
|
+
# 5:土用入(春) ( 黄経(太陽) = 27度 )
|
215
|
+
unless lsun_today0 == lsun_tomorrow0
|
216
|
+
zassetsu << 5 if lsun_tomorrow0 == 27
|
217
|
+
end
|
218
|
+
# 6:八十八夜 ( 立春から88日目(87日後) )
|
219
|
+
zassetsu << 6 if compute_sekki_24(jd - 87) == "立春"
|
220
|
+
# 7:入梅 ( 黄経(太陽) = 80度 )
|
221
|
+
unless lsun_today0 == lsun_tomorrow0
|
222
|
+
zassetsu << 7 if lsun_tomorrow0 == 80
|
223
|
+
end
|
224
|
+
# 8:半夏生 ( 黄経(太陽) = 100度 )
|
225
|
+
unless lsun_today0 == lsun_tomorrow0
|
226
|
+
zassetsu << 8 if lsun_tomorrow0 == 100
|
227
|
+
end
|
228
|
+
# 9:土用入(夏) ( 黄経(太陽) = 117度 )
|
229
|
+
unless lsun_today0 == lsun_tomorrow0
|
230
|
+
zassetsu << 9 if lsun_tomorrow0 == 117
|
231
|
+
end
|
232
|
+
# 10:二百十日 ( 立春から210日目(209日後) )
|
233
|
+
zassetsu << 10 if compute_sekki_24(jd - 209) == "立春"
|
234
|
+
# 11:二百二十日 ( 立春から220日目(219日後) )
|
235
|
+
zassetsu << 11 if compute_sekki_24(jd - 219) == "立春"
|
236
|
+
# 12:彼岸入(秋) ( 秋分の日の3日前 )
|
237
|
+
zassetsu << 12 if compute_sekki_24(jd + 3) == "秋分"
|
238
|
+
# 13:彼岸(秋) ( 秋分の日 )
|
239
|
+
zassetsu << 13 if compute_sekki_24(jd) == "秋分"
|
240
|
+
# 14:彼岸明(秋) ( 秋分の日の3日後 )
|
241
|
+
zassetsu << 14 if compute_sekki_24(jd - 3) == "秋分"
|
242
|
+
# 15:社日(秋) ( 秋分の日に最も近い戊(つちのえ)の日 )
|
243
|
+
# * 計算対象日が戊の日の時、
|
244
|
+
# * 4日後までもしくは4日前までに秋分の日がある時、
|
245
|
+
# この日が社日
|
246
|
+
# * 5日後が秋分の日の時、
|
247
|
+
# * 秋分点(黄経180度)が午前なら
|
248
|
+
# この日が社日
|
249
|
+
# * 秋分点(黄経180度)が午後なら
|
250
|
+
# この日の10日後が社日
|
251
|
+
if (jd % 10).truncate == 4 # 戊の日
|
252
|
+
# [ 当日から4日後 ]
|
253
|
+
0.upto(4) do |i|
|
254
|
+
if compute_sekki_24(jd + i) == "秋分"
|
255
|
+
zassetsu << 15
|
256
|
+
break
|
257
|
+
end
|
258
|
+
end
|
259
|
+
# [ 1日前から4日前 ]
|
260
|
+
1.upto(4) do |i|
|
261
|
+
if compute_sekki_24(jd - i) == "秋分"
|
262
|
+
zassetsu << 15
|
263
|
+
break
|
264
|
+
end
|
265
|
+
end
|
266
|
+
# [ 5日後 ]
|
267
|
+
if compute_sekki_24(jd + 5) == "秋分"
|
268
|
+
# 秋分の日の黄経(太陽)と翌日の黄経(太陽)の中間点が
|
269
|
+
# 180度以上なら、秋分点が午前と判断
|
270
|
+
zassetsu << 15 if (lsun_after_5 + lsun_after_6) / 2.0 >= 180
|
271
|
+
end
|
272
|
+
# [ 5日前 ]
|
273
|
+
if compute_sekki_24(jd - 5) == "秋分"
|
274
|
+
# 秋分の日の黄経(太陽)と翌日の黄経(太陽)の中間点が
|
275
|
+
# 180度未満なら、秋分点が午後と判断
|
276
|
+
zassetsu << 15 if (lsun_before_4 + lsun_before_5) / 2.0 < 180
|
277
|
+
end
|
278
|
+
end
|
279
|
+
# 16:土用入(秋) ( 黄経(太陽) = 207度 )
|
280
|
+
unless lsun_today0 == lsun_tomorrow0
|
281
|
+
zassetsu << 16 if lsun_tomorrow0 == 207
|
282
|
+
end
|
283
|
+
# 17:土用入(冬) ( 黄経(太陽) = 297度 )
|
284
|
+
unless lsun_today0 == lsun_tomorrow0
|
285
|
+
zassetsu << 17 if lsun_tomorrow0 == 297
|
286
|
+
end
|
287
|
+
return zassetsu.map { |z| Const::ZASSETSU[z] }.join(",")
|
288
|
+
end
|
289
|
+
|
290
|
+
#=========================================================================
|
291
|
+
# 曜日の計算
|
292
|
+
#
|
293
|
+
# * 曜日 = ( ユリウス通日 + 2 ) % 7
|
294
|
+
# 0: 日曜, 1: 月曜, 2: 火曜, 3: 水曜, 4: 木曜, 5: 金曜, 6: 土曜
|
295
|
+
#
|
296
|
+
# @param: jd (ユリウス日(JST))
|
297
|
+
# @return: yobi (漢字1文字)
|
298
|
+
#=========================================================================
|
299
|
+
def compute_yobi(jd)
|
300
|
+
return Const::YOBI[(jd.to_i + 2) % 7]
|
301
|
+
end
|
302
|
+
|
303
|
+
#=========================================================================
|
304
|
+
# 干支の計算
|
305
|
+
#
|
306
|
+
# * [ユリウス日(JST) - 10日] を60で割った剰余
|
307
|
+
#
|
308
|
+
# @param: jd (ユリウス日(JST))
|
309
|
+
# @return kanshi (漢字2文字)
|
310
|
+
#=========================================================================
|
311
|
+
def compute_kanshi(jd)
|
312
|
+
return Const::KANSHI[(jd.to_i - 10) % 60]
|
313
|
+
end
|
314
|
+
|
315
|
+
#=========================================================================
|
316
|
+
# 節句の計算
|
317
|
+
#
|
318
|
+
# @param: month
|
319
|
+
# @param: day
|
320
|
+
# @return: sekku (日本語文字列)
|
321
|
+
#=========================================================================
|
322
|
+
def compute_sekku(month, day)
|
323
|
+
sekku = ""
|
324
|
+
res = Const::SEKKU.select { |s| s[1] == month && s[2] == day }
|
325
|
+
sekku = res[0][3] unless res == []
|
326
|
+
return sekku
|
327
|
+
end
|
328
|
+
|
329
|
+
#=========================================================================
|
330
|
+
# 月齢(正午)の計算
|
331
|
+
#
|
332
|
+
# @param: jd (ユリウス日(JST))
|
333
|
+
# @return: moonage
|
334
|
+
#=========================================================================
|
335
|
+
def compute_moonage(jd)
|
336
|
+
return jd - compute_saku(jd - Const::JST_D)
|
337
|
+
end
|
338
|
+
|
339
|
+
#=========================================================================
|
340
|
+
# 旧暦の計算
|
341
|
+
#
|
342
|
+
# * 旧暦一日の六曜
|
343
|
+
# 1・7月 : 先勝
|
344
|
+
# 2・8月 : 友引
|
345
|
+
# 3・9月 : 先負
|
346
|
+
# 4・10月 : 仏滅
|
347
|
+
# 5・11月 : 大安
|
348
|
+
# 6・12月 : 赤口
|
349
|
+
# と決まっていて、あとは月末まで順番通り。
|
350
|
+
# よって、月と日をたした数を6で割った余りによって六曜を決定することができます。
|
351
|
+
# ( 旧暦の月 + 旧暦の日 ) ÷ 6 = ? … 余り
|
352
|
+
# 余り 0 : 大安
|
353
|
+
# 1 : 赤口
|
354
|
+
# 2 : 先勝
|
355
|
+
# 3 : 友引
|
356
|
+
# 4 : 先負
|
357
|
+
# 5 : 仏滅
|
358
|
+
#
|
359
|
+
# @param: jd (ユリウス日(JST))
|
360
|
+
# @return: [旧暦年, 閏月Flag, 旧暦月, 旧暦日, 六曜]
|
361
|
+
#=========================================================================
|
362
|
+
def compute_oc(jd)
|
363
|
+
jd -= 0.5
|
364
|
+
tm0 = jd
|
365
|
+
# 二分二至,中気の時刻・黄経用配列宣言
|
366
|
+
chu = Array.new(4).map { Array.new(2, 0) }
|
367
|
+
# 朔用配列宣言
|
368
|
+
saku = Array.new(5, 0)
|
369
|
+
# 朔日用配列宣言
|
370
|
+
m = Array.new(5).map { Array.new(3, 0) }
|
371
|
+
# 旧暦用配列宣言
|
372
|
+
kyureki = Array.new(4, 0)
|
373
|
+
|
374
|
+
# 計算対象の直前にあたる二分二至の時刻を計算
|
375
|
+
# chu[0][0] : 二分二至の時刻
|
376
|
+
# chu[0][1] : その時の太陽黄経
|
377
|
+
chu[0] = compute_last_nc(tm0, 90)
|
378
|
+
# 中気の時刻を計算 ( 3回計算する )
|
379
|
+
# chu[i][0] : 中気の時刻
|
380
|
+
# chu[i][1] : その時の太陽黄経
|
381
|
+
1.upto(3) do |i|
|
382
|
+
chu[i] = compute_last_nc(chu[i - 1][0] + 32, 30)
|
383
|
+
end
|
384
|
+
# 計算対象の直前にあたる二分二至の直前の朔の時刻を求める
|
385
|
+
saku[0] = compute_saku(chu[0][0])
|
386
|
+
# 朔の時刻を求める
|
387
|
+
1.upto(4) do |i|
|
388
|
+
tm = saku[i-1] + 30
|
389
|
+
saku[i] = compute_saku(tm)
|
390
|
+
# 前と同じ時刻を計算した場合( 両者の差が26日以内 )には、初期値を
|
391
|
+
# +33日にして再実行させる。
|
392
|
+
if (saku[i-1].truncate - saku[i].truncate).abs <= 26
|
393
|
+
saku[i] = compute_saku(saku[i-1] + 35)
|
394
|
+
end
|
395
|
+
end
|
396
|
+
# saku[1]が二分二至の時刻以前になってしまった場合には、朔をさかのぼり過ぎ
|
397
|
+
# たと考えて、朔の時刻を繰り下げて修正する。
|
398
|
+
# その際、計算もれ(saku[4])になっている部分を補うため、朔の時刻を計算
|
399
|
+
# する。(近日点通過の近辺で朔があると起こる事があるようだ...?)
|
400
|
+
if saku[1].truncate <= chu[0][0].truncate
|
401
|
+
0.upto(3) { |i| saku[i] = saku[i+1] }
|
402
|
+
saku[4] = compute_saku(saku[3] + 35)
|
403
|
+
# saku[0]が二分二至の時刻以後になってしまった場合には、朔をさかのぼり足
|
404
|
+
# りないと見て、朔の時刻を繰り上げて修正する。
|
405
|
+
# その際、計算もれ(saku[0])になっている部分を補うため、朔の時刻を計算
|
406
|
+
# する。(春分点の近辺で朔があると起こる事があるようだ...?)
|
407
|
+
elsif saku[0].truncate > chu[0][0].truncate
|
408
|
+
4.downto(1) { |i| saku[i] = saku[i-1] }
|
409
|
+
saku[0] = compute_saku(saku[0] - 27)
|
410
|
+
end
|
411
|
+
# 閏月検索Flagセット
|
412
|
+
# (節月で4ヶ月の間に朔が5回あると、閏月がある可能性がある。)
|
413
|
+
# leap=0:平月 leap=1:閏月
|
414
|
+
leap = 0
|
415
|
+
leap = 1 if saku[4].truncate <= chu[3][0].truncate
|
416
|
+
# 朔日行列の作成
|
417
|
+
# m[i][0] ... 月名 ( 1:正月 2:2月 3:3月 .... )
|
418
|
+
# m[i][1] ... 閏フラグ ( 0:平月 1:閏月 )
|
419
|
+
# m[i][2] ... 朔日のjd
|
420
|
+
m[0][0] = (chu[0][1] / 30.0).truncate + 2
|
421
|
+
m[0][0] -= 12 if m[0][0] > 12
|
422
|
+
m[0][2] = saku[0].truncate
|
423
|
+
m[0][1] = 0
|
424
|
+
1.upto(4) do |i|
|
425
|
+
if leap == 1 && i != 1
|
426
|
+
if chu[i-1][0].truncate <= saku[i-1].truncate ||
|
427
|
+
chu[i-1][0].truncate >= saku[i].truncate
|
428
|
+
m[i-1][0] = m[i-2][0]
|
429
|
+
m[i-1][1] = 1
|
430
|
+
m[i-1][2] = saku[i-1].truncate
|
431
|
+
leap = 0
|
432
|
+
end
|
433
|
+
end
|
434
|
+
m[i][0] = m[i-1][0] + 1
|
435
|
+
m[i][0] -= 12 if m[i][0] > 12
|
436
|
+
m[i][2] = saku[i].truncate
|
437
|
+
m[i][1] = 0
|
438
|
+
end
|
439
|
+
# 朔日行列から旧暦を求める。
|
440
|
+
state, index = 0, 0
|
441
|
+
0.upto(4) do |i|
|
442
|
+
index = i
|
443
|
+
if tm0.truncate < m[i][2].truncate
|
444
|
+
state = 1
|
445
|
+
break
|
446
|
+
elsif tm0.truncate == m[i][2].truncate
|
447
|
+
state = 2
|
448
|
+
break
|
449
|
+
end
|
450
|
+
end
|
451
|
+
index -= 1 if state == 1
|
452
|
+
kyureki[1] = m[index][1]
|
453
|
+
kyureki[2] = m[index][0]
|
454
|
+
kyureki[3] = tm0.truncate - m[index][2].truncate + 1
|
455
|
+
# 旧暦年の計算
|
456
|
+
# (旧暦月が10以上でかつ新暦月より大きい場合には、
|
457
|
+
# まだ年を越していないはず...)
|
458
|
+
a = jd2ymd(tm0)
|
459
|
+
kyureki[0] = a[0]
|
460
|
+
kyureki[0] -= 1 if kyureki[2] > 9 && kyureki[2] > a[1]
|
461
|
+
# 六曜
|
462
|
+
kyureki[4] = Const::ROKUYO[(kyureki[2] + kyureki[3]) % 6]
|
463
|
+
return kyureki
|
464
|
+
end
|
465
|
+
|
466
|
+
#=========================================================================
|
467
|
+
# 直前二分二至・中気時刻の計算
|
468
|
+
#
|
469
|
+
# @param: jd (ユリウス日)
|
470
|
+
# @param: kbn (90: 二分二至, 30: 中気)
|
471
|
+
# @return: [二分二至・中気の時刻, その時の黄経]
|
472
|
+
#=========================================================================
|
473
|
+
def compute_last_nc(jd, kbn)
|
474
|
+
jd -= 0.5
|
475
|
+
# 時刻引数を分解
|
476
|
+
tm1 = jd.truncate # 整数部分
|
477
|
+
tm2 = jd - tm1 # 小数部分
|
478
|
+
tm2 -= Const::JST_D
|
479
|
+
|
480
|
+
# 直前の二分二至の黄経 λsun0 を求める
|
481
|
+
rm_sun = compute_lambda(jd + 0.5)
|
482
|
+
rm_sun0 = kbn * (rm_sun / kbn.to_f).truncate
|
483
|
+
|
484
|
+
# 繰り返し計算によって直前の二分二至の時刻を計算する
|
485
|
+
# (誤差が±1.0 sec以内になったら打ち切る。)
|
486
|
+
delta_t1 = 0 ; delta_t2 = 1
|
487
|
+
while (delta_t1 + delta_t2).abs > (1.0 / 86400.0)
|
488
|
+
# λsun を計算
|
489
|
+
t = tm1 + tm2 + Const::JST_D + 0.5
|
490
|
+
rm_sun = compute_lambda(t)
|
491
|
+
|
492
|
+
# 黄経差 Δλ=λsun -λsun0
|
493
|
+
delta_rm = rm_sun - rm_sun0
|
494
|
+
|
495
|
+
# Δλの引き込み範囲(±180°)を逸脱した場合には、補正を行う
|
496
|
+
case
|
497
|
+
when delta_rm > 180; delta_rm -= 360
|
498
|
+
when delta_rm < -180; delta_rm += 360
|
499
|
+
end
|
500
|
+
|
501
|
+
# 時刻引数の補正値 Δt
|
502
|
+
delta_t1 = (delta_rm * 365.2 / 360.0).truncate
|
503
|
+
delta_t2 = delta_rm * 365.2 / 360.0 - delta_t1
|
504
|
+
|
505
|
+
# 時刻引数の補正
|
506
|
+
tm1 = tm1 - delta_t1
|
507
|
+
tm2 = tm2 - delta_t2
|
508
|
+
if tm2 < 0
|
509
|
+
tm2 += 1
|
510
|
+
tm1 -= 1
|
511
|
+
end
|
512
|
+
end
|
513
|
+
|
514
|
+
# nibun_chu[0] : 時刻引数を合成、DT ==> JST 変換を行い、戻り値とする
|
515
|
+
# ( 補正時刻=0.0sec と仮定して計算 )
|
516
|
+
# nibun_chu[1] : 黄経
|
517
|
+
nibun_chu = Array.new(2, 0)
|
518
|
+
nibun_chu[0] = tm2 + 9 / 24.0
|
519
|
+
nibun_chu[0] += tm1
|
520
|
+
nibun_chu[1] = rm_sun0
|
521
|
+
return nibun_chu
|
522
|
+
end
|
523
|
+
|
524
|
+
#=========================================================================
|
525
|
+
# 直近の朔の時刻(JST)の計算
|
526
|
+
#
|
527
|
+
# @param: jd (ユリウス日)
|
528
|
+
# @return: saku (直前の朔の時刻)
|
529
|
+
#=========================================================================
|
530
|
+
def compute_saku(jd)
|
531
|
+
lc = 1
|
532
|
+
|
533
|
+
# 時刻引数を分解する
|
534
|
+
tm1 = jd.truncate
|
535
|
+
tm2 = jd - tm1
|
536
|
+
tm2 -= Const::JST_D
|
537
|
+
|
538
|
+
# 繰り返し計算によって朔の時刻を計算する
|
539
|
+
# (誤差が±1.0 sec以内になったら打ち切る。)
|
540
|
+
delta_t1 = 0 ; delta_t2 = 1
|
541
|
+
while (delta_t1 + delta_t2).abs > (1.0 / 86400.0)
|
542
|
+
# 太陽の黄経λsun ,月の黄経λmoon を計算
|
543
|
+
t = tm1 + tm2 + Const::JST_D + 0.5
|
544
|
+
rm_sun = compute_lambda(t)
|
545
|
+
rm_moon = compute_alpha(t)
|
546
|
+
# 月と太陽の黄経差Δλ
|
547
|
+
# Δλ=λmoon-λsun
|
548
|
+
delta_rm = rm_moon - rm_sun
|
549
|
+
# ループの1回目 ( lc = 1 ) で delta_rm < 0.0 の場合には引き込み範囲に
|
550
|
+
# 入るように補正する
|
551
|
+
if lc == 1 && delta_rm < 0
|
552
|
+
delta_rm = norm_angle(delta_rm)
|
553
|
+
# 春分の近くで朔がある場合 ( 0 ≦λsun≦ 20 ) で、月の黄経λmoon≧300 の
|
554
|
+
# 場合には、Δλ= 360.0 - Δλ と計算して補正する
|
555
|
+
elsif rm_sun >= 0 && rm_sun <= 20 && rm_moon >= 300
|
556
|
+
delta_rm = norm_angle(delta_rm)
|
557
|
+
delta_rm = 360 - delta_rm
|
558
|
+
# Δλの引き込み範囲 ( ±40° ) を逸脱した場合には、補正を行う
|
559
|
+
elsif delta_rm.abs > 40.0
|
560
|
+
delta_rm = norm_angle(delta_rm)
|
561
|
+
end
|
562
|
+
# 時刻引数の補正値 Δt
|
563
|
+
delta_t1 = (delta_rm * 29.530589 / 360.0).truncate
|
564
|
+
delta_t2 = delta_rm * 29.530589 / 360.0 - delta_t1
|
565
|
+
# 時刻引数の補正
|
566
|
+
tm1 = tm1 - delta_t1
|
567
|
+
tm2 = tm2 - delta_t2
|
568
|
+
if tm2 < 0
|
569
|
+
tm2 += 1
|
570
|
+
tm1 -= 1
|
571
|
+
end
|
572
|
+
# ループ回数が15回になったら、初期値 tm を tm-26 とする。
|
573
|
+
if lc == 15 && (delta_t1 + delta_t2).abs > (1.0 / 86400.0)
|
574
|
+
tm1 = (jd - 26).truncate
|
575
|
+
tm2 = 0
|
576
|
+
# 初期値を補正したにも関わらず、振動を続ける場合には初期値を答えとして
|
577
|
+
# 返して強制的にループを抜け出して異常終了させる。
|
578
|
+
elsif lc > 30 && (delta_t1+delta_t2).abs > (1.0 / 86400.0)
|
579
|
+
tm1 = jd
|
580
|
+
tm2 = 0
|
581
|
+
break
|
582
|
+
end
|
583
|
+
lc += 1
|
584
|
+
end
|
585
|
+
# 時刻引数を合成、DT ==> JST 変換を行い、戻り値とする
|
586
|
+
# (補正時刻=0.0sec と仮定して計算)
|
587
|
+
return tm2 + tm1 + 9 / 24.0
|
588
|
+
end
|
589
|
+
|
590
|
+
#=========================================================================
|
591
|
+
# Gregorian Calendar -> Julian Day
|
592
|
+
#
|
593
|
+
# * フリーゲルの公式を使用する
|
594
|
+
# [ JD ] = int( 365.25 × year )
|
595
|
+
# + int( year / 400 )
|
596
|
+
# - int( year / 100 )
|
597
|
+
# + int( 30.59 ( month - 2 ) )
|
598
|
+
# + day
|
599
|
+
# + 1721088
|
600
|
+
# ※上記の int( x ) は厳密には、x を超えない最大の整数
|
601
|
+
# ( ちなみに、[ 準JD ]を求めるなら + 1721088.5 が - 678912 となる )
|
602
|
+
#
|
603
|
+
# @param: year
|
604
|
+
# @param: month
|
605
|
+
# @param: day
|
606
|
+
# @param: hour
|
607
|
+
# @param: minute
|
608
|
+
# @param: second
|
609
|
+
# @return: jd ( ユリウス日 )
|
610
|
+
#=========================================================================
|
611
|
+
def gc2jd(year, month, day, hour = 0, min = 0, sec = 0)
|
612
|
+
# 1月,2月は前年の13月,14月とする
|
613
|
+
if month < 3
|
614
|
+
year -= 1
|
615
|
+
month += 12
|
616
|
+
end
|
617
|
+
# 日付(整数)部分計算
|
618
|
+
jd = (365.25 * year).truncate
|
619
|
+
jd += (year / 400.0).truncate
|
620
|
+
jd -= (year / 100.0).truncate
|
621
|
+
jd += (30.59 * (month - 2)).truncate
|
622
|
+
jd += day
|
623
|
+
jd += 1721088.125
|
624
|
+
# 時間(小数)部分計算
|
625
|
+
t = sec / 3600.0
|
626
|
+
t += min / 60.0
|
627
|
+
t += hour
|
628
|
+
t = t / 24.0
|
629
|
+
return jd + t
|
630
|
+
end
|
631
|
+
|
632
|
+
#=========================================================================
|
633
|
+
# Julian Day -> UT
|
634
|
+
#
|
635
|
+
# @param: jd (ユリウス日)
|
636
|
+
# @return: [year, month, day, hour, minute, second]
|
637
|
+
#=========================================================================
|
638
|
+
def jd2ymd(jd)
|
639
|
+
ut = Array.new(6, 0)
|
640
|
+
x0 = (jd + 68570).truncate
|
641
|
+
x1 = (x0 / 36524.25).truncate
|
642
|
+
x2 = x0 - (36524.25 * x1 + 0.75).truncate
|
643
|
+
x3 = ((x2 + 1) / 365.2425).truncate
|
644
|
+
x4 = x2 - (365.25 * x3).truncate + 31
|
645
|
+
x5 = (x4.truncate / 30.59).truncate
|
646
|
+
x6 = (x5.truncate / 11.0).truncate
|
647
|
+
ut[2] = x4 - (30.59 * x5).truncate
|
648
|
+
ut[1] = x5 - 12 * x6 + 2
|
649
|
+
ut[0] = 100 * (x1 - 49) + x3 + x6
|
650
|
+
# 2月30日の補正
|
651
|
+
if ut[1]==2 && ut[2] > 28
|
652
|
+
if ut[0] % 100 == 0 && ut[0] % 400 == 0
|
653
|
+
ut[2] = 29
|
654
|
+
elsif ut[0] % 4 == 0
|
655
|
+
ut[2] = 29
|
656
|
+
else
|
657
|
+
ut[2] = 28
|
658
|
+
end
|
659
|
+
end
|
660
|
+
tm = 86400 * (jd - jd.truncate)
|
661
|
+
ut[3] = (tm / 3600.0).truncate
|
662
|
+
ut[4] = ((tm - 3600 * ut[3]) / 60.0).truncate
|
663
|
+
#ut[5] = (tm - 3600 * ut[3] - 60 * ut[4]).truncate
|
664
|
+
ut[5] = tm - 3600 * ut[3] - 60 * ut[4]
|
665
|
+
return ut
|
666
|
+
end
|
667
|
+
|
668
|
+
#=========================================================================
|
669
|
+
# 角度の正規化
|
670
|
+
#
|
671
|
+
# @param: angle
|
672
|
+
# @return: angle
|
673
|
+
#=========================================================================
|
674
|
+
def norm_angle(angle)
|
675
|
+
if angle < 0
|
676
|
+
angle1 = angle * (-1)
|
677
|
+
angle2 = (angle1 / 360.0).truncate
|
678
|
+
angle1 -= 360 * angle2
|
679
|
+
angle1 = 360 - angle1
|
680
|
+
else
|
681
|
+
angle1 = (angle / 360.0).truncate
|
682
|
+
angle1 = angle - 360.0 * angle1
|
683
|
+
end
|
684
|
+
return angle1
|
685
|
+
end
|
686
|
+
|
687
|
+
#=========================================================================
|
688
|
+
# ΔT の計算
|
689
|
+
#
|
690
|
+
# * 1972-01-01 以降、うるう秒挿入済みの年+αまでは、以下で算出
|
691
|
+
# TT - UTC = ΔT + DUT1 = TAI + 32.184 - UTC = ΔAT + 32.184
|
692
|
+
# [うるう秒実施日一覧](http://jjy.nict.go.jp/QandA/data/leapsec.html)
|
693
|
+
#
|
694
|
+
# @param: year
|
695
|
+
# @param: month
|
696
|
+
# @param: day
|
697
|
+
# @return: dt
|
698
|
+
#=========================================================================
|
699
|
+
def compute_dt(year, month, day)
|
700
|
+
ymd = sprintf("%04d%02d%02d", year, month, day)
|
701
|
+
tm = MkTime.new(ymd)
|
702
|
+
return tm.dt
|
703
|
+
end
|
704
|
+
|
705
|
+
#=========================================================================
|
706
|
+
# 六曜の計算
|
707
|
+
#
|
708
|
+
#
|
709
|
+
# @param: oc_month (旧暦の月)
|
710
|
+
# @param: oc_day (旧暦の日)
|
711
|
+
# @return: rokuyo (漢字2文字)
|
712
|
+
#=========================================================================
|
713
|
+
def compute_rokuyo(oc_month, oc_day)
|
714
|
+
return Const::ROKUYO[(oc_month + oc_day) % 6]
|
715
|
+
end
|
716
|
+
|
717
|
+
#=========================================================================
|
718
|
+
# 太陽視黄経の計算
|
719
|
+
#
|
720
|
+
# @param: jd (ユリウス日(JST))
|
721
|
+
# @return: lambda
|
722
|
+
#=========================================================================
|
723
|
+
def compute_lambda(jd)
|
724
|
+
year, month, day, hour, min, sec = jd2ymd(jd - Const::JST_D - 0.5)
|
725
|
+
ymd = sprintf("%04d%02d%02d%02d%02d%08d", year, month, day, hour, min, sec * 10 ** 6)
|
726
|
+
a = MkApos.new(@bin_path, ymd)
|
727
|
+
lmd = a.sun[1][0] * 180.0 / Math::PI
|
728
|
+
return lmd
|
729
|
+
end
|
730
|
+
|
731
|
+
#=========================================================================
|
732
|
+
# 月視黄経の計算
|
733
|
+
#
|
734
|
+
# @param: jd (ユリウス日(JST))
|
735
|
+
# @return: lambda
|
736
|
+
#=========================================================================
|
737
|
+
def compute_alpha(jd)
|
738
|
+
year, month, day, hour, min, sec = jd2ymd(jd - Const::JST_D - 0.5)
|
739
|
+
ymd = sprintf("%04d%02d%02d%02d%02d%08d", year, month, day, hour, min, sec * 10 ** 6)
|
740
|
+
a = MkApos.new(@bin_path, ymd)
|
741
|
+
lmd = a.moon[1][0] * 180.0 / Math::PI
|
742
|
+
return lmd
|
743
|
+
end
|
744
|
+
end
|
745
|
+
end
|
746
|
+
|