日出日没計算、やってみようを、「日本の空港一覧」で、という実践。
凝ったことはなにもしておりませぬ(numpy なしの生まれたまま python には変更してあります):
1 #! /usr/bin/python2.7
2 # -*- coding: utf-8 -*-
3 # http://www.hoshi-lab.info/env/solar-j.html の javascript を移植して「空港での…」に
4 # 仕立て上げたもの、です。凝ったことは何もしてません。
5 #
6 import math
7
8 # sin function using degree
9 def _sind(d):
10 return math.sin(math.radians(d))
11
12 # cos function using degree
13 def _cosd(d):
14 return math.cos(math.radians(d))
15
16 # tan function using degree
17 def _tand(d):
18 return math.tan(math.radians(d))
19
20 # calculate Julius year (year from 2000/1/1, for variable "t")
21 def jy(yy, mm, dd, h, m, s, i): # yy/mm/dd h:m:s, i: time difference
22 yy -= 2000
23 if (mm <= 2):
24 mm += 12
25 yy -= 1
26
27 k = 365 * yy + 30 * mm + dd - 33.5 - i / 24.0 + math.floor(3 * (mm + 1) / 5.0) \
28 + math.floor(yy / 4.0) - math.floor(yy / 100.0) + math.floor(yy / 400.0)
29 k += ((s / 60.0 + m) / 60 + h) / 24.0 # plus time
30 k += (65 + yy) / 86400.0 # plus delta T
31 return k / 365.25
32
33 # solar position1 (celestial longitude, degree)
34 def spls(t): # t: Julius year
35 L = 280.4603 + 360.00769 * t \
36 + (1.9146 - 0.00005 * t) * _sind(357.538 + 359.991 * t) \
37 + 0.0200 * _sind(355.05 + 719.981 * t) \
38 + 0.0048 * _sind(234.95 + 19.341 * t) \
39 + 0.0020 * _sind(247.1 + 329.640 * t) \
40 + 0.0018 * _sind(297.8 + 4452.67 * t) \
41 + 0.0018 * _sind(251.3 + 0.20 * t) \
42 + 0.0015 * _sind(343.2 + 450.37 * t) \
43 + 0.0013 * _sind( 81.4 + 225.18 * t) \
44 + 0.0008 * _sind(132.5 + 659.29 * t) \
45 + 0.0007 * _sind(153.3 + 90.38 * t) \
46 + 0.0007 * _sind(206.8 + 30.35 * t) \
47 + 0.0006 * _sind( 29.8 + 337.18 * t) \
48 + 0.0005 * _sind(207.4 + 1.50 * t) \
49 + 0.0005 * _sind(291.2 + 22.81 * t) \
50 + 0.0004 * _sind(234.9 + 315.56 * t) \
51 + 0.0004 * _sind(157.3 + 299.30 * t) \
52 + 0.0004 * _sind( 21.1 + 720.02 * t) \
53 + 0.0003 * _sind(352.5 + 1079.97 * t) \
54 + 0.0003 * _sind(329.7 + 44.43 * t)
55 while (L >= 360):
56 L -= 360
57 while (L < 0):
58 L += 360
59 return L
60
61 # solar position2 (distance, AU)
62 def spds(t): # t: Julius year
63 r = (0.007256 - 0.0000002 * t) * _sind(267.54 + 359.991 * t) \
64 + 0.000091 * _sind(265.1 + 719.98 * t) \
65 + 0.000030 * _sind( 90.0) \
66 + 0.000013 * _sind( 27.8 + 4452.67 * t) \
67 + 0.000007 * _sind(254 + 450.4 * t) \
68 + 0.000007 * _sind(156 + 329.6 * t)
69 r = math.pow(10, r)
70 return r
71
72 # solar position3 (declination, degree)
73 def spal(t): # t: Julius year
74 ls = spls(t) ;
75 ep = 23.439291 - 0.000130042 * t
76 al = math.degrees(math.atan(_tand(ls) * _cosd(ep)))
77 if ((ls >= 0) and (ls < 180)):
78 while (al < 0):
79 al += 180
80 while (al >= 180):
81 al -= 180
82 else:
83 while (al < 180):
84 al += 180
85 while (al >= 360):
86 al -= 180
87 return al ;
88
89 # solar position4 (the right ascension, degree)
90 def spdl(t): # t: Julius year
91 ls = spls(t)
92 ep = 23.439291 - 0.000130042 * t
93 dl = math.degrees(math.asin(_sind(ls) * _sind(ep)))
94 return dl
95
96 # Calculate sidereal hour (degree)
97 def sh(t, h, m, s, l, i):
98 # t: julius year, h: hour, m: minute, s: second,
99 # l: longitude, i: time difference
100 d = ((s / 60.0 + m) / 60.0 + h) / 24.0 # elapsed hour (from 0:00 a.m.)
101 th = 100.4606 + 360.007700536 * t + 0.00000003879 * t * t - 15 * i
102 th += l + 360 * d
103 while (th >= 360):
104 th -= 360
105 while (th < 0):
106 th += 360
107 return th
108
109 # Calculating the seeming horizon altitude "sa"(degree)
110 def eandp(alt, ds): # subfunction for altitude and parallax
111 e = 0.035333333 * math.sqrt(alt)
112 p = 0.002442818 / ds
113 return p - e
114
115 def sa(alt, ds): # alt: altitude (m), ds: solar distance (AU)
116 s = 0.266994444 / ds
117 r = 0.585555555
118 k = eandp(alt,ds) - s - r
119 return k
120
121 # Calculating solar alititude (degree) {
122 def soal(la, th, al, dl):
123 # la: latitude, th: sidereal hour,
124 # al: solar declination, dl: right ascension
125 h = _sind(dl) * _sind(la) + _cosd(dl) * _cosd(la) * _cosd(th - al)
126 h = math.degrees(math.asin(h))
127 return h
128
129 # Calculating solar direction (degree) {
130 def sodr(la, th, al, dl):
131 # la: latitude, th: sidereal hour,
132 # al: solar declination, dl: right ascension
133 t = th - al
134 dc = -_cosd(dl) * _sind(t)
135 dm = _sind(dl) * _sind(la) - _cosd(dl) * _cosd(la) * _cosd(t)
136 dr = math.degrees(math.atan2(dc, dm))
137
138 if (dr < 0):
139 dr += 360
140 return dr
141
142 def calc(yy, mm, dd, i, lon, lat, alt=0, hh=-1, m=-1):
143 """
144 return list:
145 item 0: astronomical twilight start time
146 item 1: voyage twilight start time
147 item 2: citizen twilight start time
148 item 3: sun rise time, and solar direction (in degrees)
149 item 4: meridian time, and solar altitude (in degrees)
150 item 5: sun set time, and solar direction (in degrees)
151 item 6: citizen twilight end time
152 item 7: voyage twilight end time
153 item 8: astronomical twilight end time
154 """
155 result = []
156
157 t = jy(yy, mm, dd - 1, 23, 59, 0, i)
158 th = sh(t, 23, 59, 0, lon, i)
159 ds = spds(t)
160 ls = spls(t)
161 alp = spal(t)
162 dlt = spdl(t)
163 pht = soal(lat, th, alp, dlt)
164 pdr = sodr(lat, th, alp, dlt)
165
166 for hh in range(0, 24):
167 for m in range(0, 60):
168 t = jy(yy, mm, dd, hh, m, 0, i)
169 th = sh(t, hh, m, 0, lon, i)
170 ds = spds(t)
171 ls = spls(t)
172 alp = spal(t)
173 dlt = spdl(t)
174 ht = soal(lat, th, alp, dlt)
175 dr = sodr(lat, th, alp, dlt)
176 tt = eandp(alt, ds)
177 t1 = tt - 18
178 t2 = tt - 12
179 t3 = tt - 6
180 t4 = sa(alt, ds)
181
182 #key = "%d-%02d-%02d %02d:%02d:00+%02d" % (yy, mm, dd, hh, m, i)
183 key = "%02d:%02d+%02d" % (hh, m, i)
184
185 if ((pht < t1) and (ht > t1)):
186 result.append((key, ""))
187 if ((pht < t2) and (ht > t2)):
188 result.append((key, ""))
189 if ((pht < t3) and (ht > t3)):
190 result.append((key, ""))
191 if ((pht < t4) and (ht > t4)):
192 result.append((key, math.floor(dr)))
193 if ((pdr < 180) and (dr > 180)):
194 result.append((key, math.floor(ht)))
195 if ((pht > t4) and (ht < t4)):
196 result.append((key, math.floor(dr)))
197 if ((pht > t3) and (ht < t3)):
198 result.append((key, ""))
199 if ((pht > t2) and (ht < t2)):
200 result.append((key, ""))
201 if ((pht > t1) and (ht < t1)):
202 result.append((key, ""))
203 pht = ht
204 pdr = dr
205
206 #f.result.value = ans
207 return result
208
209
210 ALL_AIRPORTS = [
211 ('RJCW', {'City': 'Wakkanai', 'Name': 'Wakkanai', 'Altitude': 30, 'Longitude': 141.800833, 'Latitude': 45.404167, 'Timezone': 9.0}),
212 ('RJER', {'City': 'Rishiri Island', 'Name': 'Rishiri', 'Altitude': 112, 'Longitude': 141.186431, 'Latitude': 45.242006, 'Timezone': 9.0}),
213 ('RJEB', {'City': 'Monbetsu', 'Name': 'Monbetsu', 'Altitude': 80, 'Longitude': 143.404028, 'Latitude': 44.303914, 'Timezone': 9.0}),
214 ('RJCM', {'City': 'Memanbetsu', 'Name': 'Memanbetsu', 'Altitude': 135, 'Longitude': 144.164053, 'Latitude': 43.880606, 'Timezone': 9.0}),
215 ('RJEC', {'City': 'Asahikawa', 'Name': 'Asahikawa', 'Altitude': 721, 'Longitude': 142.4475, 'Latitude': 43.670833, 'Timezone': 9.0}),
216 ('RJCN', {'City': 'Nakashibetsu', 'Name': 'Nakashibetsu', 'Altitude': 234, 'Longitude': 144.96, 'Latitude': 43.5775, 'Timezone': 9.0}),
217 ('RJCO', {'City': 'Sapporo', 'Name': 'Okadama Airport', 'Altitude': 25, 'Longitude': 141.38, 'Latitude': 43.1161, 'Timezone': 9.0}),
218 ('RJCK', {'City': 'Kushiro', 'Name': 'Kushiro Airport', 'Altitude': 327, 'Longitude': 144.193, 'Latitude': 43.041, 'Timezone': 9.0}),
219 ('RJCT', {'City': 'Tokachi', 'Name': 'Tokachi', 'Altitude': 281, 'Longitude': 143.158475, 'Latitude': 42.890544, 'Timezone': 9.0}),
220 ('RJCJ', {'City': 'Chitose', 'Name': 'Chitose', 'Altitude': 87, 'Longitude': 141.666447, 'Latitude': 42.794475, 'Timezone': 9.0}),
221 ('RJCC', {'City': 'Sapporo', 'Name': 'New Chitose', 'Altitude': 82, 'Longitude': 141.692283, 'Latitude': 42.7752, 'Timezone': 9.0}),
222 ('RJCB', {'City': 'Obihiro', 'Name': 'Obihiro', 'Altitude': 505, 'Longitude': 143.217222, 'Latitude': 42.733333, 'Timezone': 9.0}),
223 ('RJEO', {'City': 'Okushiri', 'Name': 'Okushiri', 'Altitude': 161, 'Longitude': 139.432911, 'Latitude': 42.071667, 'Timezone': 9.0}),
224 ('RJCH', {'City': 'Hakodate', 'Name': 'Hakodate', 'Altitude': 151, 'Longitude': 140.821944, 'Latitude': 41.77, 'Timezone': 9.0}),
225 ('RJSA', {'City': 'Aomori', 'Name': 'Aomori', 'Altitude': 664, 'Longitude': 140.690833, 'Latitude': 40.734722, 'Timezone': 9.0}),
226 ('RJSM', {'City': 'Misawa', 'Name': 'Misawa Ab', 'Altitude': 119, 'Longitude': 141.368364, 'Latitude': 40.703222, 'Timezone': 9.0}),
227 ('RJSH', {'City': 'Hachinoe', 'Name': 'Hachinohe', 'Altitude': 152, 'Longitude': 141.466325, 'Latitude': 40.556447, 'Timezone': 9.0}),
228 ('RJSR', {'City': 'Odate Noshiro', 'Name': 'Odate Noshiro Airport', 'Altitude': 292, 'Longitude': 140.371, 'Latitude': 40.1919, 'Timezone': 9.0}),
229 ('RJSK', {'City': 'Akita', 'Name': 'Akita', 'Altitude': 313, 'Longitude': 140.218611, 'Latitude': 39.615556, 'Timezone': 9.0}),
230 ('RJSI', {'City': 'Hanamaki', 'Name': 'Hanamaki', 'Altitude': 297, 'Longitude': 141.135278, 'Latitude': 39.428611, 'Timezone': 9.0}),
231 ('RJSY', {'City': 'Shonai', 'Name': 'Shonai Airport', 'Altitude': 86, 'Longitude': 139.787222, 'Latitude': 38.812222, 'Timezone': 9.0}),
232 ('RJSC', {'City': 'Yamagata', 'Name': 'Yamagata', 'Altitude': 353, 'Longitude': 140.371331, 'Latitude': 38.411894, 'Timezone': 9.0}),
233 ('RJST', {'City': 'Matsushima', 'Name': 'Matsushima', 'Altitude': 7, 'Longitude': 141.219572, 'Latitude': 38.404919, 'Timezone': 9.0}),
234 ('RJSS', {'City': 'Sendai', 'Name': 'Sendai', 'Altitude': 15, 'Longitude': 140.916944, 'Latitude': 38.139722, 'Timezone': 9.0}),
235 ('RJSD', {'City': 'Sado', 'Name': 'Sado', 'Altitude': 88, 'Longitude': 138.413928, 'Latitude': 38.060181, 'Timezone': 9.0}),
236 ('RJSN', {'City': 'Niigata', 'Name': 'Niigata', 'Altitude': 1, 'Longitude': 139.0646, 'Latitude': 37.5711, 'Timezone': 9.0}),
237 ('RJNW', {'City': 'Wajima', 'Name': 'Noto', 'Altitude': 718, 'Longitude': 136.961853, 'Latitude': 37.293097, 'Timezone': 9.0}),
238 ('RJSF', {'City': 'Fukushima', 'Name': 'Fukushima Airport', 'Altitude': 1221, 'Longitude': 140.431, 'Latitude': 37.2274, 'Timezone': 9.0}),
239 ('RJNT', {'City': 'Toyama', 'Name': 'Toyama', 'Altitude': 95, 'Longitude': 137.1875, 'Latitude': 36.648333, 'Timezone': 9.0}),
240 ('RJNK', {'City': 'Kanazawa', 'Name': 'Komatsu', 'Altitude': 36, 'Longitude': 136.406544, 'Latitude': 36.394611, 'Timezone': 9.0}),
241 ('RJNO', {'City': 'Oki Island', 'Name': 'Oki', 'Altitude': 311, 'Longitude': 133.324844, 'Latitude': 36.181125, 'Timezone': 9.0}),
242 ('RJAH', {'City': 'Ibaraki', 'Name': 'Hyakuri', 'Altitude': 105, 'Longitude': 140.415444, 'Latitude': 36.181083, 'Timezone': 9.0}),
243 ('RJAF', {'City': 'Matsumoto', 'Name': 'Matsumoto', 'Altitude': 2182, 'Longitude': 137.922669, 'Latitude': 36.166758, 'Timezone': 9.0}),
244 ('RJNF', {'City': 'Fukui', 'Name': 'Fukui', 'Altitude': 19, 'Longitude': 136.223922, 'Latitude': 36.142847, 'Timezone': 9.0}),
245 ('RJTJ', {'City': 'Iruma', 'Name': 'Iruma', 'Altitude': 295, 'Longitude': 139.410556, 'Latitude': 35.841944, 'Timezone': 9.0}),
246 ('RJTL', {'City': 'Shimofusa', 'Name': 'Shimofusa', 'Altitude': 98, 'Longitude': 140.011111, 'Latitude': 35.798944, 'Timezone': 9.0}),
247 ('RJAA', {'City': 'Tokyo', 'Name': 'Narita Intl', 'Altitude': 141, 'Longitude': 140.386389, 'Latitude': 35.764722, 'Timezone': 9.0}),
248 ('RJTY', {'City': 'Yokota', 'Name': 'Yokota Ab', 'Altitude': 463, 'Longitude': 139.348483, 'Latitude': 35.748492, 'Timezone': 9.0}),
249 ('RJTT', {'City': 'Tokyo', 'Name': 'Tokyo Intl', 'Altitude': 35, 'Longitude': 139.779694, 'Latitude': 35.552258, 'Timezone': 9.0}),
250 ('RJOR', {'City': 'Tottori', 'Name': 'Tottori', 'Altitude': 65, 'Longitude': 134.166553, 'Latitude': 35.530069, 'Timezone': 9.0}),
251 ('RJTR', {'City': 'Zama', 'Name': 'Kastner Aaf', 'Altitude': 360, 'Longitude': 139.393675, 'Latitude': 35.513769, 'Timezone': 9.0}),
252 ('RJBT', {'City': 'Toyooka', 'Name': 'Tajima Airport', 'Altitude': 578, 'Longitude': 134.786944, 'Latitude': 35.512778, 'Timezone': 9.0}),
253 ('RJOH', {'City': 'Miho', 'Name': 'Yonago Kitaro', 'Altitude': 20, 'Longitude': 133.236389, 'Latitude': 35.492222, 'Timezone': 9.0}),
254 ('RJTA', {'City': 'Atsugi', 'Name': 'Atsugi Naf', 'Altitude': 205, 'Longitude': 139.450167, 'Latitude': 35.454611, 'Timezone': 9.0}),
255 ('RJOC', {'City': 'Izumo', 'Name': 'Izumo', 'Altitude': 15, 'Longitude': 132.89, 'Latitude': 35.413611, 'Timezone': 9.0}),
256 ('RJTK', {'City': 'Kisarazu', 'Name': 'Kisarazu', 'Altitude': 10, 'Longitude': 139.909936, 'Latitude': 35.398272, 'Timezone': 9.0}),
257 ('RJNG', {'City': 'Gifu', 'Name': 'Gifu', 'Altitude': 128, 'Longitude': 136.869667, 'Latitude': 35.394078, 'Timezone': 9.0}),
258 ('RJNA', {'City': 'Nagoya', 'Name': 'Nagoya Airport', 'Altitude': 52, 'Longitude': 136.924, 'Latitude': 35.255, 'Timezone': 9.0}),
259 ('RJTE', {'City': 'Tateyama', 'Name': 'Tateyama', 'Altitude': 10, 'Longitude': 139.829208, 'Latitude': 34.987053, 'Timezone': 9.0}),
260 ('RJGG', {'City': 'Nagoya', 'Name': 'Chubu Centrair Intl', 'Altitude': 15, 'Longitude': 136.805408, 'Latitude': 34.858414, 'Timezone': 9.0}),
261 ('RJNY', {'City': 'Yaizu', 'Name': 'Shizuhama', 'Altitude': 23, 'Longitude': 138.298056, 'Latitude': 34.812778, 'Timezone': 9.0}),
262 ('RJNS', {'City': 'Shizuoka', 'Name': 'Mt. Fuji Shizuoka Airport', 'Altitude': 433, 'Longitude': 138.189444, 'Latitude': 34.796111, 'Timezone': 9.0}),
263 ('RJOO', {'City': 'Osaka', 'Name': 'Osaka Intl', 'Altitude': 50, 'Longitude': 135.438222, 'Latitude': 34.785528, 'Timezone': 9.0}),
264 ('RJTO', {'City': 'Oshima', 'Name': 'Oshima', 'Altitude': 130, 'Longitude': 139.360306, 'Latitude': 34.782033, 'Timezone': 9.0}),
265 ('RJOB', {'City': 'Okayama', 'Name': 'Okayama', 'Altitude': 806, 'Longitude': 133.855278, 'Latitude': 34.756944, 'Timezone': 9.0}),
266 ('RJNH', {'City': 'Hamamatsu', 'Name': 'Hamamatsu', 'Altitude': 150, 'Longitude': 137.703083, 'Latitude': 34.750239, 'Timezone': 9.0}),
267 ('RJOW', {'City': 'Iwami', 'Name': 'Iwami Airport', 'Altitude': 184, 'Longitude': 131.79, 'Latitude': 34.6764, 'Timezone': 9.0}),
268 ('RJBE', {'City': 'Kobe', 'Name': 'Kobe', 'Altitude': 22, 'Longitude': 135.223889, 'Latitude': 34.632778, 'Timezone': 9.0}),
269 ('RJOY', {'City': 'Osaka', 'Name': 'Yao', 'Altitude': 39, 'Longitude': 135.602944, 'Latitude': 34.596311, 'Timezone': 9.0}),
270 ('RJBK', {'City': 'Kohnan', 'Name': 'Kohnan', 'Altitude': 3, 'Longitude': 133.933225, 'Latitude': 34.590836, 'Timezone': 9.0}),
271 ('RJOE', {'City': 'Akeno', 'Name': 'Akeno Aero', 'Altitude': 12, 'Longitude': 136.672222, 'Latitude': 34.533333, 'Timezone': 9.0}),
272 ('RJOA', {'City': 'Hiroshima', 'Name': 'Hiroshima', 'Altitude': 1088, 'Longitude': 132.919444, 'Latitude': 34.436111, 'Timezone': 9.0}),
273 ('RJBB', {'City': 'Osaka', 'Name': 'Kansai', 'Altitude': 49, 'Longitude': 135.244167, 'Latitude': 34.4347222, 'Timezone': 9.0}),
274 ('RJBH', {'City': 'Hiroshima', 'Name': 'Hiroshima-Nishi', 'Altitude': 9, 'Longitude': 132.408, 'Latitude': 34.367, 'Timezone': 9.0}),
275 ('RJAN', {'City': 'Niijima', 'Name': 'Niijima Airport', 'Altitude': 133, 'Longitude': 139.268611, 'Latitude': 34.366944, 'Timezone': 9.0}),
276 ('RJDT', {'City': 'Tsushima', 'Name': 'Tsushima', 'Altitude': 213, 'Longitude': 129.33055, 'Latitude': 34.284889, 'Timezone': 9.0}),
277 ('RJOT', {'City': 'Takamatsu', 'Name': 'Takamatsu', 'Altitude': 607, 'Longitude': 134.015556, 'Latitude': 34.214167, 'Timezone': 9.0}),
278 ('RJOI', {'City': 'Iwakuni', 'Name': 'Iwakuni Mcas', 'Altitude': 7, 'Longitude': 132.23575, 'Latitude': 34.14386, 'Timezone': 9.0}),
279 ('RJOS', {'City': 'Tokushima', 'Name': 'Tokushima', 'Altitude': 26, 'Longitude': 134.606639, 'Latitude': 34.132808, 'Timezone': 9.0}),
280 ('RJTQ', {'City': 'Miyakejima', 'Name': 'Miyakejima Airport', 'Altitude': 67, 'Longitude': 139.56, 'Latitude': 34.0736, 'Timezone': 9.0}),
281 ('RJOZ', {'City': 'Ozuki', 'Name': 'Ozuki', 'Altitude': 13, 'Longitude': 131.052144, 'Latitude': 34.045322, 'Timezone': 9.0}),
282 ('RJOF', {'City': 'Hofu', 'Name': 'Hofu', 'Altitude': 7, 'Longitude': 131.549194, 'Latitude': 34.034667, 'Timezone': 9.0}),
283 ('RJDC', {'City': 'Yamaguchi', 'Name': 'Yamaguchi Ube', 'Altitude': 23, 'Longitude': 131.278611, 'Latitude': 33.93, 'Timezone': 9.0}),
284 ('RJFA', {'City': 'Ashiya', 'Name': 'Ashiya', 'Altitude': 98, 'Longitude': 130.653, 'Latitude': 33.883083, 'Timezone': 9.0}),
285 ('RJFR', {'City': 'Kitakyushu', 'Name': 'New Kitakyushu', 'Altitude': 21, 'Longitude': 131.034689, 'Latitude': 33.845942, 'Timezone': 9.0}),
286 ('RJOM', {'City': 'Matsuyama', 'Name': 'Matsuyama', 'Altitude': 25, 'Longitude': 132.699722, 'Latitude': 33.827222, 'Timezone': 9.0}),
287 ('RJDB', {'City': 'Iki', 'Name': 'Iki', 'Altitude': 41, 'Longitude': 129.785417, 'Latitude': 33.749027, 'Timezone': 9.0}),
288 ('RJFZ', {'City': 'Tsuiki', 'Name': 'Tsuiki', 'Altitude': 55, 'Longitude': 131.040278, 'Latitude': 33.685, 'Timezone': 9.0}),
289 ('RJBD', {'City': 'Nanki-shirahama', 'Name': 'Nanki Shirahama', 'Altitude': 298, 'Longitude': 135.364444, 'Latitude': 33.662222, 'Timezone': 9.0}),
290 ('RJFF', {'City': 'Fukuoka', 'Name': 'Fukuoka', 'Altitude': 32, 'Longitude': 130.450686, 'Latitude': 33.585942, 'Timezone': 9.0}),
291 ('RJOK', {'City': 'Kochi', 'Name': 'Kochi', 'Altitude': 42, 'Longitude': 133.669444, 'Latitude': 33.546111, 'Timezone': 9.0}),
292 ('RJFO', {'City': 'Oita', 'Name': 'Oita', 'Altitude': 19, 'Longitude': 131.737222, 'Latitude': 33.479444, 'Timezone': 9.0}),
293 ('RJFS', {'City': 'Saga', 'Name': 'Saga Airport', 'Altitude': 6, 'Longitude': 130.302, 'Latitude': 33.1497, 'Timezone': 9.0}),
294 ('RJTH', {'City': 'Hachijojima', 'Name': 'Hachijojima', 'Altitude': 303, 'Longitude': 139.785833, 'Latitude': 33.115, 'Timezone': 9.0}),
295 ('RJFU', {'City': 'Nagasaki', 'Name': 'Nagasaki', 'Altitude': 15, 'Longitude': 129.913611, 'Latitude': 32.916944, 'Timezone': 9.0}),
296 ('RJFT', {'City': 'Kumamoto', 'Name': 'Kumamoto', 'Altitude': 642, 'Longitude': 130.85505, 'Latitude': 32.837319, 'Timezone': 9.0}),
297 ('RJFE', {'City': 'Fukue', 'Name': 'Fukue', 'Altitude': 273, 'Longitude': 128.832808, 'Latitude': 32.666269, 'Timezone': 9.0}),
298 ('RJDA', {'City': 'Amakusa', 'Name': 'Amakusa Airfield', 'Altitude': 340, 'Longitude': 130.158889, 'Latitude': 32.482222, 'Timezone': 9.0}),
299 ('RJFN', {'City': 'Nyutabaru', 'Name': 'Nyutabaru', 'Altitude': 259, 'Longitude': 131.451389, 'Latitude': 32.083611, 'Timezone': 9.0}),
300 ('RJFM', {'City': 'Miyazaki', 'Name': 'Miyazaki', 'Altitude': 20, 'Longitude': 131.448611, 'Latitude': 31.877222, 'Timezone': 9.0}),
301 ('RJFK', {'City': 'Kagoshima', 'Name': 'Kagoshima', 'Altitude': 906, 'Longitude': 130.719408, 'Latitude': 31.803397, 'Timezone': 9.0}),
302 ('RJFY', {'City': 'Kanoya', 'Name': 'Kanoya', 'Altitude': 214, 'Longitude': 130.845456, 'Latitude': 31.367608, 'Timezone': 9.0}),
303 ('RJFG', {'City': 'Tanegashima', 'Name': 'New Tanegashima', 'Altitude': 768, 'Longitude': 130.991231, 'Latitude': 30.605067, 'Timezone': 9.0}),
304 ('RJFC', {'City': 'Yakushima', 'Name': 'Yakushima', 'Altitude': 124, 'Longitude': 130.659017, 'Latitude': 30.385569, 'Timezone': 9.0}),
305 ('RJKA', {'City': 'Amami', 'Name': 'Amami', 'Altitude': 27, 'Longitude': 129.712542, 'Latitude': 28.430633, 'Timezone': 9.0}),
306 ('RJKI', {'City': 'Kikai', 'Name': 'Kikai Airport', 'Altitude': 15, 'Longitude': 129.928056, 'Latitude': 28.321389, 'Timezone': 9.0}),
307 ('RJKN', {'City': 'Tokunoshima', 'Name': 'Tokunoshima', 'Altitude': 17, 'Longitude': 128.881253, 'Latitude': 27.836381, 'Timezone': 9.0}),
308 ('RJKB', {'City': 'Okierabu', 'Name': 'Okierabu', 'Altitude': 101, 'Longitude': 128.700903, 'Latitude': 27.425522, 'Timezone': 9.0}),
309 ('RORY', {'City': 'Yoron', 'Name': 'Yoron', 'Altitude': 52, 'Longitude': 128.401517, 'Latitude': 27.043964, 'Timezone': 9.0}),
310 ('RODE', {'City': 'Iejima', 'Name': 'Ie Shima Aux Ab', 'Altitude': 184, 'Longitude': 127.761775, 'Latitude': 26.728775, 'Timezone': 9.0}),
311 ('RORA', {'City': 'Aguni', 'Name': 'Aguni Airport', 'Altitude': 38, 'Longitude': 127.240278, 'Latitude': 26.592778, 'Timezone': 9.0}),
312 ('ROKJ', {'City': 'Kumejima', 'Name': 'Kumejima', 'Altitude': 23, 'Longitude': 126.713806, 'Latitude': 26.363506, 'Timezone': 9.0}),
313 ('RODN', {'City': 'Kadena', 'Name': 'Kadena Ab', 'Altitude': 143, 'Longitude': 127.767633, 'Latitude': 26.355612, 'Timezone': 9.0}),
314 ('ROTM', {'City': 'Futema', 'Name': 'Futenma Mcas', 'Altitude': 247, 'Longitude': 127.756494, 'Latitude': 26.274275, 'Timezone': 9.0}),
315 ('ROAH', {'City': 'Okinawa', 'Name': 'Naha', 'Altitude': 12, 'Longitude': 127.645869, 'Latitude': 26.195814, 'Timezone': 9.0}),
316 ('ROKR', {'City': 'Kerama', 'Name': 'Kerama Airport', 'Altitude': 156, 'Longitude': 127.293333, 'Latitude': 26.168333, 'Timezone': 9.0}),
317 ('RORK', {'City': 'Kitadaito', 'Name': 'Kitadaito', 'Altitude': 80, 'Longitude': 131.326944, 'Latitude': 25.944722, 'Timezone': 9.0}),
318 ('ROMD', {'City': 'Minami Daito', 'Name': 'Minami Daito', 'Altitude': 167, 'Longitude': 131.263494, 'Latitude': 25.846533, 'Timezone': 9.0}),
319 ('RORS', {'City': 'Shimojishima', 'Name': 'Shimojishima', 'Altitude': 54, 'Longitude': 125.144722, 'Latitude': 24.826667, 'Timezone': 9.0}),
320 ('RJAW', {'City': 'Iwojima', 'Name': 'Iwo Jima', 'Altitude': 384, 'Longitude': 141.322722, 'Latitude': 24.784, 'Timezone': 10.0}),
321 ('ROMY', {'City': 'Miyako', 'Name': 'Miyako', 'Altitude': 150, 'Longitude': 125.295111, 'Latitude': 24.782833, 'Timezone': 9.0}),
322 ('RORT', {'City': 'Tarama', 'Name': 'Tarama', 'Altitude': 36, 'Longitude': 124.675278, 'Latitude': 24.653889, 'Timezone': 9.0}),
323 ('ROYN', {'City': 'Yonaguni Jima', 'Name': 'Yonaguni', 'Altitude': 70, 'Longitude': 122.977778, 'Latitude': 24.466944, 'Timezone': 9.0}),
324 ('ROIG', {'City': 'Ishigaki', 'Name': 'Ishigaki', 'Altitude': 93, 'Longitude': 124.186983, 'Latitude': 24.344525, 'Timezone': 9.0}),
325 ('RJAM', {'City': 'Minami Tori Shima', 'Name': 'Minami Torishima', 'Altitude': 22, 'Longitude': 153.979119, 'Latitude': 24.289697, 'Timezone': 10.0}),
326 ]
327 #ALL_AIRPORTS_DICT = dict(ALL_AIRPORTS)
328
329 if __name__ == '__main__':
330 import sys, codecs
331 import time
332
333 fo = codecs.getwriter('utf-8')(open("jp_airports_sunrise_sunset.html", "w"))
334
335 tm = time.localtime()
336
337 fo.write("""\
338 <html dir="ltr" lang="ja">
339 <head>
340 <meta charset="UTF-8">
341 <meta name="robots" content="noindex,nofollow,noodp,noydir">
342 <style type="text/css">
343 <!--
344 body { margin: 2em; }
345 h1 {
346 font-size: 2em;
347 padding-bottom: 0.2em;
348 border-bottom: 5px #770000 solid;
349 }
350 .icao4letter { font-weight: 900; background-color: #eef; }
351 .sunrise { background-color: yellow; }
352 .sunset { background-color: orange; }
353 -->
354 </style>
355 </head>
356 <body>
357 """)
358 fo.write(u"""\
359 <h1>日本の空港の日の出日没時刻(%d-%02d-%02d)</h1>
360 <p>
361 <a href="http://hhsprings.pinoko.jp/site-hhs/2015/02/%%E6%%97%%A5%%E5%%87%%BA%%E6%%97%%A5%%E6%%B2%%A1%%E8%%A8%%88%%E7%%AE%%97%%E3%%80%%81%%E3%%82%%84%%E3%%81%%A3%%E3%%81%%A6%%E3%%81%%BF%%E3%%82%%88%%E3%%81%%86/" target="_blank">日出日没計算、やってみよう</a>の実践、です。CGIでもなんでもないただのバッチで毎日静的ページを作っているだけでございます。半年後を知りたい、のようなことには対応できませんです。
362
363 <p>
364 <a href="http://www.hoshi-lab.info/env/solar-j.html">
365 近畿大学 星 岳彦 さん作成の日の出と日の入りの計算
366 </a>
367 と同じことをしているはずです、多分。Pythonに移植したままのテストプログラムの結果
368 そのもので、あまり正確なテストはしておりませんし、また、もともと1分の精度は
369 ありませんし、本来地形の影響等々様々な原因で日の出日没時間は現実とはずれます。
370
371 ですので、本データを使用したいかなる損害についても、当方関知しませんし、「そういうものだ」
372 と思ってくださいますよう。
373 <p>
374 """ % (tm.tm_year, tm.tm_mon, tm.tm_mday))
375 fo.write("""\
376 <table border='1'>
377 """)
378 for icao4letter, airpt_info in ALL_AIRPORTS:
379 airpt_info["ICAO4letter"] = icao4letter
380 r = calc(tm.tm_year, tm.tm_mon, tm.tm_mday,
381 airpt_info["Timezone"],
382 airpt_info["Longitude"],
383 airpt_info["Latitude"],
384 airpt_info["Altitude"] * 0.3048)
385 fo.write("""\
386 <tr>
387 <tr><td rowspan="5" class="icao4letter">{ICAO4letter}</td><td>Name</td><td>{Name}</td></tr>
388 <tr><td>City</td><td>{City}</td></tr>
389 <tr><td>Lon / Lat</td><td>{Longitude} / {Latitude}</td></tr>
390 <tr><td>Altitude</td><td>{Altitude} [feets]</td></tr>
391 <tr>
392 """.format(**airpt_info))
393 fo.write("""\
394 <td></td>
395 <td>
396 <table border="1">
397 <tr><td>astronomical twilight start</td><td>%s</td><td> </td></tr>
398 <tr><td>nautical twilight start </td><td>%s</td><td> </td></tr>
399 <tr><td>citizen twilight start </td><td>%s</td><td> </td></tr>
400 <tr class="sunrise"><td>sun rise </td><td>%s</td><td>solar direction (in degrees): %d</td></tr>
401 <tr><td>meridian </td><td>%s</td><td>solar altitude (in degrees): %d</td></tr>
402 <tr class="sunset"><td>sun set </td><td>%s</td><td>solar direction (in degrees): %d</td></tr>
403 <tr><td>citizen twilight end </td><td>%s</td><td> </td></tr>
404 <tr><td>nautical twilight end </td><td>%s</td><td> </td></tr>
405 <tr><td>astronomical twilight end </td><td>%s</td><td> </td></tr>
406 </table>
407 </td>
408 </tr>
409 </tr>
410
411 """ % (
412 r[0][0], #astronomical twilight start
413 r[1][0], #nautical twilight start
414 r[2][0], #citizen twilight start
415 r[3][0], r[3][1], #sun rise
416 r[4][0], r[4][1], #meridian
417 r[5][0], r[5][1], #sun set
418 r[6][0], #citizen twilight end
419 r[7][0], #nautical twilight end
420 r[8][0], #astronomical twilight end
421 ))
422 fo.write("""\
423 </table>
424 </body>
425 </html>""")
426 fo.close()