sekki24 1.0.0
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 +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +190 -0
- data/Rakefile +8 -0
- data/exe/sekki24 +104 -0
- data/lib/sekki24/delta_t.rb +67 -0
- data/lib/sekki24/finder.rb +112 -0
- data/lib/sekki24/kou.rb +49 -0
- data/lib/sekki24/kou_names.rb +60 -0
- data/lib/sekki24/lunar/moon.rb +66 -0
- data/lib/sekki24/lunar/periodic_terms.rb +31 -0
- data/lib/sekki24/lunar/phase_finder.rb +157 -0
- data/lib/sekki24/lunisolar/calendar.rb +129 -0
- data/lib/sekki24/lunisolar/date.rb +58 -0
- data/lib/sekki24/lunisolar/month.rb +67 -0
- data/lib/sekki24/lunisolar/month_builder.rb +143 -0
- data/lib/sekki24/names.rb +63 -0
- data/lib/sekki24/nutation.rb +31 -0
- data/lib/sekki24/seventy_two_kou.rb +129 -0
- data/lib/sekki24/solar/fast.rb +41 -0
- data/lib/sekki24/solar/precise.rb +45 -0
- data/lib/sekki24/solar/vsop87_earth.rb +227 -0
- data/lib/sekki24/solar.rb +21 -0
- data/lib/sekki24/term.rb +52 -0
- data/lib/sekki24/time_scale.rb +94 -0
- data/lib/sekki24/version.rb +5 -0
- data/lib/sekki24/zassetsu.rb +50 -0
- data/lib/sekki24/zassetsu_calendar.rb +176 -0
- data/lib/sekki24.rb +146 -0
- data/sekki24.gemspec +31 -0
- metadata +75 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Sekki24
|
|
4
|
+
module Names
|
|
5
|
+
Definition = Struct.new(
|
|
6
|
+
:key,
|
|
7
|
+
:name_ja,
|
|
8
|
+
:reading,
|
|
9
|
+
:name_en,
|
|
10
|
+
:name_zh,
|
|
11
|
+
:longitude,
|
|
12
|
+
keyword_init: true
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
TERMS = [
|
|
16
|
+
[:risshun, "立春", "りっしゅん", "Start of spring", "立春", 315],
|
|
17
|
+
[:usui, "雨水", "うすい", "Rain water", "雨水", 330],
|
|
18
|
+
[:keichitsu, "啓蟄", "けいちつ", "Awakening of insects", "惊蛰", 345],
|
|
19
|
+
[:shunbun, "春分", "しゅんぶん", "Spring equinox", "春分", 0],
|
|
20
|
+
[:seimei, "清明", "せいめい", "Pure brightness", "清明", 15],
|
|
21
|
+
[:kokuu, "穀雨", "こくう", "Grain rain", "谷雨", 30],
|
|
22
|
+
[:rikka, "立夏", "りっか", "Start of summer", "立夏", 45],
|
|
23
|
+
[:shoman, "小満", "しょうまん", "Grain buds", "小满", 60],
|
|
24
|
+
[:boshu, "芒種", "ぼうしゅ", "Grain in ear", "芒种", 75],
|
|
25
|
+
[:geshi, "夏至", "げし", "Summer solstice", "夏至", 90],
|
|
26
|
+
[:shosho, "小暑", "しょうしょ", "Minor heat", "小暑", 105],
|
|
27
|
+
[:taisho, "大暑", "たいしょ", "Major heat", "大暑", 120],
|
|
28
|
+
[:risshu, "立秋", "りっしゅう", "Start of autumn", "立秋", 135],
|
|
29
|
+
[:shoshu, "処暑", "しょしょ", "End of heat", "处暑", 150],
|
|
30
|
+
[:hakuro, "白露", "はくろ", "White dew", "白露", 165],
|
|
31
|
+
[:shubun, "秋分", "しゅうぶん", "Autumn equinox", "秋分", 180],
|
|
32
|
+
[:kanro, "寒露", "かんろ", "Cold dew", "寒露", 195],
|
|
33
|
+
[:soko, "霜降", "そうこう", "Frost descent", "霜降", 210],
|
|
34
|
+
[:ritto, "立冬", "りっとう", "Start of winter", "立冬", 225],
|
|
35
|
+
[:shosetsu, "小雪", "しょうせつ", "Minor snow", "小雪", 240],
|
|
36
|
+
[:taisetsu, "大雪", "たいせつ", "Major snow", "大雪", 255],
|
|
37
|
+
[:toji, "冬至", "とうじ", "Winter solstice", "冬至", 270],
|
|
38
|
+
[:shokan, "小寒", "しょうかん", "Minor cold", "小寒", 285],
|
|
39
|
+
[:daikan, "大寒", "だいかん", "Major cold", "大寒", 300]
|
|
40
|
+
].map do |key, name_ja, reading, name_en, name_zh, longitude|
|
|
41
|
+
Definition.new(
|
|
42
|
+
key: key,
|
|
43
|
+
name_ja: name_ja,
|
|
44
|
+
reading: reading,
|
|
45
|
+
name_en: name_en,
|
|
46
|
+
name_zh: name_zh,
|
|
47
|
+
longitude: longitude
|
|
48
|
+
).freeze
|
|
49
|
+
end.freeze
|
|
50
|
+
|
|
51
|
+
BY_KEY = TERMS.to_h { |term| [term.key, term] }.freeze
|
|
52
|
+
BY_LONGITUDE = TERMS.to_h { |term| [term.longitude, term] }.freeze
|
|
53
|
+
CALENDAR_ORDER = (TERMS.drop(22) + TERMS.take(22)).freeze
|
|
54
|
+
|
|
55
|
+
module_function
|
|
56
|
+
|
|
57
|
+
def fetch(key)
|
|
58
|
+
BY_KEY.fetch(key.to_sym)
|
|
59
|
+
rescue NoMethodError, KeyError
|
|
60
|
+
raise ArgumentError, "unknown solar term: #{key.inspect}"
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Sekki24
|
|
4
|
+
module Nutation
|
|
5
|
+
J2000 = 2_451_545.0
|
|
6
|
+
JULIAN_CENTURY = 36_525.0
|
|
7
|
+
DEGREES_TO_RADIANS = Math::PI / 180.0
|
|
8
|
+
|
|
9
|
+
module_function
|
|
10
|
+
|
|
11
|
+
# Four dominant IAU 1980 terms, returned in degrees.
|
|
12
|
+
def longitude(jde)
|
|
13
|
+
centuries = (Float(jde) - J2000) / JULIAN_CENTURY
|
|
14
|
+
sun_mean_longitude = 280.4665 + (36_000.7698 * centuries)
|
|
15
|
+
moon_mean_longitude = 218.3165 + (481_267.8813 * centuries)
|
|
16
|
+
ascending_node = 125.04452 - (1934.136261 * centuries) +
|
|
17
|
+
(0.0020708 * centuries**2) + (centuries**3 / 450_000.0)
|
|
18
|
+
|
|
19
|
+
arcseconds = (-17.20 * sin_degrees(ascending_node)) -
|
|
20
|
+
(1.32 * sin_degrees(2.0 * sun_mean_longitude)) -
|
|
21
|
+
(0.23 * sin_degrees(2.0 * moon_mean_longitude)) +
|
|
22
|
+
(0.21 * sin_degrees(2.0 * ascending_node))
|
|
23
|
+
arcseconds / 3600.0
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def sin_degrees(angle)
|
|
27
|
+
Math.sin(angle * DEGREES_TO_RADIANS)
|
|
28
|
+
end
|
|
29
|
+
private_class_method :sin_degrees
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "kou_names"
|
|
4
|
+
require_relative "kou"
|
|
5
|
+
|
|
6
|
+
module Sekki24
|
|
7
|
+
module SeventyTwoKou
|
|
8
|
+
@cache_mutex = Mutex.new
|
|
9
|
+
@year_cache = {}
|
|
10
|
+
@candidate_cache = {}
|
|
11
|
+
|
|
12
|
+
class << self
|
|
13
|
+
def year(year, tz:, precision:)
|
|
14
|
+
calendar_year = validate_year(year)
|
|
15
|
+
mode = normalize_precision(precision)
|
|
16
|
+
solar = Solar.model(mode)
|
|
17
|
+
cache_key = [calendar_year, TimeScale.timezone_key(tz), mode].freeze
|
|
18
|
+
cached = @cache_mutex.synchronize { @year_cache[cache_key] }
|
|
19
|
+
return cached if cached
|
|
20
|
+
|
|
21
|
+
calculated = calculate_year(calendar_year, tz, mode, solar)
|
|
22
|
+
@cache_mutex.synchronize { @year_cache[cache_key] ||= calculated }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def fetch(year, ordinal, tz:, precision:)
|
|
26
|
+
definition = KouNames.fetch(ordinal)
|
|
27
|
+
self.year(year, tz: tz, precision: precision).find { |entry| entry.ordinal == definition.ordinal }
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def current(time, tz:, precision:)
|
|
31
|
+
navigation_terms(time, tz, precision).select { |entry| entry.time <= time }.max ||
|
|
32
|
+
raise(RangeError, "no current kou in the supported range")
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def next_kou(time, tz:, precision:)
|
|
36
|
+
navigation_terms(time, tz, precision).select { |entry| entry.time > time }.min ||
|
|
37
|
+
raise(RangeError, "no next kou in the supported range")
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def previous(time, tz:, precision:)
|
|
41
|
+
navigation_terms(time, tz, precision).select { |entry| entry.time < time }.max ||
|
|
42
|
+
raise(RangeError, "no previous kou in the supported range")
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def clear_cache!
|
|
46
|
+
@cache_mutex.synchronize do
|
|
47
|
+
@year_cache.clear
|
|
48
|
+
@candidate_cache.clear
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
private
|
|
53
|
+
|
|
54
|
+
def calculate_year(calendar_year, timezone, mode, solar)
|
|
55
|
+
entries = candidate_times(calendar_year, mode, solar).map do |definition, utc_time|
|
|
56
|
+
local_time = TimeScale.localize(utc_time, timezone)
|
|
57
|
+
Kou.new(definition: definition, time: local_time)
|
|
58
|
+
end.sort.freeze
|
|
59
|
+
return entries if entries.length == 72
|
|
60
|
+
|
|
61
|
+
raise Error, "expected 72 kou for #{calendar_year}, got #{entries.length}"
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def candidate_times(year, mode, solar)
|
|
65
|
+
cache_key = [year, mode].freeze
|
|
66
|
+
cached = @cache_mutex.synchronize { @candidate_cache[cache_key] }
|
|
67
|
+
return cached if cached
|
|
68
|
+
|
|
69
|
+
calculated = Names::CALENDAR_ORDER.flat_map do |term_definition|
|
|
70
|
+
term_time = Finder.find(year: year, longitude: term_definition.longitude, solar: solar).freeze
|
|
71
|
+
KouNames::TERMS.select { |definition| definition.term_key == term_definition.key }.map do |definition|
|
|
72
|
+
time = if definition.position == :initial
|
|
73
|
+
term_time
|
|
74
|
+
else
|
|
75
|
+
Finder.find_after(time: term_time, longitude: definition.longitude, solar: solar).freeze
|
|
76
|
+
end
|
|
77
|
+
[definition, time].freeze
|
|
78
|
+
end
|
|
79
|
+
end.freeze
|
|
80
|
+
@cache_mutex.synchronize { @candidate_cache[cache_key] ||= calculated }
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def navigation_terms(time, timezone, precision)
|
|
84
|
+
raise TypeError, "expected Time, got #{time.class}" unless time.is_a?(Time)
|
|
85
|
+
|
|
86
|
+
local_year = TimeScale.localize(time, timezone).year
|
|
87
|
+
years = ((local_year - 1)..(local_year + 1)).select { |value| (MIN_YEAR..MAX_YEAR).cover?(value) }
|
|
88
|
+
years.flat_map { |value| year(value, tz: timezone, precision: precision) }
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def validate_year(year)
|
|
92
|
+
value = Integer(year)
|
|
93
|
+
return value if (MIN_YEAR..MAX_YEAR).cover?(value)
|
|
94
|
+
|
|
95
|
+
raise RangeError, "year must be between #{MIN_YEAR} and #{MAX_YEAR}"
|
|
96
|
+
rescue ArgumentError, TypeError
|
|
97
|
+
raise ArgumentError, "year must be an Integer between #{MIN_YEAR} and #{MAX_YEAR}"
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def normalize_precision(precision)
|
|
101
|
+
precision.to_sym
|
|
102
|
+
rescue NoMethodError
|
|
103
|
+
raise ArgumentError, "precision must be :fast or :precise"
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
class << self
|
|
109
|
+
def kou_year(year, tz: DEFAULT_TIMEZONE, precision: DEFAULT_PRECISION)
|
|
110
|
+
SeventyTwoKou.year(year, tz: tz, precision: precision)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def kou(year, ordinal, tz: DEFAULT_TIMEZONE, precision: DEFAULT_PRECISION)
|
|
114
|
+
SeventyTwoKou.fetch(year, ordinal, tz: tz, precision: precision)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def current_kou(time = Time.now, tz: DEFAULT_TIMEZONE, precision: DEFAULT_PRECISION)
|
|
118
|
+
SeventyTwoKou.current(time, tz: tz, precision: precision)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def next_kou(time = Time.now, tz: DEFAULT_TIMEZONE, precision: DEFAULT_PRECISION)
|
|
122
|
+
SeventyTwoKou.next_kou(time, tz: tz, precision: precision)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def prev_kou(time = Time.now, tz: DEFAULT_TIMEZONE, precision: DEFAULT_PRECISION)
|
|
126
|
+
SeventyTwoKou.previous(time, tz: tz, precision: precision)
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Sekki24
|
|
4
|
+
module Solar
|
|
5
|
+
module Fast
|
|
6
|
+
J2000 = 2_451_545.0
|
|
7
|
+
JULIAN_CENTURY = 36_525.0
|
|
8
|
+
DEGREES_TO_RADIANS = Math::PI / 180.0
|
|
9
|
+
|
|
10
|
+
module_function
|
|
11
|
+
|
|
12
|
+
def longitude(jde)
|
|
13
|
+
centuries = (Float(jde) - J2000) / JULIAN_CENTURY
|
|
14
|
+
mean_longitude = 280.46646 + (36_000.76983 * centuries) + (0.0003032 * centuries**2)
|
|
15
|
+
mean_anomaly = 357.52911 + (35_999.05029 * centuries) - (0.0001537 * centuries**2) +
|
|
16
|
+
(centuries**3 / 24_490_000.0)
|
|
17
|
+
center = equation_of_center(mean_anomaly, centuries)
|
|
18
|
+
omega = 125.04 - (1934.136 * centuries)
|
|
19
|
+
|
|
20
|
+
normalize(mean_longitude + center - 0.00569 - (0.00478 * sin_degrees(omega)))
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def equation_of_center(mean_anomaly, centuries)
|
|
24
|
+
((1.914602 - (0.004817 * centuries) - (0.000014 * centuries**2)) * sin_degrees(mean_anomaly)) +
|
|
25
|
+
((0.019993 - (0.000101 * centuries)) * sin_degrees(2.0 * mean_anomaly)) +
|
|
26
|
+
(0.000289 * sin_degrees(3.0 * mean_anomaly))
|
|
27
|
+
end
|
|
28
|
+
private_class_method :equation_of_center
|
|
29
|
+
|
|
30
|
+
def sin_degrees(angle)
|
|
31
|
+
Math.sin(angle * DEGREES_TO_RADIANS)
|
|
32
|
+
end
|
|
33
|
+
private_class_method :sin_degrees
|
|
34
|
+
|
|
35
|
+
def normalize(angle)
|
|
36
|
+
angle % 360.0
|
|
37
|
+
end
|
|
38
|
+
private_class_method :normalize
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "vsop87_earth"
|
|
4
|
+
require_relative "../nutation"
|
|
5
|
+
|
|
6
|
+
module Sekki24
|
|
7
|
+
module Solar
|
|
8
|
+
module Precise
|
|
9
|
+
J2000 = 2_451_545.0
|
|
10
|
+
JULIAN_MILLENNIUM = 365_250.0
|
|
11
|
+
JULIAN_CENTURY = 36_525.0
|
|
12
|
+
RADIANS_TO_DEGREES = 180.0 / Math::PI
|
|
13
|
+
ABERRATION_ARCSECONDS = 20.4898
|
|
14
|
+
FK5_LONGITUDE_CORRECTION = -0.09033 / 3600.0
|
|
15
|
+
|
|
16
|
+
module_function
|
|
17
|
+
|
|
18
|
+
def longitude(jde)
|
|
19
|
+
jde = Float(jde)
|
|
20
|
+
millennia = (jde - J2000) / JULIAN_MILLENNIUM
|
|
21
|
+
earth_longitude = evaluate(VSOP87Earth::LONGITUDE, millennia) * RADIANS_TO_DEGREES
|
|
22
|
+
radius = evaluate(VSOP87Earth::RADIUS, millennia)
|
|
23
|
+
geometric_longitude = earth_longitude + 180.0 + FK5_LONGITUDE_CORRECTION
|
|
24
|
+
apparent_longitude = geometric_longitude + Nutation.longitude(jde) -
|
|
25
|
+
(ABERRATION_ARCSECONDS / (3600.0 * radius))
|
|
26
|
+
|
|
27
|
+
apparent_longitude % 360.0
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def evaluate(series, time)
|
|
31
|
+
power = 1.0
|
|
32
|
+
series.sum do |terms|
|
|
33
|
+
value = terms.sum do |amplitude, phase, frequency|
|
|
34
|
+
amplitude * Math.cos(phase + (frequency * time))
|
|
35
|
+
end
|
|
36
|
+
result = value * power
|
|
37
|
+
power *= time
|
|
38
|
+
result
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
private_class_method :evaluate
|
|
42
|
+
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Sekki24
|
|
4
|
+
module Solar
|
|
5
|
+
# Truncated VSOP87D Earth series (Bretagnon & Francou, 1988).
|
|
6
|
+
# Coefficients are from the official IMCCE VSOP87D.ear distribution.
|
|
7
|
+
module VSOP87Earth
|
|
8
|
+
LONGITUDE = [
|
|
9
|
+
[
|
|
10
|
+
[1.75347045673, 0.00000000000, 0.00000000000].freeze,
|
|
11
|
+
[0.03341656456, 4.66925680417, 6283.07584999140].freeze,
|
|
12
|
+
[0.00034894275, 4.62610241759, 12566.15169998280].freeze,
|
|
13
|
+
[0.00003417571, 2.82886579606, 3.52311834900].freeze,
|
|
14
|
+
[0.00003497056, 2.74411800971, 5753.38488489680].freeze,
|
|
15
|
+
[0.00003135896, 3.62767041758, 77713.77146812050].freeze,
|
|
16
|
+
[0.00002676218, 4.41808351397, 7860.41939243920].freeze,
|
|
17
|
+
[0.00002342687, 6.13516237631, 3930.20969621960].freeze,
|
|
18
|
+
[0.00001273166, 2.03709655772, 529.69096509460].freeze,
|
|
19
|
+
[0.00001324292, 0.74246356352, 11506.76976979360].freeze,
|
|
20
|
+
[0.00000901855, 2.04505443513, 26.29831979980].freeze,
|
|
21
|
+
[0.00001199167, 1.10962944315, 1577.34354244780].freeze,
|
|
22
|
+
[0.00000857223, 3.50849156957, 398.14900340820].freeze,
|
|
23
|
+
[0.00000779786, 1.17882652114, 5223.69391980220].freeze,
|
|
24
|
+
[0.00000990250, 5.23268129594, 5884.92684658320].freeze,
|
|
25
|
+
[0.00000753141, 2.53339053818, 5507.55323866740].freeze,
|
|
26
|
+
[0.00000505264, 4.58292563052, 18849.22754997420].freeze,
|
|
27
|
+
[0.00000492379, 4.20506639861, 775.52261132400].freeze,
|
|
28
|
+
[0.00000356655, 2.91954116867, 0.06731030280].freeze,
|
|
29
|
+
[0.00000284125, 1.89869034186, 796.29800681640].freeze,
|
|
30
|
+
[0.00000242810, 0.34481140906, 5486.77784317500].freeze,
|
|
31
|
+
[0.00000317087, 5.84901952218, 11790.62908865880].freeze,
|
|
32
|
+
[0.00000271039, 0.31488607649, 10977.07880469900].freeze,
|
|
33
|
+
[0.00000206160, 4.80646606059, 2544.31441988340].freeze,
|
|
34
|
+
[0.00000205385, 1.86947813692, 5573.14280143310].freeze,
|
|
35
|
+
[0.00000202261, 2.45767795458, 6069.77675455340].freeze,
|
|
36
|
+
[0.00000126184, 1.08302630210, 20.77539549240].freeze,
|
|
37
|
+
[0.00000155516, 0.83306073807, 213.29909543800].freeze,
|
|
38
|
+
[0.00000115132, 0.64544911683, 0.98032106820].freeze,
|
|
39
|
+
[0.00000102851, 0.63599846727, 4694.00295470760].freeze,
|
|
40
|
+
[0.00000101724, 4.26679821365, 7.11354700080].freeze,
|
|
41
|
+
[0.00000099206, 6.20992940258, 2146.16541647520].freeze,
|
|
42
|
+
[0.00000132212, 3.41118275555, 2942.46342329160].freeze,
|
|
43
|
+
[0.00000097607, 0.68101272270, 155.42039943420].freeze,
|
|
44
|
+
[0.00000085128, 1.29870743025, 6275.96230299060].freeze,
|
|
45
|
+
[0.00000074651, 1.75508916159, 5088.62883976680].freeze,
|
|
46
|
+
[0.00000101895, 0.97569221824, 15720.83878487840].freeze,
|
|
47
|
+
[0.00000084711, 3.67080093025, 71430.69561812909].freeze,
|
|
48
|
+
[0.00000073547, 4.67926565481, 801.82093112380].freeze,
|
|
49
|
+
[0.00000073874, 3.50319443167, 3154.68708489560].freeze,
|
|
50
|
+
[0.00000078756, 3.03698313141, 12036.46073488820].freeze,
|
|
51
|
+
[0.00000079637, 1.80791330700, 17260.15465469040].freeze,
|
|
52
|
+
[0.00000085803, 5.98322631256, 161000.68573767410].freeze,
|
|
53
|
+
[0.00000056963, 2.78430398043, 6286.59896834040].freeze,
|
|
54
|
+
[0.00000061148, 1.81839811024, 7084.89678111520].freeze,
|
|
55
|
+
[0.00000069627, 0.83297596966, 9437.76293488700].freeze,
|
|
56
|
+
[0.00000056116, 4.38694880779, 14143.49524243060].freeze,
|
|
57
|
+
[0.00000062449, 3.97763880587, 8827.39026987480].freeze,
|
|
58
|
+
[0.00000051145, 0.28306864501, 5856.47765911540].freeze,
|
|
59
|
+
[0.00000055577, 3.47006009062, 6279.55273164240].freeze,
|
|
60
|
+
[0.00000041036, 5.36817351402, 8429.24126646660].freeze,
|
|
61
|
+
[0.00000051605, 1.33282746983, 1748.01641306700].freeze,
|
|
62
|
+
[0.00000051992, 0.18914945834, 12139.55350910680].freeze,
|
|
63
|
+
[0.00000049000, 0.48735065033, 1194.44701022460].freeze,
|
|
64
|
+
[0.00000039200, 6.16832995016, 10447.38783960440].freeze,
|
|
65
|
+
[0.00000035566, 1.77597314691, 6812.76681508600].freeze,
|
|
66
|
+
[0.00000036770, 6.04133859347, 10213.28554621100].freeze,
|
|
67
|
+
[0.00000036596, 2.56955238628, 1059.38193018920].freeze,
|
|
68
|
+
[0.00000033291, 0.59309499459, 17789.84561978500].freeze,
|
|
69
|
+
[0.00000035954, 1.70876111898, 2352.86615377180].freeze,
|
|
70
|
+
[0.00000040938, 2.39850881707, 19651.04848109800].freeze,
|
|
71
|
+
[0.00000030047, 2.73975123935, 1349.86740965880].freeze,
|
|
72
|
+
[0.00000030412, 0.44294464135, 83996.84731811189].freeze,
|
|
73
|
+
[0.00000023663, 0.48473567763, 8031.09226305840].freeze,
|
|
74
|
+
].freeze,
|
|
75
|
+
[
|
|
76
|
+
[6283.31966747491, 0.00000000000, 0.00000000000].freeze,
|
|
77
|
+
[0.00206058863, 2.67823455584, 6283.07584999140].freeze,
|
|
78
|
+
[0.00004303430, 2.63512650414, 12566.15169998280].freeze,
|
|
79
|
+
[0.00000425264, 1.59046980729, 3.52311834900].freeze,
|
|
80
|
+
[0.00000108977, 2.96618001993, 1577.34354244780].freeze,
|
|
81
|
+
[0.00000093478, 2.59212835365, 18849.22754997420].freeze,
|
|
82
|
+
[0.00000119261, 5.79557487799, 26.29831979980].freeze,
|
|
83
|
+
[0.00000072122, 1.13846158196, 529.69096509460].freeze,
|
|
84
|
+
[0.00000067768, 1.87472304791, 398.14900340820].freeze,
|
|
85
|
+
[0.00000067327, 4.40918235168, 5507.55323866740].freeze,
|
|
86
|
+
[0.00000059027, 2.88797038460, 5223.69391980220].freeze,
|
|
87
|
+
[0.00000055976, 2.17471680261, 155.42039943420].freeze,
|
|
88
|
+
[0.00000045407, 0.39803079805, 796.29800681640].freeze,
|
|
89
|
+
[0.00000036369, 0.46624739835, 775.52261132400].freeze,
|
|
90
|
+
[0.00000028958, 2.64707383882, 7.11354700080].freeze,
|
|
91
|
+
[0.00000019097, 1.84628332577, 5486.77784317500].freeze,
|
|
92
|
+
[0.00000020844, 5.34138275149, 0.98032106820].freeze,
|
|
93
|
+
[0.00000018508, 4.96855124577, 213.29909543800].freeze,
|
|
94
|
+
[0.00000016233, 0.03216483047, 2544.31441988340].freeze,
|
|
95
|
+
[0.00000017293, 2.99116864949, 6275.96230299060].freeze,
|
|
96
|
+
[0.00000015832, 1.43049285325, 2146.16541647520].freeze,
|
|
97
|
+
[0.00000014615, 1.20532366323, 10977.07880469900].freeze,
|
|
98
|
+
[0.00000011877, 3.25804815607, 5088.62883976680].freeze,
|
|
99
|
+
[0.00000011514, 2.07502418155, 4694.00295470760].freeze,
|
|
100
|
+
[0.00000009721, 4.23925472239, 1349.86740965880].freeze,
|
|
101
|
+
[0.00000009969, 1.30262991097, 6286.59896834040].freeze,
|
|
102
|
+
[0.00000009452, 2.69957062864, 242.72860397400].freeze,
|
|
103
|
+
[0.00000012461, 2.83432285512, 1748.01641306700].freeze,
|
|
104
|
+
[0.00000011808, 5.27379790480, 1194.44701022460].freeze,
|
|
105
|
+
[0.00000008577, 5.64475868067, 951.71840625060].freeze,
|
|
106
|
+
[0.00000010641, 0.76614199202, 553.56940284240].freeze,
|
|
107
|
+
[0.00000007576, 5.30062664886, 2352.86615377180].freeze,
|
|
108
|
+
[0.00000005834, 1.76649917904, 1059.38193018920].freeze,
|
|
109
|
+
[0.00000006385, 2.65033984967, 9437.76293488700].freeze,
|
|
110
|
+
].freeze,
|
|
111
|
+
[
|
|
112
|
+
[0.00052918870, 0.00000000000, 0.00000000000].freeze,
|
|
113
|
+
[0.00008719837, 1.07209665242, 6283.07584999140].freeze,
|
|
114
|
+
[0.00000309125, 0.86728818832, 12566.15169998280].freeze,
|
|
115
|
+
[0.00000027339, 0.05297871691, 3.52311834900].freeze,
|
|
116
|
+
[0.00000016334, 5.18826691036, 26.29831979980].freeze,
|
|
117
|
+
[0.00000015752, 3.68457889430, 155.42039943420].freeze,
|
|
118
|
+
[0.00000009541, 0.75742297675, 18849.22754997420].freeze,
|
|
119
|
+
[0.00000008937, 2.05705419118, 77713.77146812050].freeze,
|
|
120
|
+
[0.00000006952, 0.82673305410, 775.52261132400].freeze,
|
|
121
|
+
[0.00000005064, 4.66284525271, 1577.34354244780].freeze,
|
|
122
|
+
[0.00000004061, 1.03057162962, 7.11354700080].freeze,
|
|
123
|
+
[0.00000003463, 5.14074632811, 796.29800681640].freeze,
|
|
124
|
+
[0.00000003169, 6.05291851171, 5507.55323866740].freeze,
|
|
125
|
+
[0.00000003020, 1.19246506441, 242.72860397400].freeze,
|
|
126
|
+
[0.00000002886, 6.11652627155, 529.69096509460].freeze,
|
|
127
|
+
[0.00000003810, 3.44050803490, 5573.14280143310].freeze,
|
|
128
|
+
[0.00000002714, 0.30637881025, 398.14900340820].freeze,
|
|
129
|
+
[0.00000002371, 4.38118838167, 5223.69391980220].freeze,
|
|
130
|
+
[0.00000002538, 2.27992810679, 553.56940284240].freeze,
|
|
131
|
+
[0.00000002079, 3.75435330484, 0.98032106820].freeze,
|
|
132
|
+
].freeze,
|
|
133
|
+
[
|
|
134
|
+
[0.00000289226, 5.84384198723, 6283.07584999140].freeze,
|
|
135
|
+
[0.00000034955, 0.00000000000, 0.00000000000].freeze,
|
|
136
|
+
[0.00000016819, 5.48766912348, 12566.15169998280].freeze,
|
|
137
|
+
[0.00000002962, 5.19577265202, 155.42039943420].freeze,
|
|
138
|
+
[0.00000001288, 4.72200252235, 3.52311834900].freeze,
|
|
139
|
+
[0.00000000635, 5.96925937141, 242.72860397400].freeze,
|
|
140
|
+
[0.00000000714, 5.30045809128, 18849.22754997420].freeze,
|
|
141
|
+
].freeze,
|
|
142
|
+
[
|
|
143
|
+
[0.00000114084, 3.14159265359, 0.00000000000].freeze,
|
|
144
|
+
[0.00000007717, 4.13446589358, 6283.07584999140].freeze,
|
|
145
|
+
[0.00000000765, 3.83803776214, 12566.15169998280].freeze,
|
|
146
|
+
].freeze,
|
|
147
|
+
[
|
|
148
|
+
[0.00000000878, 3.14159265359, 0.00000000000].freeze,
|
|
149
|
+
].freeze,
|
|
150
|
+
].freeze
|
|
151
|
+
RADIUS = [
|
|
152
|
+
[
|
|
153
|
+
[1.00013988799, 0.00000000000, 0.00000000000].freeze,
|
|
154
|
+
[0.01670699626, 3.09846350771, 6283.07584999140].freeze,
|
|
155
|
+
[0.00013956023, 3.05524609620, 12566.15169998280].freeze,
|
|
156
|
+
[0.00003083720, 5.19846674381, 77713.77146812050].freeze,
|
|
157
|
+
[0.00001628461, 1.17387749012, 5753.38488489680].freeze,
|
|
158
|
+
[0.00001575568, 2.84685245825, 7860.41939243920].freeze,
|
|
159
|
+
[0.00000924799, 5.45292234084, 11506.76976979360].freeze,
|
|
160
|
+
[0.00000542444, 4.56409149777, 3930.20969621960].freeze,
|
|
161
|
+
[0.00000472110, 3.66100022149, 5884.92684658320].freeze,
|
|
162
|
+
[0.00000328780, 5.89983646482, 5223.69391980220].freeze,
|
|
163
|
+
[0.00000345983, 0.96368617687, 5507.55323866740].freeze,
|
|
164
|
+
[0.00000306784, 0.29867139512, 5573.14280143310].freeze,
|
|
165
|
+
[0.00000174844, 3.01193636534, 18849.22754997420].freeze,
|
|
166
|
+
[0.00000243189, 4.27349536153, 11790.62908865880].freeze,
|
|
167
|
+
[0.00000211829, 5.84714540314, 1577.34354244780].freeze,
|
|
168
|
+
[0.00000185752, 5.02194447178, 10977.07880469900].freeze,
|
|
169
|
+
[0.00000109835, 5.05510636285, 5486.77784317500].freeze,
|
|
170
|
+
[0.00000098316, 0.88681311277, 6069.77675455340].freeze,
|
|
171
|
+
[0.00000086499, 5.68959778254, 15720.83878487840].freeze,
|
|
172
|
+
[0.00000085825, 1.27083733351, 161000.68573767410].freeze,
|
|
173
|
+
[0.00000062916, 0.92177108832, 529.69096509460].freeze,
|
|
174
|
+
[0.00000057056, 2.01374292014, 83996.84731811189].freeze,
|
|
175
|
+
[0.00000064903, 0.27250613787, 17260.15465469040].freeze,
|
|
176
|
+
[0.00000049384, 3.24501240359, 2544.31441988340].freeze,
|
|
177
|
+
[0.00000055736, 5.24159798933, 71430.69561812909].freeze,
|
|
178
|
+
[0.00000042515, 6.01110242003, 6275.96230299060].freeze,
|
|
179
|
+
[0.00000046963, 2.57805070386, 775.52261132400].freeze,
|
|
180
|
+
[0.00000038968, 5.36071738169, 4694.00295470760].freeze,
|
|
181
|
+
[0.00000044661, 5.53715807302, 9437.76293488700].freeze,
|
|
182
|
+
[0.00000035660, 1.67468058995, 12036.46073488820].freeze,
|
|
183
|
+
[0.00000031921, 0.18368229781, 5088.62883976680].freeze,
|
|
184
|
+
[0.00000031846, 1.77775642085, 398.14900340820].freeze,
|
|
185
|
+
[0.00000033193, 0.24370300098, 7084.89678111520].freeze,
|
|
186
|
+
[0.00000038245, 2.39255343974, 8827.39026987480].freeze,
|
|
187
|
+
[0.00000028464, 1.21344868176, 6286.59896834040].freeze,
|
|
188
|
+
[0.00000037490, 0.82952922332, 19651.04848109800].freeze,
|
|
189
|
+
[0.00000036957, 4.90107591914, 12139.55350910680].freeze,
|
|
190
|
+
[0.00000034537, 1.84270693282, 2942.46342329160].freeze,
|
|
191
|
+
[0.00000026275, 4.58896850401, 10447.38783960440].freeze,
|
|
192
|
+
[0.00000024596, 3.78660875483, 8429.24126646660].freeze,
|
|
193
|
+
].freeze,
|
|
194
|
+
[
|
|
195
|
+
[0.00103018608, 1.10748969588, 6283.07584999140].freeze,
|
|
196
|
+
[0.00001721238, 1.06442301418, 12566.15169998280].freeze,
|
|
197
|
+
[0.00000702215, 3.14159265359, 0.00000000000].freeze,
|
|
198
|
+
[0.00000032346, 1.02169059149, 18849.22754997420].freeze,
|
|
199
|
+
[0.00000030799, 2.84353804832, 5507.55323866740].freeze,
|
|
200
|
+
[0.00000024971, 1.31906709482, 5223.69391980220].freeze,
|
|
201
|
+
[0.00000018485, 1.42429748614, 1577.34354244780].freeze,
|
|
202
|
+
[0.00000010078, 5.91378194648, 10977.07880469900].freeze,
|
|
203
|
+
[0.00000008634, 0.27146150602, 5486.77784317500].freeze,
|
|
204
|
+
[0.00000008654, 1.42046854427, 6275.96230299060].freeze,
|
|
205
|
+
].freeze,
|
|
206
|
+
[
|
|
207
|
+
[0.00004359385, 5.78455133738, 6283.07584999140].freeze,
|
|
208
|
+
[0.00000123633, 5.57934722157, 12566.15169998280].freeze,
|
|
209
|
+
[0.00000012341, 3.14159265359, 0.00000000000].freeze,
|
|
210
|
+
[0.00000008792, 3.62777733395, 77713.77146812050].freeze,
|
|
211
|
+
[0.00000005689, 1.86958905084, 5573.14280143310].freeze,
|
|
212
|
+
[0.00000003301, 5.47027913302, 18849.22754997420].freeze,
|
|
213
|
+
].freeze,
|
|
214
|
+
[
|
|
215
|
+
[0.00000144595, 4.27319435148, 6283.07584999140].freeze,
|
|
216
|
+
[0.00000006729, 3.91697608662, 12566.15169998280].freeze,
|
|
217
|
+
].freeze,
|
|
218
|
+
[
|
|
219
|
+
[0.00000003858, 2.56384387339, 6283.07584999140].freeze,
|
|
220
|
+
].freeze,
|
|
221
|
+
[
|
|
222
|
+
].freeze,
|
|
223
|
+
].freeze
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
end
|
|
227
|
+
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "solar/fast"
|
|
4
|
+
require_relative "solar/precise"
|
|
5
|
+
|
|
6
|
+
module Sekki24
|
|
7
|
+
module Solar
|
|
8
|
+
MODELS = {
|
|
9
|
+
fast: Fast,
|
|
10
|
+
precise: Precise
|
|
11
|
+
}.freeze
|
|
12
|
+
|
|
13
|
+
module_function
|
|
14
|
+
|
|
15
|
+
def model(precision)
|
|
16
|
+
MODELS.fetch(precision.to_sym)
|
|
17
|
+
rescue NoMethodError, KeyError
|
|
18
|
+
raise ArgumentError, "precision must be :fast or :precise"
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
data/lib/sekki24/term.rb
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "date"
|
|
4
|
+
require "time"
|
|
5
|
+
|
|
6
|
+
module Sekki24
|
|
7
|
+
class Term
|
|
8
|
+
include Comparable
|
|
9
|
+
|
|
10
|
+
ATTRIBUTES = %i[key name_ja reading name_en name_zh longitude time].freeze
|
|
11
|
+
|
|
12
|
+
attr_reader(*ATTRIBUTES)
|
|
13
|
+
|
|
14
|
+
def initialize(definition:, time:)
|
|
15
|
+
@key = definition.key
|
|
16
|
+
@name_ja = definition.name_ja
|
|
17
|
+
@reading = definition.reading
|
|
18
|
+
@name_en = definition.name_en
|
|
19
|
+
@name_zh = definition.name_zh
|
|
20
|
+
@longitude = definition.longitude
|
|
21
|
+
@time = time.dup.freeze
|
|
22
|
+
freeze
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def <=>(other)
|
|
26
|
+
return unless other.respond_to?(:time)
|
|
27
|
+
|
|
28
|
+
time <=> other.time
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def ==(other)
|
|
32
|
+
other.is_a?(Term) && key == other.key && time == other.time
|
|
33
|
+
end
|
|
34
|
+
alias eql? ==
|
|
35
|
+
|
|
36
|
+
def hash
|
|
37
|
+
[self.class, key, time].hash
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def to_date
|
|
41
|
+
time.to_date
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def to_h
|
|
45
|
+
ATTRIBUTES.to_h { |attribute| [attribute, public_send(attribute)] }
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def inspect
|
|
49
|
+
"#<#{self.class} #{name_ja} (#{key}) #{time.iso8601} longitude=#{longitude}°>"
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|