when_exe 0.4.1 → 0.4.2

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.
Files changed (96) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +36 -33
  3. data/bin/locales.rb +1 -1
  4. data/bin/make_ttl.rb.config +1 -1
  5. data/lib/when_exe.rb +27 -16
  6. data/lib/when_exe/basictypes.rb +772 -771
  7. data/lib/when_exe/calendartypes.rb +1485 -1453
  8. data/lib/when_exe/coordinates.rb +5 -0
  9. data/lib/when_exe/core/compatibility.rb +1 -1
  10. data/lib/when_exe/core/duration.rb +147 -116
  11. data/lib/when_exe/core/extension.rb +499 -497
  12. data/lib/when_exe/ephemeris.rb +1952 -1951
  13. data/lib/when_exe/ephemeris/eclipse.rb +5 -4
  14. data/lib/when_exe/ephemeris/notes.rb +457 -421
  15. data/lib/when_exe/ephemeris/planets.rb +585 -585
  16. data/lib/when_exe/ephemeris/sun.rb +214 -214
  17. data/lib/when_exe/google_api.rb +153 -0
  18. data/lib/when_exe/icalendar.rb +1640 -1632
  19. data/lib/when_exe/inspect.rb +42 -20
  20. data/lib/when_exe/linkeddata.rb +28 -7
  21. data/lib/when_exe/locales/autoload.rb +2 -1
  22. data/lib/when_exe/locales/locale.rb +35 -15
  23. data/lib/when_exe/locales/zh.rb +77 -0
  24. data/lib/when_exe/mini_application.rb +3 -1
  25. data/lib/when_exe/{googlecalendar.rb → obsolete/googlecalendar.rb} +144 -144
  26. data/lib/when_exe/parts/enumerator.rb +498 -486
  27. data/lib/when_exe/parts/geometric_complex.rb +397 -397
  28. data/lib/when_exe/parts/timezone.rb +246 -241
  29. data/lib/when_exe/region/armenian.rb +55 -56
  30. data/lib/when_exe/region/babylonian.rb +406 -405
  31. data/lib/when_exe/region/bahai.rb +107 -106
  32. data/lib/when_exe/region/balinese.rb +624 -622
  33. data/lib/when_exe/region/chinese.rb +1071 -1026
  34. data/lib/when_exe/region/chinese/epochs.rb +28 -28
  35. data/lib/when_exe/region/chinese/notes.rb +219 -0
  36. data/lib/when_exe/region/chinese/twins.rb +803 -803
  37. data/lib/when_exe/region/christian.rb +21 -15
  38. data/lib/when_exe/region/coptic.rb +107 -106
  39. data/lib/when_exe/region/discordian.rb +218 -218
  40. data/lib/when_exe/region/east_asian.rb +1 -1
  41. data/lib/when_exe/region/french.rb +126 -56
  42. data/lib/when_exe/region/geologicalage.rb +639 -639
  43. data/lib/when_exe/region/goddess.rb +60 -58
  44. data/lib/when_exe/region/hanke_henry.rb +2 -2
  45. data/lib/when_exe/region/indian.rb +1225 -1222
  46. data/lib/when_exe/region/international_fixed.rb +96 -97
  47. data/lib/when_exe/region/iranian.rb +206 -203
  48. data/lib/when_exe/region/islamic.rb +102 -102
  49. data/lib/when_exe/region/japanese.rb +126 -71
  50. data/lib/when_exe/region/japanese/epochs.rb +426 -426
  51. data/lib/when_exe/region/japanese/notes.rb +101 -81
  52. data/lib/when_exe/region/japanese/residues.rb +1345 -1311
  53. data/lib/when_exe/region/japanese/twins.rb +225 -225
  54. data/lib/when_exe/region/japanese/weeks.rb +112 -112
  55. data/lib/when_exe/region/javanese.rb +230 -230
  56. data/lib/when_exe/region/jewish.rb +130 -131
  57. data/lib/when_exe/region/m17n.rb +114 -114
  58. data/lib/when_exe/region/martian.rb +258 -258
  59. data/lib/when_exe/region/mayan.rb +11 -8
  60. data/lib/when_exe/region/pax.rb +4 -5
  61. data/lib/when_exe/region/pope.rb +1 -1
  62. data/lib/when_exe/region/positivist.rb +100 -100
  63. data/lib/when_exe/region/residue.rb +162 -162
  64. data/lib/when_exe/region/roman.rb +333 -333
  65. data/lib/when_exe/region/{soviet.rb → russian.rb} +221 -209
  66. data/lib/when_exe/region/shire.rb +222 -223
  67. data/lib/when_exe/region/symmetry.rb +50 -50
  68. data/lib/when_exe/region/thai.rb +336 -336
  69. data/lib/when_exe/region/tibetan.rb +315 -316
  70. data/lib/when_exe/region/tranquility.rb +207 -208
  71. data/lib/when_exe/region/vanishing_leprechaun.rb +3 -1
  72. data/lib/when_exe/region/vietnamese.rb +449 -440
  73. data/lib/when_exe/region/weekdate.rb +80 -80
  74. data/lib/when_exe/region/world.rb +170 -171
  75. data/lib/when_exe/region/world_season.rb +89 -89
  76. data/lib/when_exe/region/yerm.rb +3 -3
  77. data/lib/when_exe/region/zoroastrian.rb +205 -205
  78. data/lib/when_exe/timestandard.rb +708 -707
  79. data/lib/when_exe/tmduration.rb +338 -338
  80. data/lib/when_exe/tmobjects.rb +1356 -1356
  81. data/lib/when_exe/tmposition.rb +66 -31
  82. data/lib/when_exe/version.rb +16 -2
  83. data/test/examples/Residue.m17n +83 -83
  84. data/test/examples/Terms.m17n +2 -2
  85. data/test/test.rb +2 -2
  86. data/test/test/google_api.rb +65 -0
  87. data/test/test/linkeddata.rb +1 -1
  88. data/test/test/{googlecalendar.rb → obsolete/googlecalendar.rb} +194 -194
  89. data/test/test/region/indian.rb +90 -85
  90. data/test/test/region/m17n.rb +7 -7
  91. data/test/test/region/mayan.rb +195 -195
  92. data/test/test/region/residue.rb +153 -153
  93. data/test/test/tmposition.rb +11 -1
  94. data/when_exe.gemspec +2 -2
  95. metadata +95 -8
  96. data/test/test.rb.config +0 -1
@@ -1,707 +1,708 @@
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
- #
9
- # 標準的な時刻系の定義
10
- #
11
- module When::TimeStandard
12
-
13
- # TT(Terrestrial Time) - UTC(Universal Time, Coordinated) at 1970-01-01T00:00:00Z
14
- DeltaT0 = (40 + 377.0/2048) * When::TM::Duration::SECOND
15
-
16
- TAI_UTC = # http://maia.usno.navy.mil/ser7/tai-utc.dat
17
- [[2437300.5, 1.422818, 37300.0, 0.001296 ],
18
- [2437512.5, 1.372818, 37300.0, 0.001296 ],
19
- [2437665.5, 1.845858, 37665.0, 0.0011232],
20
- [2438334.5, 1.945858, 37665.0, 0.0011232],
21
- [2438395.5, 3.24013, 38761.0, 0.001296 ],
22
- [2438486.5, 3.34013, 38761.0, 0.001296 ],
23
- [2438639.5, 3.44013, 38761.0, 0.001296 ],
24
- [2438761.5, 3.54013, 38761.0, 0.001296 ],
25
- [2438820.5, 3.64013, 38761.0, 0.001296 ],
26
- [2438942.5, 3.74013, 38761.0, 0.001296 ],
27
- [2439004.5, 3.84013, 38761.0, 0.001296 ],
28
- [2439126.5, 4.31317, 39126.0, 0.002592 ],
29
- [2439887.5, 4.21317, 39126.0, 0.002592 ],
30
- [2441317.5, 10.0],
31
- [2441499.5, 11.0],
32
- [2441683.5, 12.0],
33
- [2442048.5, 13.0],
34
- [2442413.5, 14.0],
35
- [2442778.5, 15.0],
36
- [2443144.5, 16.0],
37
- [2443509.5, 17.0],
38
- [2443874.5, 18.0],
39
- [2444239.5, 19.0],
40
- [2444786.5, 20.0],
41
- [2445151.5, 21.0],
42
- [2445516.5, 22.0],
43
- [2446247.5, 23.0],
44
- [2447161.5, 24.0],
45
- [2447892.5, 25.0],
46
- [2448257.5, 26.0],
47
- [2448804.5, 27.0],
48
- [2449169.5, 28.0],
49
- [2449534.5, 29.0],
50
- [2450083.5, 30.0],
51
- [2450630.5, 31.0],
52
- [2451179.5, 32.0],
53
- [2453736.5, 33.0],
54
- [2454832.5, 34.0],
55
- [2456109.5, 35.0]]
56
-
57
- DeltaT = [ 63.467, # 1999
58
- 63.827, 64.092, 64.300, 64.473, 64.573, 64.689, 64.846, 65.145, 65.456, 65.779, # 2000-
59
- 66.070, 66.324, 66.603, 66.909 # 2010-
60
- ]
61
-
62
- class << self
63
- # When::TimeStandard Module のグローバルな設定を行う
64
- #
65
- # @param [String] leap_seconds http://maia.usno.navy.mil/ser7/tai-utc.dat 形式のファイルのファイルパス
66
- # @param [Array<Array<Numeric>>] leap_seconds 閏秒の挿入記録 [ [ JD, TAI-UTC, (MJD, OFFSET) ] ]
67
- # [ JD - 閏秒を挿入した日時のユリウス日 ]
68
- # [ TAI-UTC - 閏秒を挿入後の TAI と UTC の差 ]
69
- # [ MJD - 周波数オフセットの基準となる日時の修正ユリウス日 ]
70
- # [ OFFSET - 周波数オフセット値 ]
71
- #
72
- # @return [void]
73
- #
74
- # @note
75
- # 本メソッドでマルチスレッド対応の管理変数の初期化を行っている。
76
- # このため、本メソッド自体はスレッドセーフでない。
77
- #
78
- def _setup_(leap_seconds=nil)
79
- @_lock_ = Mutex.new if When.multi_thread
80
- leap_seconds ||= TAI_UTC
81
- @leap_seconds =
82
- if leap_seconds.kind_of?(String)
83
- OpenURI
84
- open(leap_seconds) do |file|
85
- file.read.split(/[\n\r]+/).map { |line|
86
- line.split(/[^\d.]+/)[3..6].map {|d| d.to_f}
87
- }.reverse
88
- end
89
- else
90
- leap_seconds.reverse
91
- end
92
- end
93
-
94
- # 設定情報を取得する
95
- #
96
- # @return [Hash] 設定情報
97
- #
98
- def _setup_info
99
- {:leap_seconds => _leap_seconds}
100
- end
101
-
102
- # @private
103
- # 閏秒の挿入記録を取得する
104
- def _leap_seconds
105
- @leap_seconds ||= TAI_UTC.reverse
106
- end
107
-
108
- # 処理系が閏秒を無視しているか否か
109
- # @private
110
- def _is_systemtime_universal?
111
- @is_systemtime_universal = ((Time.utc(1976).to_i - Time.utc(1975).to_i) % 86400 == 0) if @is_systemtime_universal == nil
112
- @is_systemtime_universal
113
- end
114
-
115
- # ΔT
116
- #
117
- # @param [Numeric] jd_utc ユリウス日(Universal Time, Coordinated)
118
- #
119
- # @return [Numeric] (dynamical_time - universal_time) / second
120
- # 1/2048 second(≒0.5ms)未満を四捨五入
121
- #
122
- def delta_t(jd_utc)
123
- (delta_t_coordinated(jd_utc) * 4096 + 1).floor / 4096.0
124
- end
125
- alias :deltaT :delta_t
126
-
127
- # ΔT - 閏秒による(TT-UTC)
128
- #
129
- # @param [Numeric] jd_utc ユリウス日(Universal Time, Coordinated)
130
- #
131
- # @return [Numeric] (Terrestrial Time - Universal Time, Coordinated) / second
132
- #
133
- def delta_t_coordinated(jd_utc)
134
- list = _leap_seconds
135
- list.each do |v|
136
- if jd_utc >= v[0]
137
- result = 32.184 + v[1]
138
- result += (jd_utc - (2400000.5 + v[2])) * v[3] unless (v[3]||0) == 0
139
- return result
140
- end
141
- end
142
- delta_t_observed(jd_utc)
143
- end
144
-
145
- # ΔT - 観測による(TT-UT1) mix of Table and NASA
146
- #
147
- # @param [Numeric] jd_utc ユリウス日(Universal Time, Coordinated)
148
- #
149
- # @return [Numeric] (Terrestrial Time - Universal Time 1) / second
150
- #
151
- def delta_t_observed(jd_utc)
152
- year = (jd_utc - When::Ephemeris::EPOCH2000)/When::Ephemeris::JYEAR + 2000 # 0年からの経過世紀
153
- return delta_t_observed_poly(year) unless 2000 <= year && year < 2050
154
- return delta_t_observed_poly(year) + DeltaThreshold * (year - 2050.0) / (YearThreshold - 2050.0) if year >= YearThreshold
155
-
156
- i = (year-1999.0).floor # 1999年からの経過年(整数)
157
- n = year % 1
158
- d0 = DeltaT[i+0] - DeltaT[i-1]
159
- d1 = DeltaT[i+1] - DeltaT[i+0]
160
- d2 = DeltaT[i+2] - DeltaT[i+1]
161
- d10 = d1 - d0
162
- d21 = d2 - d1
163
- d210 = d21 - d10
164
- DeltaT[i] + n*d1 + n*(n-1.0)/4.0*(d10+d21) + n*(n-1.0)*(n-0.5)/6.0*d210
165
- end
166
-
167
- # ΔT - 観測による(TT-UT1) from http://eclipse.gsfc.nasa.gov/SEhelp/deltatpoly2004.html
168
- #
169
- # @param [Numeric] jd_utc ユリウス日(Universal Time, Coordinated)
170
- #
171
- # @return [Numeric] (Terrestrial Time - Universal Time 1) / second
172
- #
173
- def delta_t_observed_nasa(jd_utc)
174
- delta_t_observed_poly((jd_utc - When::Ephemeris::EPOCH2000)/When::Ephemeris::JYEAR + 2000.0) # 0年からの経過年
175
- end
176
-
177
- # 多項式による近似
178
- def delta_t_observed_poly(year)
179
- u = (year-1820)/100
180
-
181
- # 2150 ... 3000
182
- if year >= 2150
183
- -20 + 32 * u**2
184
-
185
- # 2050 ... 2150
186
- elsif year >= 2050
187
- -20 + 32 * u**2 - 0.5628 * (2150 - year)
188
-
189
- # 2005 ... 2050
190
- elsif year >= 2005
191
- t = year - 2000
192
- 62.92 + 0.32217 * t + 0.005589 * t**2
193
-
194
- # 1986 ... 2005
195
- elsif year >= 1986
196
- t = year - 2000
197
- 63.86 + 0.3345 * t - 0.060374 * t**2 + 0.0017275 * t**3 + 0.000651814 * t**4 + 0.00002373599 * t**5
198
-
199
- # 1961 ... 1986
200
- elsif year >= 1961
201
- t = year - 1975
202
- 45.45 + 1.067*t - t**2/260 - t**3 / 718
203
-
204
- # 1941 ... 1961
205
- elsif year >= 1941
206
- t = year - 1950
207
- 29.07 + 0.407*t - t**2/233 + t**3 / 2547
208
-
209
- # 1920 ... 1941
210
- elsif year >= 1920
211
- t = year - 1920
212
- 21.20 + 0.84493*t - 0.076100 * t**2 + 0.0020936 * t**3
213
-
214
- # 1900 ... 1920
215
- elsif year >= 1900
216
- t = year - 1900
217
- -2.79 + 1.494119 * t - 0.0598939 * t**2 + 0.0061966 * t**3 - 0.000197 * t**4
218
-
219
- # 1860 ... 1900
220
- elsif year >= 1860
221
- t = year - 1860
222
- 7.62 + 0.5737 * t - 0.251754 * t**2 + 0.01680668 * t**3 - 0.0004473624 * t**4 + t**5 / 233174
223
-
224
- # 1800 ... 1860
225
- elsif year >= 1800
226
- t = year - 1800
227
- 13.72 - 0.332447 * t + 0.0068612 * t**2 + 0.0041116 * t**3 - 0.00037436 * t**4 + 0.0000121272 * t**5 - 0.0000001699 * t**6 + 0.000000000875 * t**7
228
-
229
- # 1700 ... 1800
230
- elsif year >= 1700
231
- t = year - 1700
232
- 8.83 + 0.1603 * t - 0.0059285 * t**2 + 0.00013336 * t**3 - t**4 / 1174000
233
-
234
- # 1600 ... 1700
235
- elsif year >= 1600
236
- t = year - 1600
237
- 120 - 0.9808 * t - 0.01532 * t**2 + t**3 / 7129
238
-
239
- # 500 ... 1600
240
- elsif year >= 500
241
- u = (year - 1000) / 100
242
- 1574.2 - 556.01 * u + 71.23472 * u**2 + 0.319781 * u**3 - 0.8503463 * u**4 - 0.005050998 * u**5 + 0.0083572073 * u**6
243
-
244
- # -500 ... 500
245
- elsif year >= -500
246
- u = year / 100
247
- 10583.6 - 1014.41 * u + 33.78311 * u**2 - 5.952053 * u**3 - 0.1798452 * u**4 + 0.022174192 * u**5 + 0.0090316521 * u**6
248
-
249
- # ... -500
250
- else
251
- -20 + 32 * u**2
252
- end
253
- end
254
- private :delta_t_observed_poly
255
-
256
- # universal time を dynamical time に変換する
257
- #
258
- # @param [Numeric] time universal time
259
- #
260
- # @return [Numeric] dynamical time
261
- #
262
- def to_dynamical_time(time)
263
- return time unless -Float::MAX/4 < time && time < Float::MAX/4
264
- jd_utc = When::TM::JulianDate._t_to_d(time * 1)
265
- +time + delta_t(jd_utc) * When::TM::Duration::SECOND
266
- end
267
-
268
- # dynamical time を universal time に変換する
269
- #
270
- # @param [Numeric] time dynamical time
271
- #
272
- # @return [Numeric] universal time
273
- #
274
- def from_dynamical_time(time)
275
- return time unless -Float::MAX/4 < time && time < Float::MAX/4
276
- jd_tt = When::TM::JulianDate._t_to_d(time)
277
- utc = time - delta_t(jd_tt) * When::TM::Duration::SECOND
278
- diff = time - to_dynamical_time(utc)
279
- return utc if diff == 0 # 間に閏秒なし
280
- utc += diff
281
- diff = time - to_dynamical_time(utc)
282
- return utc if diff == 0 # 間に閏秒なし
283
- return When::Coordinates::LeapSeconds.new(utc+diff, -diff, When::TM::Duration::SECOND)
284
- end
285
-
286
- # Time オブジェクトを dynamical time に変換する
287
- #
288
- # @param [::Time] time
289
- #
290
- # @return [Numeric] [dynamical time
291
- #
292
- def from_time_object(time)
293
- time = time.to_f * When::TM::Duration::SECOND
294
- _is_systemtime_universal? ? to_dynamical_time(time) : time + DeltaT0
295
- end
296
-
297
- # dynamical time を Time オブジェクトに変換する
298
- #
299
- # @param [Numeric] time dynamical time
300
- #
301
- # @return [::Time]
302
- #
303
- def to_time_object(time)
304
- time = _is_systemtime_universal? ? from_dynamical_time(time) : time - DeltaT0
305
- ::Time.at(+time / When::TM::Duration::SECOND)
306
- end
307
- end
308
-
309
- # @private
310
- YearThreshold = 1997.0 + DeltaT.size
311
-
312
- # @private
313
- DeltaThreshold = DeltaT[-2] - delta_t_observed_poly(YearThreshold)
314
-
315
- #
316
- # When::TM::Calendar のための TimeBasis の初期化
317
- #
318
- # @private
319
- module TimeBasis
320
-
321
- # @private
322
- attr_reader :_time_basis
323
-
324
- module FixedTimeBasis
325
-
326
- private
327
-
328
- # 太陽黄経のための日付境界のオフセットを反映した通日
329
- #
330
- # @param [Numeric] t ユリウス日(Terrestrial Time)
331
- #
332
- # @return [Integer]
333
- #
334
- def solar_sdn(t)
335
- (t + 0.5 + @_time_basis_offset[0]).floor
336
- end
337
-
338
- # 月の位相のための日付境界のオフセットを反映した通日
339
- #
340
- # @param [Numeric] t ユリウス日(Terrestrial Time)
341
- #
342
- # @return [Integer]
343
- #
344
- def lunar_sdn(t)
345
- (t + 0.5 + @_time_basis_offset[-1]).floor
346
- end
347
- end
348
-
349
- module ApparentTimeBasis
350
-
351
- private
352
-
353
- # 太陽黄経のための日付境界のオフセットを反映した通日
354
- #
355
- # @param [Numeric] t ユリウス日(Terrestrial Time)
356
- #
357
- # @return [Integer]
358
- #
359
- def solar_sdn(t)
360
- time_basis.time_standard.from_dynamical_date(t + 0.5).floor
361
- end
362
-
363
- # 月の位相のための日付境界のオフセットを反映した通日
364
- #
365
- # @param [Numeric] t ユリウス日(Terrestrial Time)
366
- #
367
- # @return [Integer]
368
- #
369
- def lunar_sdn(t)
370
- time_basis.time_standard.from_dynamical_date(t + 0.5).floor
371
- end
372
- end
373
-
374
- #
375
- # When::TM::Calendar のための TimeBasis の初期化
376
- #
377
- def _normalize_time_basis
378
-
379
- @_time_basis ||= @time_basis || (@location ? @location.long / When::Coordinates::Spatial::DEGREE * 240 : When::UTC)
380
- @_time_basis = When::Locale._split(@_time_basis) if @_time_basis.kind_of?(String)
381
- @_time_basis = [@_time_basis] unless @_time_basis.kind_of?(Array)
382
- @_time_basis = @_time_basis.map {|clock| When.Clock(clock)}
383
- @_time_basis_offset = @_time_basis.map {|clock| -clock.universal_time / When::TM::Duration::DAY}
384
-
385
- @time_basis = @_time_basis[0] if @time_basis
386
-
387
- if @_time_basis[0].time_standard.kind_of?(LocalApparentTime)
388
- extend ApparentTimeBasis
389
- else
390
- extend FixedTimeBasis
391
- end
392
- end
393
- end
394
-
395
- #
396
- # Local Time と Universal Time の差分
397
- #
398
- # @private
399
- module LocalTime
400
-
401
- # local time と universal time の差 / 日
402
- #
403
- # @return [Numeric] difference / day
404
- #
405
- def localdate_difference
406
- @localdate_difference ||= @location.long / (360.0 * When::Coordinates::Spatial::DEGREE)
407
- end
408
-
409
- # local time と universal time の差 / 128秒
410
- #
411
- # @return [Numeric] difference / day
412
- #
413
- def localtime_difference
414
- @localtime_difference ||= When::TM::Duration::DAY * localdate_difference
415
- end
416
- end
417
-
418
- #
419
- # 時刻系のひながた
420
- #
421
- class TimeStandard < When::BasicTypes::Object
422
-
423
- include When::TimeStandard
424
-
425
- Ratio = 1.0
426
-
427
- # universal time を dynamical time に変換する
428
- #
429
- # @param [Numeric] time universal time
430
- #
431
- # @return [Numeric] dynamical time
432
- #
433
- def to_dynamical_time(time)
434
- When::TimeStandard.to_dynamical_time(time)
435
- end
436
-
437
- # dynamical time を universal time に変換する
438
- #
439
- # @param [Numeric] time dynamical time
440
- #
441
- # @return [Numeric] universal time
442
- #
443
- def from_dynamical_time(time)
444
- When::TimeStandard.from_dynamical_time(time)
445
- end
446
-
447
- # 当該時刻系の日付を dynamical date に変換する
448
- #
449
- # @param [Numeric] date 当該時刻系の日付
450
- #
451
- # @return [Numeric] dynamical date
452
- #
453
- def to_dynamical_date(date)
454
- When::TM::JulianDate._t_to_d(
455
- to_dynamical_time(
456
- When::TM::JulianDate._d_to_t(+date)))
457
- end
458
-
459
- # dynamical date を当該時刻系の日付に変換する
460
- #
461
- # @param [Numeric] date dynamical date
462
- #
463
- # @return [Numeric] 当該時刻系の日付
464
- #
465
- def from_dynamical_date(date)
466
- When::TM::JulianDate._t_to_d(
467
- from_dynamical_time(
468
- When::TM::JulianDate._d_to_t(+date)))
469
- end
470
-
471
- # Time オブジェクトを universal time に変換する
472
- #
473
- # @param [::Time] time
474
- #
475
- # @return [Numeric] universal time
476
- #
477
- def from_time_object(time)
478
- from_dynamical_time(When::TimeStandard.from_time_object(time))
479
- end
480
-
481
- # universal time を Time オブジェクトに変換する
482
- #
483
- # @param [Numeric] time universal time
484
- #
485
- # @return [::Time]
486
- #
487
- def to_time_object(time)
488
- When::TimeStandard.to_time_object(to_dynamical_time(time))
489
- end
490
-
491
- # 当該時刻系に閏秒があるか?
492
- #
493
- # @return [Boolean] - false 閏秒なし
494
- #
495
- def has_leap?
496
- false
497
- end
498
-
499
- # 時間の歩度
500
- #
501
- # @return [Numeric]
502
- #
503
- def rate_of_clock
504
- self.class::Ratio
505
- end
506
-
507
- private
508
-
509
- def _normalize(args=[], options={})
510
- end
511
- end
512
-
513
- #
514
- # 協定世界時
515
- #
516
- class UniversalTime < TimeStandard
517
-
518
- # Time オブジェクトを universal time に変換する
519
- #
520
- # @param [::Time] time
521
- #
522
- # @return [Numeric] universal time
523
- #
524
- def from_time_object(time)
525
- result = time.to_f * When::TM::Duration::SECOND
526
- return result if When::TimeStandard._is_systemtime_universal?
527
- from_dynamical_time(result + DeltaT0)
528
- end
529
-
530
- # universal time を Time オブジェクトに変換する
531
- #
532
- # @param [Numeric] time universal time
533
- #
534
- # @return [::Time]
535
- #
536
- def to_time_object(time)
537
- time = to_dynamical_time(time) - DeltaT0 unless When::TimeStandard._is_systemtime_universal?
538
- ::Time.at(+time / When::TM::Duration::SECOND)
539
- end
540
-
541
- # 当該時刻系に閏秒があるか?
542
- #
543
- # @return [Boolean] - true 閏秒あり
544
- #
545
- def has_leap?
546
- true
547
- end
548
- end
549
-
550
- #
551
- # 地方平均太陽時
552
- #
553
- class LocalMeanTime < TimeStandard
554
-
555
- include LocalTime
556
-
557
- # local mean time を dynamical time に変換する
558
- #
559
- # @param [Numeric] time local mean time
560
- #
561
- # @return [Numeric] dynamical time
562
- #
563
- def to_dynamical_time(time)
564
- super(time - localtime_difference)
565
- end
566
-
567
- # dynamical time を local mean time に変換する
568
- #
569
- # @param [Numeric] time dynamical time
570
- #
571
- # @return [Numeric] local mean time
572
- #
573
- def from_dynamical_time(time)
574
- super(time) + localtime_difference
575
- end
576
-
577
- private
578
-
579
- # オブジェクトの正規化
580
- def _normalize(args=[], options={})
581
- @location = When.Resource(@location || '_l:long=0&lat=0')
582
- super
583
- end
584
- end
585
-
586
- #
587
- # 地方真太陽時
588
- #
589
- class LocalApparentTime < TimeStandard
590
-
591
- include LocalTime
592
-
593
- # local apparent time を dynamical time に変換する
594
- #
595
- # @param [Numeric] time local apparent time
596
- #
597
- # @return [Numeric] dynamical time
598
- #
599
- def to_dynamical_time(time)
600
- date = When::TM::JulianDate._t_to_d(time) - localdate_difference
601
- diff = 0
602
- 2.times do
603
- diff = @datum.equation_of_time(date-diff)
604
- end
605
- super(When::TM::JulianDate._d_to_t(date-diff))
606
- end
607
-
608
- # dynamical time を local apparent time に変換する
609
- #
610
- # @param [Numeric] time dynamical time
611
- #
612
- # @return [Numeric] local apparent time
613
- #
614
- def from_dynamical_time(time)
615
- super(time) + When::TM::Duration::DAY * (localdate_difference + @datum.equation_of_time(When::TM::JulianDate._t_to_d(time)))
616
- end
617
-
618
- private
619
-
620
- # オブジェクトの正規化
621
- def _normalize(args=[], options={})
622
- @location ||= '_l:long=0&lat=0'
623
- @location = When.Resource(@location) if @location.kind_of?(String)
624
- @datum = When.Resource(@datum || '_ep:Earth' )
625
- super
626
- end
627
- end
628
-
629
- #
630
- # 不定時法
631
- #
632
- class TemporalHourSystem < LocalApparentTime
633
-
634
- # @private
635
- alias :_to_dynamical_time :to_dynamical_time
636
- # @private
637
- alias :_from_dynamical_time :from_dynamical_time
638
-
639
- # temporal hour system を dynamical time に変換する
640
- #
641
- # @param [Numeric] time temporal hour system
642
- #
643
- # @return [Numeric] dynamical time
644
- #
645
- def to_dynamical_time(time)
646
- noon, frac = When::TM::JulianDate._t_to_d(time).divmod(1)
647
-
648
- r, *p =
649
- case (frac * 4).floor
650
- when 3 ; [-1.5, [noon+1, -1],[noon+1, +1]] # morning
651
- when 0 ; [+0.5, [noon, -1],[noon, +1]] # afternoon
652
- else ; [-0.5, [noon, +1],[noon+1, -1]] # night
653
- end
654
-
655
- s, e = p.map {|v|
656
- When::TM::JulianDate._d_to_t(@formula.day_event(_to_dynamical_date(v[0]), v[1], When.Resource('_ep:Sun'), @height))
657
- }
658
-
659
- s + (e - s) * (frac * 2 + r)
660
- end
661
-
662
- # dynamical time を temporal hour system に変換する
663
- #
664
- # @param [Numeric] time dynamical time
665
- #
666
- # @return [Numeric] temporal hour system
667
- #
668
- def from_dynamical_time(time)
669
- date = When::TM::JulianDate._t_to_d(time)
670
-
671
- d, t = [-1, +1].map {|v| @formula.day_event(date, v, When.Resource('_ep:Sun'), @height)}
672
-
673
- if date < d # after midnight
674
- t = @formula.sunset(date-1, @height)
675
- f = (date - t) / (d - t) / 2 - 0.25
676
-
677
- elsif date > t # before midnight
678
- d = @formula.sunrise(date+1, @height)
679
- f = (date - t) / (d - t) / 2 - 0.25
680
-
681
- else # day time
682
- f = (date - d) / (t - d) / 2 + 0.25
683
- end
684
-
685
- When::TM::JulianDate._d_to_t(_from_dynamical_date(d).floor + 0.5 + f)
686
- end
687
-
688
- private
689
-
690
- # オブジェクトの正規化
691
- def _normalize(args=[], options={})
692
- @formula = When::Ephemeris::Formula.new({:location=>@location})
693
- @height ||= 'T'
694
- super
695
- end
696
-
697
- # 単位を「日」にした to_dynamical_time
698
- def _to_dynamical_date(date)
699
- When::TM::JulianDate._t_to_d(_to_dynamical_time(When::TM::JulianDate._d_to_t(date)))
700
- end
701
-
702
- # 単位を「日」にした from_dynamical_time
703
- def _from_dynamical_date(date)
704
- When::TM::JulianDate._t_to_d(_from_dynamical_time(When::TM::JulianDate._d_to_t(date)))
705
- end
706
- end
707
- end
1
+ # -*- coding: utf-8 -*-
2
+ =begin
3
+ Copyright (C) 2011-2015 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
+ #
9
+ # 標準的な時刻系の定義
10
+ #
11
+ module When::TimeStandard
12
+
13
+ # TT(Terrestrial Time) - UTC(Universal Time, Coordinated) at 1970-01-01T00:00:00Z
14
+ DeltaT0 = (40 + 377.0/2048) * When::TM::Duration::SECOND
15
+
16
+ TAI_UTC = # http://maia.usno.navy.mil/ser7/tai-utc.dat
17
+ [[2437300.5, 1.422818, 37300.0, 0.001296 ],
18
+ [2437512.5, 1.372818, 37300.0, 0.001296 ],
19
+ [2437665.5, 1.845858, 37665.0, 0.0011232],
20
+ [2438334.5, 1.945858, 37665.0, 0.0011232],
21
+ [2438395.5, 3.24013, 38761.0, 0.001296 ],
22
+ [2438486.5, 3.34013, 38761.0, 0.001296 ],
23
+ [2438639.5, 3.44013, 38761.0, 0.001296 ],
24
+ [2438761.5, 3.54013, 38761.0, 0.001296 ],
25
+ [2438820.5, 3.64013, 38761.0, 0.001296 ],
26
+ [2438942.5, 3.74013, 38761.0, 0.001296 ],
27
+ [2439004.5, 3.84013, 38761.0, 0.001296 ],
28
+ [2439126.5, 4.31317, 39126.0, 0.002592 ],
29
+ [2439887.5, 4.21317, 39126.0, 0.002592 ],
30
+ [2441317.5, 10.0],
31
+ [2441499.5, 11.0],
32
+ [2441683.5, 12.0],
33
+ [2442048.5, 13.0],
34
+ [2442413.5, 14.0],
35
+ [2442778.5, 15.0],
36
+ [2443144.5, 16.0],
37
+ [2443509.5, 17.0],
38
+ [2443874.5, 18.0],
39
+ [2444239.5, 19.0],
40
+ [2444786.5, 20.0],
41
+ [2445151.5, 21.0],
42
+ [2445516.5, 22.0],
43
+ [2446247.5, 23.0],
44
+ [2447161.5, 24.0],
45
+ [2447892.5, 25.0],
46
+ [2448257.5, 26.0],
47
+ [2448804.5, 27.0],
48
+ [2449169.5, 28.0],
49
+ [2449534.5, 29.0],
50
+ [2450083.5, 30.0],
51
+ [2450630.5, 31.0],
52
+ [2451179.5, 32.0],
53
+ [2453736.5, 33.0],
54
+ [2454832.5, 34.0],
55
+ [2456109.5, 35.0],
56
+ [2457204.5, 36.0]]
57
+
58
+ DeltaT = [ 63.467, # 1999
59
+ 63.827, 64.092, 64.300, 64.473, 64.573, 64.689, 64.846, 65.145, 65.456, 65.779, # 2000-
60
+ 66.070, 66.324, 66.603, 66.909, 67.282 # 2010-
61
+ ]
62
+
63
+ class << self
64
+ # When::TimeStandard Module のグローバルな設定を行う
65
+ #
66
+ # @param [String] leap_seconds http://maia.usno.navy.mil/ser7/tai-utc.dat 形式のファイルのファイルパス
67
+ # @param [Array<Array<Numeric>>] leap_seconds 閏秒の挿入記録 [ [ JD, TAI-UTC, (MJD, OFFSET) ] ]
68
+ # [ JD - 閏秒を挿入した日時のユリウス日 ]
69
+ # [ TAI-UTC - 閏秒を挿入後の TAI と UTC の差 ]
70
+ # [ MJD - 周波数オフセットの基準となる日時の修正ユリウス日 ]
71
+ # [ OFFSET - 周波数オフセット値 ]
72
+ #
73
+ # @return [void]
74
+ #
75
+ # @note
76
+ # 本メソッドでマルチスレッド対応の管理変数の初期化を行っている。
77
+ # このため、本メソッド自体はスレッドセーフでない。
78
+ #
79
+ def _setup_(leap_seconds=nil)
80
+ @_lock_ = Mutex.new if When.multi_thread
81
+ leap_seconds ||= TAI_UTC
82
+ @leap_seconds =
83
+ if leap_seconds.kind_of?(String)
84
+ OpenURI
85
+ open(leap_seconds) do |file|
86
+ file.read.split(/[\n\r]+/).map { |line|
87
+ line.split(/[^\d.]+/)[3..6].map {|d| d.to_f}
88
+ }.reverse
89
+ end
90
+ else
91
+ leap_seconds.reverse
92
+ end
93
+ end
94
+
95
+ # 設定情報を取得する
96
+ #
97
+ # @return [Hash] 設定情報
98
+ #
99
+ def _setup_info
100
+ {:leap_seconds => _leap_seconds}
101
+ end
102
+
103
+ # @private
104
+ # 閏秒の挿入記録を取得する
105
+ def _leap_seconds
106
+ @leap_seconds ||= TAI_UTC.reverse
107
+ end
108
+
109
+ # 処理系が閏秒を無視しているか否か
110
+ # @private
111
+ def _is_systemtime_universal?
112
+ @is_systemtime_universal = ((Time.utc(1976).to_i - Time.utc(1975).to_i) % 86400 == 0) if @is_systemtime_universal == nil
113
+ @is_systemtime_universal
114
+ end
115
+
116
+ # ΔT
117
+ #
118
+ # @param [Numeric] jd_utc ユリウス日(Universal Time, Coordinated)
119
+ #
120
+ # @return [Numeric] (dynamical_time - universal_time) / second
121
+ # 1/2048 second(≒0.5ms)未満を四捨五入
122
+ #
123
+ def delta_t(jd_utc)
124
+ (delta_t_coordinated(jd_utc) * 4096 + 1).floor / 4096.0
125
+ end
126
+ alias :deltaT :delta_t
127
+
128
+ # ΔT - 閏秒による(TT-UTC)
129
+ #
130
+ # @param [Numeric] jd_utc ユリウス日(Universal Time, Coordinated)
131
+ #
132
+ # @return [Numeric] (Terrestrial Time - Universal Time, Coordinated) / second
133
+ #
134
+ def delta_t_coordinated(jd_utc)
135
+ list = _leap_seconds
136
+ list.each do |v|
137
+ if jd_utc >= v[0]
138
+ result = 32.184 + v[1]
139
+ result += (jd_utc - (2400000.5 + v[2])) * v[3] unless (v[3]||0) == 0
140
+ return result
141
+ end
142
+ end
143
+ delta_t_observed(jd_utc)
144
+ end
145
+
146
+ # ΔT - 観測による(TT-UT1) mix of Table and NASA
147
+ #
148
+ # @param [Numeric] jd_utc ユリウス日(Universal Time, Coordinated)
149
+ #
150
+ # @return [Numeric] (Terrestrial Time - Universal Time 1) / second
151
+ #
152
+ def delta_t_observed(jd_utc)
153
+ year = (jd_utc - When::Ephemeris::EPOCH2000)/When::Ephemeris::JYEAR + 2000 # 0年からの経過世紀
154
+ return delta_t_observed_poly(year) unless 2000 <= year && year < 2050
155
+ return delta_t_observed_poly(year) + DeltaThreshold * (year - 2050.0) / (YearThreshold - 2050.0) if year >= YearThreshold
156
+
157
+ i = (year-1999.0).floor # 1999年からの経過年(整数)
158
+ n = year % 1
159
+ d0 = DeltaT[i+0] - DeltaT[i-1]
160
+ d1 = DeltaT[i+1] - DeltaT[i+0]
161
+ d2 = DeltaT[i+2] - DeltaT[i+1]
162
+ d10 = d1 - d0
163
+ d21 = d2 - d1
164
+ d210 = d21 - d10
165
+ DeltaT[i] + n*d1 + n*(n-1.0)/4.0*(d10+d21) + n*(n-1.0)*(n-0.5)/6.0*d210
166
+ end
167
+
168
+ # ΔT - 観測による(TT-UT1) from http://eclipse.gsfc.nasa.gov/SEhelp/deltatpoly2004.html
169
+ #
170
+ # @param [Numeric] jd_utc ユリウス日(Universal Time, Coordinated)
171
+ #
172
+ # @return [Numeric] (Terrestrial Time - Universal Time 1) / second
173
+ #
174
+ def delta_t_observed_nasa(jd_utc)
175
+ delta_t_observed_poly((jd_utc - When::Ephemeris::EPOCH2000)/When::Ephemeris::JYEAR + 2000.0) # 0年からの経過年
176
+ end
177
+
178
+ # 多項式による近似
179
+ def delta_t_observed_poly(year)
180
+ u = (year-1820)/100
181
+
182
+ # 2150 ... 3000
183
+ if year >= 2150
184
+ -20 + 32 * u**2
185
+
186
+ # 2050 ... 2150
187
+ elsif year >= 2050
188
+ -20 + 32 * u**2 - 0.5628 * (2150 - year)
189
+
190
+ # 2005 ... 2050
191
+ elsif year >= 2005
192
+ t = year - 2000
193
+ 62.92 + 0.32217 * t + 0.005589 * t**2
194
+
195
+ # 1986 ... 2005
196
+ elsif year >= 1986
197
+ t = year - 2000
198
+ 63.86 + 0.3345 * t - 0.060374 * t**2 + 0.0017275 * t**3 + 0.000651814 * t**4 + 0.00002373599 * t**5
199
+
200
+ # 1961 ... 1986
201
+ elsif year >= 1961
202
+ t = year - 1975
203
+ 45.45 + 1.067*t - t**2/260 - t**3 / 718
204
+
205
+ # 1941 ... 1961
206
+ elsif year >= 1941
207
+ t = year - 1950
208
+ 29.07 + 0.407*t - t**2/233 + t**3 / 2547
209
+
210
+ # 1920 ... 1941
211
+ elsif year >= 1920
212
+ t = year - 1920
213
+ 21.20 + 0.84493*t - 0.076100 * t**2 + 0.0020936 * t**3
214
+
215
+ # 1900 ... 1920
216
+ elsif year >= 1900
217
+ t = year - 1900
218
+ -2.79 + 1.494119 * t - 0.0598939 * t**2 + 0.0061966 * t**3 - 0.000197 * t**4
219
+
220
+ # 1860 ... 1900
221
+ elsif year >= 1860
222
+ t = year - 1860
223
+ 7.62 + 0.5737 * t - 0.251754 * t**2 + 0.01680668 * t**3 - 0.0004473624 * t**4 + t**5 / 233174
224
+
225
+ # 1800 ... 1860
226
+ elsif year >= 1800
227
+ t = year - 1800
228
+ 13.72 - 0.332447 * t + 0.0068612 * t**2 + 0.0041116 * t**3 - 0.00037436 * t**4 + 0.0000121272 * t**5 - 0.0000001699 * t**6 + 0.000000000875 * t**7
229
+
230
+ # 1700 ... 1800
231
+ elsif year >= 1700
232
+ t = year - 1700
233
+ 8.83 + 0.1603 * t - 0.0059285 * t**2 + 0.00013336 * t**3 - t**4 / 1174000
234
+
235
+ # 1600 ... 1700
236
+ elsif year >= 1600
237
+ t = year - 1600
238
+ 120 - 0.9808 * t - 0.01532 * t**2 + t**3 / 7129
239
+
240
+ # 500 ... 1600
241
+ elsif year >= 500
242
+ u = (year - 1000) / 100
243
+ 1574.2 - 556.01 * u + 71.23472 * u**2 + 0.319781 * u**3 - 0.8503463 * u**4 - 0.005050998 * u**5 + 0.0083572073 * u**6
244
+
245
+ # -500 ... 500
246
+ elsif year >= -500
247
+ u = year / 100
248
+ 10583.6 - 1014.41 * u + 33.78311 * u**2 - 5.952053 * u**3 - 0.1798452 * u**4 + 0.022174192 * u**5 + 0.0090316521 * u**6
249
+
250
+ # ... -500
251
+ else
252
+ -20 + 32 * u**2
253
+ end
254
+ end
255
+ private :delta_t_observed_poly
256
+
257
+ # universal time を dynamical time に変換する
258
+ #
259
+ # @param [Numeric] time universal time
260
+ #
261
+ # @return [Numeric] dynamical time
262
+ #
263
+ def to_dynamical_time(time)
264
+ return time unless -Float::MAX/4 < time && time < Float::MAX/4
265
+ jd_utc = When::TM::JulianDate._t_to_d(time * 1)
266
+ +time + delta_t(jd_utc) * When::TM::Duration::SECOND
267
+ end
268
+
269
+ # dynamical time を universal time に変換する
270
+ #
271
+ # @param [Numeric] time dynamical time
272
+ #
273
+ # @return [Numeric] universal time
274
+ #
275
+ def from_dynamical_time(time)
276
+ return time unless -Float::MAX/4 < time && time < Float::MAX/4
277
+ jd_tt = When::TM::JulianDate._t_to_d(time)
278
+ utc = time - delta_t(jd_tt) * When::TM::Duration::SECOND
279
+ diff = time - to_dynamical_time(utc)
280
+ return utc if diff == 0 # 間に閏秒なし
281
+ utc += diff
282
+ diff = time - to_dynamical_time(utc)
283
+ return utc if diff == 0 # 間に閏秒なし
284
+ return When::Coordinates::LeapSeconds.new(utc+diff, -diff, When::TM::Duration::SECOND)
285
+ end
286
+
287
+ # Time オブジェクトを dynamical time に変換する
288
+ #
289
+ # @param [::Time] time
290
+ #
291
+ # @return [Numeric] [dynamical time
292
+ #
293
+ def from_time_object(time)
294
+ time = time.to_f * When::TM::Duration::SECOND
295
+ _is_systemtime_universal? ? to_dynamical_time(time) : time + DeltaT0
296
+ end
297
+
298
+ # dynamical time を Time オブジェクトに変換する
299
+ #
300
+ # @param [Numeric] time dynamical time
301
+ #
302
+ # @return [::Time]
303
+ #
304
+ def to_time_object(time)
305
+ time = _is_systemtime_universal? ? from_dynamical_time(time) : time - DeltaT0
306
+ ::Time.at(+time / When::TM::Duration::SECOND)
307
+ end
308
+ end
309
+
310
+ # @private
311
+ YearThreshold = 1997.0 + DeltaT.size
312
+
313
+ # @private
314
+ DeltaThreshold = DeltaT[-2] - delta_t_observed_poly(YearThreshold)
315
+
316
+ #
317
+ # When::TM::Calendar のための TimeBasis の初期化
318
+ #
319
+ # @private
320
+ module TimeBasis
321
+
322
+ # @private
323
+ attr_reader :_time_basis
324
+
325
+ module FixedTimeBasis
326
+
327
+ private
328
+
329
+ # 太陽黄経のための日付境界のオフセットを反映した通日
330
+ #
331
+ # @param [Numeric] t ユリウス日(Terrestrial Time)
332
+ #
333
+ # @return [Integer]
334
+ #
335
+ def solar_sdn(t)
336
+ (t + 0.5 + @_time_basis_offset[0]).floor
337
+ end
338
+
339
+ # 月の位相のための日付境界のオフセットを反映した通日
340
+ #
341
+ # @param [Numeric] t ユリウス日(Terrestrial Time)
342
+ #
343
+ # @return [Integer]
344
+ #
345
+ def lunar_sdn(t)
346
+ (t + 0.5 + @_time_basis_offset[-1]).floor
347
+ end
348
+ end
349
+
350
+ module ApparentTimeBasis
351
+
352
+ private
353
+
354
+ # 太陽黄経のための日付境界のオフセットを反映した通日
355
+ #
356
+ # @param [Numeric] t ユリウス日(Terrestrial Time)
357
+ #
358
+ # @return [Integer]
359
+ #
360
+ def solar_sdn(t)
361
+ time_basis.time_standard.from_dynamical_date(t + 0.5).floor
362
+ end
363
+
364
+ # 月の位相のための日付境界のオフセットを反映した通日
365
+ #
366
+ # @param [Numeric] t ユリウス日(Terrestrial Time)
367
+ #
368
+ # @return [Integer]
369
+ #
370
+ def lunar_sdn(t)
371
+ time_basis.time_standard.from_dynamical_date(t + 0.5).floor
372
+ end
373
+ end
374
+
375
+ #
376
+ # When::TM::Calendar のための TimeBasis の初期化
377
+ #
378
+ def _normalize_time_basis
379
+
380
+ @_time_basis ||= @time_basis || (@location ? @location.long / When::Coordinates::Spatial::DEGREE * 240 : When::UTC)
381
+ @_time_basis = When::Locale._split(@_time_basis) if @_time_basis.kind_of?(String)
382
+ @_time_basis = [@_time_basis] unless @_time_basis.kind_of?(Array)
383
+ @_time_basis = @_time_basis.map {|clock| When.Clock(clock)}
384
+ @_time_basis_offset = @_time_basis.map {|clock| -clock.universal_time / When::TM::Duration::DAY}
385
+
386
+ @time_basis = @_time_basis[0] if @time_basis
387
+
388
+ if @_time_basis[0].time_standard.kind_of?(LocalApparentTime)
389
+ extend ApparentTimeBasis
390
+ else
391
+ extend FixedTimeBasis
392
+ end
393
+ end
394
+ end
395
+
396
+ #
397
+ # Local Time と Universal Time の差分
398
+ #
399
+ # @private
400
+ module LocalTime
401
+
402
+ # local time と universal time の差 / 日
403
+ #
404
+ # @return [Numeric] difference / day
405
+ #
406
+ def localdate_difference
407
+ @localdate_difference ||= @location.long / (360.0 * When::Coordinates::Spatial::DEGREE)
408
+ end
409
+
410
+ # local time と universal time の差 / 128秒
411
+ #
412
+ # @return [Numeric] difference / day
413
+ #
414
+ def localtime_difference
415
+ @localtime_difference ||= When::TM::Duration::DAY * localdate_difference
416
+ end
417
+ end
418
+
419
+ #
420
+ # 時刻系のひながた
421
+ #
422
+ class TimeStandard < When::BasicTypes::Object
423
+
424
+ include When::TimeStandard
425
+
426
+ Ratio = 1.0
427
+
428
+ # universal time を dynamical time に変換する
429
+ #
430
+ # @param [Numeric] time universal time
431
+ #
432
+ # @return [Numeric] dynamical time
433
+ #
434
+ def to_dynamical_time(time)
435
+ When::TimeStandard.to_dynamical_time(time)
436
+ end
437
+
438
+ # dynamical time を universal time に変換する
439
+ #
440
+ # @param [Numeric] time dynamical time
441
+ #
442
+ # @return [Numeric] universal time
443
+ #
444
+ def from_dynamical_time(time)
445
+ When::TimeStandard.from_dynamical_time(time)
446
+ end
447
+
448
+ # 当該時刻系の日付を dynamical date に変換する
449
+ #
450
+ # @param [Numeric] date 当該時刻系の日付
451
+ #
452
+ # @return [Numeric] dynamical date
453
+ #
454
+ def to_dynamical_date(date)
455
+ When::TM::JulianDate._t_to_d(
456
+ to_dynamical_time(
457
+ When::TM::JulianDate._d_to_t(+date)))
458
+ end
459
+
460
+ # dynamical date を当該時刻系の日付に変換する
461
+ #
462
+ # @param [Numeric] date dynamical date
463
+ #
464
+ # @return [Numeric] 当該時刻系の日付
465
+ #
466
+ def from_dynamical_date(date)
467
+ When::TM::JulianDate._t_to_d(
468
+ from_dynamical_time(
469
+ When::TM::JulianDate._d_to_t(+date)))
470
+ end
471
+
472
+ # Time オブジェクトを universal time に変換する
473
+ #
474
+ # @param [::Time] time
475
+ #
476
+ # @return [Numeric] universal time
477
+ #
478
+ def from_time_object(time)
479
+ from_dynamical_time(When::TimeStandard.from_time_object(time))
480
+ end
481
+
482
+ # universal time を Time オブジェクトに変換する
483
+ #
484
+ # @param [Numeric] time universal time
485
+ #
486
+ # @return [::Time]
487
+ #
488
+ def to_time_object(time)
489
+ When::TimeStandard.to_time_object(to_dynamical_time(time))
490
+ end
491
+
492
+ # 当該時刻系に閏秒があるか?
493
+ #
494
+ # @return [Boolean] - false 閏秒なし
495
+ #
496
+ def has_leap?
497
+ false
498
+ end
499
+
500
+ # 時間の歩度
501
+ #
502
+ # @return [Numeric]
503
+ #
504
+ def rate_of_clock
505
+ self.class::Ratio
506
+ end
507
+
508
+ private
509
+
510
+ def _normalize(args=[], options={})
511
+ end
512
+ end
513
+
514
+ #
515
+ # 協定世界時
516
+ #
517
+ class UniversalTime < TimeStandard
518
+
519
+ # Time オブジェクトを universal time に変換する
520
+ #
521
+ # @param [::Time] time
522
+ #
523
+ # @return [Numeric] universal time
524
+ #
525
+ def from_time_object(time)
526
+ result = time.to_f * When::TM::Duration::SECOND
527
+ return result if When::TimeStandard._is_systemtime_universal?
528
+ from_dynamical_time(result + DeltaT0)
529
+ end
530
+
531
+ # universal time を Time オブジェクトに変換する
532
+ #
533
+ # @param [Numeric] time universal time
534
+ #
535
+ # @return [::Time]
536
+ #
537
+ def to_time_object(time)
538
+ time = to_dynamical_time(time) - DeltaT0 unless When::TimeStandard._is_systemtime_universal?
539
+ ::Time.at(+time / When::TM::Duration::SECOND)
540
+ end
541
+
542
+ # 当該時刻系に閏秒があるか?
543
+ #
544
+ # @return [Boolean] - true 閏秒あり
545
+ #
546
+ def has_leap?
547
+ true
548
+ end
549
+ end
550
+
551
+ #
552
+ # 地方平均太陽時
553
+ #
554
+ class LocalMeanTime < TimeStandard
555
+
556
+ include LocalTime
557
+
558
+ # local mean time を dynamical time に変換する
559
+ #
560
+ # @param [Numeric] time local mean time
561
+ #
562
+ # @return [Numeric] dynamical time
563
+ #
564
+ def to_dynamical_time(time)
565
+ super(time - localtime_difference)
566
+ end
567
+
568
+ # dynamical time を local mean time に変換する
569
+ #
570
+ # @param [Numeric] time dynamical time
571
+ #
572
+ # @return [Numeric] local mean time
573
+ #
574
+ def from_dynamical_time(time)
575
+ super(time) + localtime_difference
576
+ end
577
+
578
+ private
579
+
580
+ # オブジェクトの正規化
581
+ def _normalize(args=[], options={})
582
+ @location = When.Resource(@location || '_l:long=0&lat=0')
583
+ super
584
+ end
585
+ end
586
+
587
+ #
588
+ # 地方真太陽時
589
+ #
590
+ class LocalApparentTime < TimeStandard
591
+
592
+ include LocalTime
593
+
594
+ # local apparent time を dynamical time に変換する
595
+ #
596
+ # @param [Numeric] time local apparent time
597
+ #
598
+ # @return [Numeric] dynamical time
599
+ #
600
+ def to_dynamical_time(time)
601
+ date = When::TM::JulianDate._t_to_d(time) - localdate_difference
602
+ diff = 0
603
+ 2.times do
604
+ diff = @datum.equation_of_time(date-diff)
605
+ end
606
+ super(When::TM::JulianDate._d_to_t(date-diff))
607
+ end
608
+
609
+ # dynamical time を local apparent time に変換する
610
+ #
611
+ # @param [Numeric] time dynamical time
612
+ #
613
+ # @return [Numeric] local apparent time
614
+ #
615
+ def from_dynamical_time(time)
616
+ super(time) + When::TM::Duration::DAY * (localdate_difference + @datum.equation_of_time(When::TM::JulianDate._t_to_d(time)))
617
+ end
618
+
619
+ private
620
+
621
+ # オブジェクトの正規化
622
+ def _normalize(args=[], options={})
623
+ @location ||= '_l:long=0&lat=0'
624
+ @location = When.Resource(@location) if @location.kind_of?(String)
625
+ @datum = When.Resource(@datum || '_ep:Earth' )
626
+ super
627
+ end
628
+ end
629
+
630
+ #
631
+ # 不定時法
632
+ #
633
+ class TemporalHourSystem < LocalApparentTime
634
+
635
+ # @private
636
+ alias :_to_dynamical_time :to_dynamical_time
637
+ # @private
638
+ alias :_from_dynamical_time :from_dynamical_time
639
+
640
+ # temporal hour system を dynamical time に変換する
641
+ #
642
+ # @param [Numeric] time temporal hour system
643
+ #
644
+ # @return [Numeric] dynamical time
645
+ #
646
+ def to_dynamical_time(time)
647
+ noon, frac = When::TM::JulianDate._t_to_d(time).divmod(1)
648
+
649
+ r, *p =
650
+ case (frac * 4).floor
651
+ when 3 ; [-1.5, [noon+1, -1],[noon+1, +1]] # morning
652
+ when 0 ; [+0.5, [noon, -1],[noon, +1]] # afternoon
653
+ else ; [-0.5, [noon, +1],[noon+1, -1]] # night
654
+ end
655
+
656
+ s, e = p.map {|v|
657
+ When::TM::JulianDate._d_to_t(@formula.day_event(_to_dynamical_date(v[0]), v[1], When.Resource('_ep:Sun'), @height))
658
+ }
659
+
660
+ s + (e - s) * (frac * 2 + r)
661
+ end
662
+
663
+ # dynamical time を temporal hour system に変換する
664
+ #
665
+ # @param [Numeric] time dynamical time
666
+ #
667
+ # @return [Numeric] temporal hour system
668
+ #
669
+ def from_dynamical_time(time)
670
+ date = When::TM::JulianDate._t_to_d(time)
671
+
672
+ d, t = [-1, +1].map {|v| @formula.day_event(date, v, When.Resource('_ep:Sun'), @height)}
673
+
674
+ if date < d # after midnight
675
+ t = @formula.sunset(date-1, @height)
676
+ f = (date - t) / (d - t) / 2 - 0.25
677
+
678
+ elsif date > t # before midnight
679
+ d = @formula.sunrise(date+1, @height)
680
+ f = (date - t) / (d - t) / 2 - 0.25
681
+
682
+ else # day time
683
+ f = (date - d) / (t - d) / 2 + 0.25
684
+ end
685
+
686
+ When::TM::JulianDate._d_to_t(_from_dynamical_date(d).floor + 0.5 + f)
687
+ end
688
+
689
+ private
690
+
691
+ # オブジェクトの正規化
692
+ def _normalize(args=[], options={})
693
+ @formula = When::Ephemeris::Formula.new({:location=>@location})
694
+ @height ||= 'T'
695
+ super
696
+ end
697
+
698
+ # 単位を「日」にした to_dynamical_time
699
+ def _to_dynamical_date(date)
700
+ When::TM::JulianDate._t_to_d(_to_dynamical_time(When::TM::JulianDate._d_to_t(date)))
701
+ end
702
+
703
+ # 単位を「日」にした from_dynamical_time
704
+ def _from_dynamical_date(date)
705
+ When::TM::JulianDate._t_to_d(_from_dynamical_time(When::TM::JulianDate._d_to_t(date)))
706
+ end
707
+ end
708
+ end