when_exe 0.3.1 → 0.3.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 (53) hide show
  1. data/lib/when_exe.rb +98 -64
  2. data/lib/when_exe/basictypes.rb +2 -2
  3. data/lib/when_exe/calendartypes.rb +5 -2
  4. data/lib/when_exe/coordinates.rb +11 -1
  5. data/lib/when_exe/core/duration.rb +38 -0
  6. data/lib/when_exe/core/extension.rb +17 -4
  7. data/lib/when_exe/ephemeris.rb +49 -17
  8. data/lib/when_exe/icalendar.rb +19 -17
  9. data/lib/when_exe/inspect.rb +16 -4
  10. data/lib/when_exe/mini_application.rb +42 -4
  11. data/lib/when_exe/parts/locale.rb +30 -13
  12. data/lib/when_exe/parts/resource.rb +59 -36
  13. data/lib/when_exe/parts/timezone.rb +19 -13
  14. data/lib/when_exe/region/bahai.rb +5 -4
  15. data/lib/when_exe/region/balinese.rb +2 -2
  16. data/lib/when_exe/region/chinese.rb +11 -11
  17. data/lib/when_exe/region/chinese_calendar.rb +37 -79
  18. data/lib/when_exe/region/chinese_epoch.rb +832 -831
  19. data/lib/when_exe/region/christian.rb +6 -6
  20. data/lib/when_exe/region/far_east.rb +104 -104
  21. data/lib/when_exe/region/french.rb +4 -4
  22. data/lib/when_exe/region/geologicalage.rb +9 -8
  23. data/lib/when_exe/region/indian.rb +10 -10
  24. data/lib/when_exe/region/iranian.rb +3 -3
  25. data/lib/when_exe/region/islamic.rb +3 -3
  26. data/lib/when_exe/region/japanese.rb +376 -376
  27. data/lib/when_exe/region/japanese_notes.rb +60 -60
  28. data/lib/when_exe/region/javanese.rb +4 -4
  29. data/lib/when_exe/region/jewish.rb +2 -2
  30. data/lib/when_exe/region/korean.rb +204 -204
  31. data/lib/when_exe/region/m17n.rb +1 -1
  32. data/lib/when_exe/region/martian.rb +2 -2
  33. data/lib/when_exe/region/mayan.rb +1 -1
  34. data/lib/when_exe/region/nihon_shoki.rb +43 -43
  35. data/lib/when_exe/region/pope.rb +271 -271
  36. data/lib/when_exe/region/roman.rb +13 -12
  37. data/lib/when_exe/region/ryukyu.rb +47 -47
  38. data/lib/when_exe/region/shire.rb +4 -4
  39. data/lib/when_exe/region/thai.rb +2 -2
  40. data/lib/when_exe/region/tibetan.rb +3 -3
  41. data/lib/when_exe/region/vietnamese.rb +122 -122
  42. data/lib/when_exe/region/world.rb +2 -2
  43. data/lib/when_exe/timestandard.rb +112 -67
  44. data/lib/when_exe/tmobjects.rb +4 -0
  45. data/lib/when_exe/tmposition.rb +63 -10
  46. data/lib/when_exe/tmreference.rb +34 -13
  47. data/lib/when_exe/version.rb +1 -1
  48. data/test/test/icalendar.rb +29 -29
  49. data/test/test/region/m17n.rb +4 -4
  50. data/test/test/tmobjects.rb +9 -0
  51. data/test/test/tmposition.rb +3 -3
  52. data/when_exe.gemspec +1 -1
  53. metadata +4 -2
data/lib/when_exe.rb CHANGED
@@ -49,6 +49,7 @@ module When
49
49
  # @option options [When::TM::Clock, When::V::Timezone, When::Parts::Timezone] :local デフォルトの地方時
50
50
  # @option options [When::TM::IntervalLength] :until V::Event::Enumerator の until
51
51
  # @option options [Hash{String=>String}] :alias Locale の読替パターン ({ 読替前のlocale=>読替後のlocale })
52
+ # @option options [Hash{String=>String}] :unification 漢字の包摂パターン ({ 包摂前の文字列=>包摂後の文字列 })
52
53
  # @option options [Array<String>] :order CalendarEra の検索順序 ([ IRI of When::TM::CalendarEra ])
53
54
  # @option options [Hash{String=>Array, String}] :format strftime で用いる記号の定義 ({ 記号=>[ 書式,項目名 ] or 記号列 })
54
55
  # @option options [Array<Array>] :leap_seconds 閏秒の挿入記録 ([ [JD, TAI-UTC, (MJD, OFFSET)] ])
@@ -56,10 +57,14 @@ module When
56
57
  #
57
58
  # @return [void]
58
59
  #
60
+ # @note
61
+ # 本メソッドでマルチスレッド対応の管理変数の初期化を行っている。
62
+ # このため、本メソッド自体および本メソッドから呼んでいる各クラスの _setup_ メソッドはスレッドセーフでない。
63
+ #
59
64
  def _setup_(options={})
60
65
  @multi_thread = options[:multi_thread]
61
66
  Parts::Resource._setup_
62
- Parts::Locale._setup_(options[:alias])
67
+ Parts::Locale._setup_(options)
63
68
  TM::CalendarEra._setup_(options[:order])
64
69
  TM::Calendar._setup_
65
70
  TM::Clock._setup_(options[:local])
@@ -107,6 +112,9 @@ module When
107
112
  DurationP1Y = TM::PeriodDuration.new([1,0,0])
108
113
  TimeValue = TM::IndeterminateValue
109
114
 
115
+ PlusInfinity = TM::TemporalPosition.new({:indeterminated_position=>TimeValue::Max})
116
+ MinusInfinity = TM::TemporalPosition.new({:indeterminated_position=>TimeValue::Min})
117
+
110
118
  UTF8 = '.UTF-8'
111
119
  W31J = '.Windows-31J'
112
120
  EUCJP = '.eucJP'
@@ -161,7 +169,17 @@ module When
161
169
  autoload :Shire, 'when_exe/region/shire'
162
170
  autoload :ShireG, 'when_exe/region/shire'
163
171
  autoload :Darian, 'when_exe/region/martian'
164
- autoload :MTC, 'when_exe/region/martian'
172
+
173
+ _time_systems = {
174
+ 'LMT' => nil, # Local Mean Time
175
+ 'LAT' => nil, # Local Apparent Time
176
+ 'THS' => nil, # Temporal Hour System
177
+ 'MTC' => 'when_exe/region/martian', # Martian Time, Coordinated
178
+ }
179
+ TimeSystems = _time_systems.keys.join('|')
180
+ _time_systems.each_pair do |key, required|
181
+ autoload key.to_sym, required if required
182
+ end
165
183
 
166
184
  class CalendarNote
167
185
  autoload :JapaneseNote, 'when_exe/region/japanese_notes'
@@ -189,76 +207,92 @@ module When
189
207
  autoload :Roman, 'when_exe/region/roman'
190
208
  autoload :Mayan, 'when_exe/region/mayan'
191
209
 
192
- # default index for date coordinates
193
- DefaultDateIndex = [
210
+ # default index for day coordinate
211
+ DefaultDayIndex = Coordinates::Index.new
212
+
213
+ # default indices for date coordinates
214
+ DefaultDateIndices = [
194
215
  Coordinates::Index.new({:unit=>12}),
195
- Coordinates::Index.new
216
+ DefaultDayIndex
196
217
  ]
197
218
 
198
- # default index for time coordinates
199
- DefaultTimeIndex = [
219
+ # default indices for time coordinates
220
+ DefaultTimeIndices = [
200
221
  Coordinates::Index.new({:base=>0, :unit=>24}),
201
222
  Coordinates::Index.new({:base=>0, :unit=>60}),
202
223
  Coordinates::Index.new({:base=>0, :unit=>60})
203
224
  ]
204
225
  end
205
226
 
206
- class TM::CalendarEra
207
- autoload :GeologicalAge, 'when_exe/region/geologicalage'
208
- autoload :Japanese, 'when_exe/region/japanese'
209
- autoload :JapanesePrimeMinister, 'when_exe/region/japanese'
210
- autoload :NihonKoki, 'when_exe/region/nihon_shoki'
211
- autoload :NihonShoki, 'when_exe/region/nihon_shoki'
212
- autoload :Chinese, 'when_exe/region/chinese_epoch'
213
- autoload :Ryukyu, 'when_exe/region/ryukyu'
214
- autoload :Korean, 'when_exe/region/korean'
215
- autoload :Vietnamese, 'when_exe/region/vietnamese'
216
- autoload :Manchurian, 'when_exe/region/far_east'
217
- autoload :Rouran, 'when_exe/region/far_east'
218
- autoload :Gaochang, 'when_exe/region/far_east'
219
- autoload :Yunnan, 'when_exe/region/far_east'
220
- # autoload :Tibetan, 'when_exe/region/tibetan'
221
- autoload :Balinese, 'when_exe/region/balinese'
222
- autoload :Javanese, 'when_exe/region/javanese'
223
- autoload :Indian , 'when_exe/region/indian'
224
- autoload :Iranian, 'when_exe/region/iranian'
225
- autoload :Hijra, 'when_exe/region/islamic'
226
- autoload :Jewish, 'when_exe/region/jewish'
227
- autoload :Roman, 'when_exe/region/roman'
228
- autoload :Julian, 'when_exe/region/roman'
229
- autoload :Pope, 'when_exe/region/pope'
230
- autoload :Byzantine, 'when_exe/region/christian'
231
- autoload :French, 'when_exe/region/french'
232
- autoload :World, 'when_exe/region/world'
233
- autoload :Mayan, 'when_exe/region/mayan'
234
-
235
- # Defualt search path for Epochs and Eras
236
- DefaultEpochs = ['Common', 'ModernJapanese',
237
- 'Iranian', 'Hijra', 'Jewish', 'Roman', 'Byzantine',
238
- 'French', 'World', 'Mayan',
239
- 'Balinese', 'Javanese',
240
- 'Japanese', 'JapanesePrimeMinister', 'NihonKoki', 'NihonShoki',
241
- 'Chinese', 'Ryukyu', 'Vietnamese', 'Korean',
242
- 'Manchurian', 'Rouran', 'Gaochang', 'Yunnan', # 'Tibetan',
243
- 'Pope' ]
244
-
245
- # Common Era
246
- Common = [self, [
247
- "namespace:[en=http://en.wikipedia.org/wiki/]",
248
- "area:[Common]",
249
- ["[BeforeCommonEra=en:BCE_(disambiguation),*alias:BCE]0.1.1"],
250
- ["[CommonEra=en:Common_Era,*alias:CE]1.1.1", "Calendar Epoch", "01-01-01^Julian"],
251
- ["[CommonEra=en:Common_Era,*alias:CE]1582.10.15", "Calendar Reform", "1582-10-15^Gregorian"]
252
- ]]
253
-
254
- # Modern Japanese Eras after the calendar reform to the Gregorian Calendar
255
- ModernJapanese = [self, [
256
- "area:[Japan]",
257
- ["M6.01.01", "Calendar Reform", "1873-01-01^Gregorian?note=DefaultNotes"],
258
- ["T1.07.30", "Accession", "1912-07-30"],
259
- ["S1.12.25", "Accession", "1926-12-25"],
260
- ["H1.01.08", "Accession", "1989-01-08"]
261
- ]]
227
+ module TM
228
+ autoload :GeologicalAge, 'when_exe/region/geologicalage'
229
+ class CalendarEra
230
+ autoload :Japanese, 'when_exe/region/japanese'
231
+ autoload :JapanesePrimeMinister, 'when_exe/region/japanese'
232
+ autoload :NihonKoki, 'when_exe/region/nihon_shoki'
233
+ autoload :NihonShoki, 'when_exe/region/nihon_shoki'
234
+ autoload :Chinese, 'when_exe/region/chinese_epoch'
235
+ autoload :Ryukyu, 'when_exe/region/ryukyu'
236
+ autoload :Korean, 'when_exe/region/korean'
237
+ autoload :Vietnamese, 'when_exe/region/vietnamese'
238
+ autoload :Manchurian, 'when_exe/region/far_east'
239
+ autoload :Rouran, 'when_exe/region/far_east'
240
+ autoload :Gaochang, 'when_exe/region/far_east'
241
+ autoload :Yunnan, 'when_exe/region/far_east'
242
+ # autoload :Tibetan, 'when_exe/region/tibetan'
243
+ autoload :Balinese, 'when_exe/region/balinese'
244
+ autoload :Javanese, 'when_exe/region/javanese'
245
+ autoload :Indian , 'when_exe/region/indian'
246
+ autoload :Iranian, 'when_exe/region/iranian'
247
+ autoload :Hijra, 'when_exe/region/islamic'
248
+ autoload :Jewish, 'when_exe/region/jewish'
249
+ autoload :Roman, 'when_exe/region/roman'
250
+ autoload :Julian, 'when_exe/region/roman'
251
+ autoload :Pope, 'when_exe/region/pope'
252
+ autoload :Byzantine, 'when_exe/region/christian'
253
+ autoload :French, 'when_exe/region/french'
254
+ autoload :World, 'when_exe/region/world'
255
+ autoload :Mayan, 'when_exe/region/mayan'
256
+
257
+ # Defualt search path for Epochs and Eras
258
+ DefaultEpochs = ['Common', 'ModernJapanese',
259
+ 'Indian', 'Iranian', 'Hijra', 'Jewish',
260
+ 'Roman', 'Byzantine', 'French', 'World', 'Mayan',
261
+ 'Balinese', 'Javanese',
262
+ 'Japanese', 'JapanesePrimeMinister', 'NihonKoki', 'NihonShoki',
263
+ 'Chinese', 'Ryukyu', 'Vietnamese', 'Korean',
264
+ 'Manchurian', 'Rouran', 'Gaochang', 'Yunnan', # 'Tibetan',
265
+ 'Pope' ]
266
+
267
+ # Defualt events for Epochs and Eras
268
+ DefaultEvents = Hash[*([['@A', 'Accession' ],
269
+ ['@FE', 'FelicitousEvent' ],
270
+ ['@ND', 'NaturalDisaster' ],
271
+ ['@IY', 'InauspiciousYear'],
272
+ ['@F', 'Foundation' ],
273
+ ['@CR', 'CalendarReform' ]].map {|e|
274
+ [e[0], When::Parts::Resource._instance('EpochEvents::'+e[1], '_m:')]
275
+ }.flatten)]
276
+
277
+ # Common Era
278
+ Common = [self, [
279
+ "namespace:[en=http://en.wikipedia.org/wiki/]",
280
+ "area:[Common]",
281
+ ["[BeforeCommonEra=en:BCE_(disambiguation),*alias:BCE]0.1.1"],
282
+ ["[CommonEra=en:Common_Era,*alias:CE]1.1.1", "Calendar Epoch", "01-01-01^Julian"],
283
+ ["[CommonEra=en:Common_Era,*alias:CE]1582.10.15", "Calendar Reform", "1582-10-15^Gregorian"]
284
+ ]]
285
+
286
+ # Modern Japanese Eras after the calendar reform to the Gregorian Calendar
287
+ ModernJapanese = [self, [
288
+ "namespace:[en=http://en.wikipedia.org/wiki/, ja=http://ja.wikipedia.org/wiki/]",
289
+ "area:[Japan]",
290
+ ["[M=,alias:明=ja:明治]6.01.01", "Calendar Reform", "1873-01-01^Gregorian?note=DefaultNotes"],
291
+ ["[T=,alias:大=ja:大正]1.07.30", "Accession", "1912-07-30"],
292
+ ["[S=,alias:昭=ja:昭和]1.12.25", "Accession", "1926-12-25"],
293
+ ["[H=,alias:平=ja:平成]1.01.08", "Accession", "1989-01-08"]
294
+ ]]
295
+ end
262
296
  end
263
297
 
264
298
  #
@@ -508,7 +542,7 @@ module When
508
542
  case clock
509
543
  when TM::Clock ; return clock
510
544
  when 'Z' ; return utc
511
- when /^LMT|LAT|THS|MTC/ ; return Parts::Resource._instance('_c:' + clock)
545
+ when /^#{CalendarTypes::TimeSystems}/ ; return Parts::Resource._instance('_c:' + clock)
512
546
  when Numeric ; return utc if clock==0
513
547
  when String
514
548
  c = TM::Clock[clock] || V::Timezone[clock]
@@ -278,7 +278,7 @@ module When
278
278
  unless (time =~ /^(\d{2}(?:\.\d+)?|-)(\d{2}(?:\.\d+)?|-)?(\d{2}(\.\d+)?)?$/)
279
279
  raise ArgumentError, "Wrong time format: #{time}"
280
280
  end
281
- indices = options[:frame] ? options[:frame].indices : Coordinates::DefaultDateIndex
281
+ indices = options[:frame] ? options[:frame].indices : Coordinates::DefaultDateIndices
282
282
  abbr = Array(options[:abbr]).dup
283
283
  abbr[0..indices.length] = []
284
284
  return [0, Coordinates::Pair._en_number($1=='-' ? abbr[0] : $1, nil),
@@ -290,7 +290,7 @@ module When
290
290
  def _to_array_extended(time, t, options={})
291
291
  return nil unless t
292
292
  return [0] unless time
293
- indices = options[:frame] ? options[:frame].indices : Coordinates::DefaultDateIndex
293
+ indices = options[:frame] ? options[:frame].indices : Coordinates::DefaultDateIndices
294
294
  abbr = Array(options[:abbr]).dup
295
295
  abbr[0..indices.length] = []
296
296
  time.sub!(/,/, '.')
@@ -57,7 +57,7 @@ module When::CalendarTypes
57
57
  # オブジェクトの正規化
58
58
  def _normalize(args=[], options={})
59
59
  @label ||= m17n('Z')
60
- @indices ||= When::Coordinates::DefaultTimeIndex
60
+ @indices ||= When::Coordinates::DefaultTimeIndices
61
61
  @note ||= 'JulianDayNotes'
62
62
  _normalize_temporal
63
63
  @second = (@second||128).to_f
@@ -1228,6 +1228,9 @@ module When::CalendarTypes
1228
1228
  # @option options [Hash] その他のキー date を When::TM::TemporalPosition に変換するために使用する
1229
1229
  # see {When::TM::TemporalPosition._instance}
1230
1230
  #
1231
+ # @note CalendarNoteオブジェクト生成時に _normalize メソッド内で @prime 変数を設定しておけば、
1232
+ # 本メソッドの :prime オプションで参照される。(BalineseNote#_normalize等参照)
1233
+ #
1231
1234
  # @note 暦注のビットアドレスは、暦注サブクラスのNoteObjects定数の中の定義順序による。
1232
1235
  # When::CalendarTypes::CalendarNote クラスの場合 new の引数とした暦注要素リストの定義順序による。
1233
1236
  # ビットアドレスの値が 1 の暦注が計算対象となる。
@@ -1327,7 +1330,7 @@ module When::CalendarTypes
1327
1330
  #
1328
1331
  def _normalize(args=[], options={})
1329
1332
  @_elements = (args.size == 0 && self.class.const_defined?(:NoteObjects)) ?
1330
- When::SourceURI + self.class.to_s.split(/::/)[1..-1].join('/') + '/NoteObjects' :
1333
+ When::Parts::Resource.base_uri + self.class.to_s.split(/::/)[1..-1].join('/') + '/NoteObjects' :
1331
1334
  _to_iri(args, options[:prefix] || '_co:')
1332
1335
  if @_elements.kind_of?(Array)
1333
1336
  @_elements.each do |e|
@@ -855,6 +855,8 @@ module When::Coordinates
855
855
  #
856
856
  # @return [String]
857
857
  #
858
+ # @note %0s は文字列引数の表示を抑制するための指定となる。C言語のprintfと異なるので注意。
859
+ #
858
860
  def _format(m17ns)
859
861
  index = 1
860
862
  m17ns[0].scan(/(%(?:(\d)\$)?[-+0# ]?[*\d.$]*[cspdiuboxXfgeEG])([-.:])?|(%%|.)/).inject('') { |form, m17n|
@@ -1399,7 +1401,12 @@ module When::Coordinates
1399
1401
  if respond_to?(:timezone)
1400
1402
  @timezone ||= @location ? @location.long / (Spatial::DEGREE * 15) : 9.0
1401
1403
  @timezone = @timezone.kind_of?(String) ? @timezone.split(/,/) : Array(@timezone)
1402
- @timezone = @timezone.map {|v| v.to_f / 24}
1404
+ @timezone = @timezone.map {|v|
1405
+ d = v.split('/')[1] if v.kind_of?(String)
1406
+ v = v.to_f / 24
1407
+ v /= d.to_f if d
1408
+ v
1409
+ }
1403
1410
  (1...@timezone.size).each do |i|
1404
1411
  @timezone[i] += @timezone[i-1]
1405
1412
  end
@@ -1487,6 +1494,9 @@ module When::Coordinates
1487
1494
  #
1488
1495
  # 初期化時に indices から自動生成する
1489
1496
  #
1497
+ # @note 日付/日時の外部表現の「下限」を指定する。内部表現の下限は常に 0 である。
1498
+ # サブクラスが定義するメソッド _coordinates_to_number, _number_to_coordinates は内部表現を使用する。
1499
+ #
1490
1500
  attr_reader :base
1491
1501
 
1492
1502
  # 日時要素がPairであるべきか
@@ -9,6 +9,44 @@
9
9
  # When::TM::Duration のための標準クラスの拡張
10
10
  #
11
11
 
12
+ #
13
+ # When::TM::Duration
14
+ #
15
+ # @private
16
+ class When::TM::Duration
17
+ def rational_duration
18
+ unless @rational_duration
19
+ sec = duration / When::TM::Duration::SECOND
20
+ mod = sec % When::TM::Duration::DAY.to_i
21
+ if mod == 0 || mod != mod.to_i
22
+ @rational_duration = @duration / When::TM::Duration::DAY
23
+ else
24
+ @rational_duration = Rational(sec.to_i, 86400)
25
+ end
26
+ end
27
+
28
+ @rational_duration
29
+ end
30
+ end
31
+
32
+ #
33
+ # Extensions to Date class
34
+ #
35
+ # @private
36
+ class Date
37
+
38
+ alias :_plus_ :+
39
+ def +(other)
40
+ other.kind_of?(When::TM::Duration) ? self + other.rational_duration : self._plus_(other)
41
+ end
42
+
43
+
44
+ alias :_minus_ :-
45
+ def -(other)
46
+ other.kind_of?(When::TM::Duration) ? self - other.rational_duration : self._minus_(other)
47
+ end
48
+ end
49
+
12
50
  #
13
51
  # Extensions to Time class
14
52
  #
@@ -90,6 +90,17 @@ class Numeric
90
90
  end
91
91
  alias :month_name :to_month_name
92
92
 
93
+ # self を幹の要素と解釈してWhen::Coordinates::Pair を生成
94
+ #
95
+ # @see When::Coordinates::Pair._force_pair
96
+ #
97
+ # @return [When::Coordinates::Pair]
98
+ #
99
+ def to_pair(branch=nil)
100
+ Coordinates::Pair._force_pair(self, branch)
101
+ end
102
+ alias :pair :to_pair
103
+
93
104
  # メソッド名に相当する単位で表した When::TM::IntervalLength
94
105
  # @method unit_interval_length
95
106
  # @return [When::TM::IntervalLength]
@@ -163,7 +174,7 @@ class String
163
174
  #
164
175
  # @return [String] 包摂結果
165
176
  #
166
- def ideographic_unification(pattern=When::Parts::Locale::DefaultUnification)
177
+ def ideographic_unification(pattern=When::Parts::Locale._unification)
167
178
  When::Parts::Locale.ideographic_unification(self, pattern)
168
179
  end
169
180
 
@@ -234,9 +245,10 @@ class String
234
245
  #
235
246
  # @return [When::Coordinates::Pair]
236
247
  #
237
- def pair
248
+ def to_pair
238
249
  Coordinates::Pair._force_pair(self)
239
250
  end
251
+ alias :pair :to_pair
240
252
 
241
253
  #
242
254
  # self を検索する暦年代とみなして登録された When::TM::CalendarEraを検索
@@ -290,7 +302,8 @@ class String
290
302
  def to_residue
291
303
  When::Coordinates::Residue.to_residue(self)
292
304
  end
293
- alias :residue :to_residue
305
+ alias :residue :to_residue
306
+ alias :day_of_week :to_residue
294
307
 
295
308
  #
296
309
  # 月名
@@ -350,7 +363,7 @@ class Regexp
350
363
  #
351
364
  # @return [Regexp] 包摂結果
352
365
  #
353
- def ideographic_unification(pattern=When::Parts::Locale::DefaultUnification)
366
+ def ideographic_unification(pattern=When::Parts::Locale._unification)
354
367
  When::Parts::Locale.ideographic_unification(self, pattern)
355
368
  end
356
369
  end
@@ -277,13 +277,15 @@ module When::Ephemeris
277
277
 
278
278
  # func の逆変換
279
279
  #
280
- # @param [Numeric] t0 独立変数の初期近似値
281
- # @param [Numeric] y0 逆変換される関数値(nil なら極値を求める)
282
- # @param [Block] func 逆変換される関数
280
+ # @param [Numeric] t0 独立変数の初期近似値
281
+ # @param [Numeric] y0 逆変換される関数値(nil なら極値を求める)
282
+ # @param [Numeric] count 収束までの最大繰り返し回数
283
+ # @param [Float] error 収束と判断する誤差
284
+ # @param [Block] func 逆変換される関数
283
285
  #
284
286
  # @return [Numeric] 逆変換結果
285
287
  #
286
- def root(t0, y0=nil, &func)
288
+ def root(t0, y0=nil, count=10, error=1E-6, &func)
287
289
 
288
290
  # 近似値0,1
289
291
  # printf("y0=%20.7f\n",y0)
@@ -295,11 +297,11 @@ module When::Ephemeris
295
297
  t << (y0 ? (t[1]-t[0])/(y[1]-y[0])*(y0-y[0])+t[0] : t0-0.1)
296
298
 
297
299
  # 繰り返し
298
- i = 10
299
- while ((t[2]-t[1]).abs > 1E-6) && (i > 0)
300
+ i = count
301
+ while ((t[2]-t[1]).abs > error) && (i > 0)
300
302
  # 予備計算
301
303
  y << func.call(t[2])
302
- break if y0 && (y[2]-y0).abs <= 1E-7
304
+ break if y0 && (y[2]-y0).abs <= error / 10
303
305
 
304
306
  # printf("t=%20.7f,L=%20.7f\n",t[2],y[2])
305
307
  t01 = t[0]-t[1]
@@ -329,7 +331,7 @@ module When::Ephemeris
329
331
  t.shift
330
332
  y.shift
331
333
  end
332
- $stderr.puts "The result is not reliable" if i<=0
334
+ raise RangeError, "The result does not converge." if i<=0
333
335
  return t[2]
334
336
  end
335
337
 
@@ -1292,9 +1294,10 @@ module When::Ephemeris
1292
1294
  # @param [Numeric] t ユリウス日(Terrestrial Time)
1293
1295
  # @param [When::TM::TemporalPosition] t
1294
1296
  # @param [Integer] event
1295
- # [ -1 - 出 ]
1296
- # [ 0 - 最大高度 ]
1297
- # [ +1 - 没 ]
1297
+ # [ -1 - 出 ]
1298
+ # [ 0 - 南中 ]
1299
+ # [ +1 - 没 ]
1300
+ # [ nil - 最大高度 ]
1298
1301
  # @param [When::Ephemeris::CelestialObject] target 対象星(デフォルトは太陽)
1299
1302
  # @param [Numeric] height 閾値高度/度
1300
1303
  # @param [String] height
@@ -1311,13 +1314,14 @@ module When::Ephemeris
1311
1314
  dl = @location.long / (360.0 * When::Coordinates::Spatial::DEGREE)
1312
1315
  t0 = (+t + 0.5 + dl).floor - dl
1313
1316
  dt = _coords(t0, When::Coordinates::Spatial::EQUATORIAL, target).phi -
1314
- @location.local_sidereal_time(t0) / 24.0 + 0.25 * event
1317
+ @location.local_sidereal_time(t0) / 24.0 + 0.25 * (event||0)
1315
1318
  t0 += dt - (dt+0.5).floor
1316
1319
 
1317
- # 天体の地平座標での高度
1318
- if event == 0
1319
- height = nil # 極値検索のため
1320
- else
1320
+ # 天体の地平座標での高度または方位角
1321
+ case event
1322
+ when 0
1323
+ meridian = _coords(t0, When::Coordinates::Spatial::HORIZONTAL, target).phi.round
1324
+ when +1, -1
1321
1325
  height ||= target.instance_of?(When::Ephemeris::Sun) ? '0' : 'A'
1322
1326
  if height.kind_of?(String)
1323
1327
  height = @location.datum.zeros[height.upcase]
@@ -1325,10 +1329,15 @@ module When::Ephemeris
1325
1329
  end
1326
1330
  height = height / 360.0 - (0.25 - @location.horizon) +
1327
1331
  [@location.alt / (1000.0 * @location.datum.air[0]), 1].min * @location.datum.zeros['A'] / 360.0
1332
+ else
1333
+ height = nil # 極値検索のため
1328
1334
  end
1329
1335
 
1330
1336
  # イベントの時刻
1331
- _to_seed_type(root(t0, height) {|t1| _coords(t1, When::Coordinates::Spatial::HORIZONTAL, target).theta }, t)
1337
+ _to_seed_type(
1338
+ event == 0 ? (root(t0, meridian) {|t1| _coords(t1, When::Coordinates::Spatial::HORIZONTAL, target).phi }) :
1339
+ (root(t0, height ) {|t1| _coords(t1, When::Coordinates::Spatial::HORIZONTAL, target).theta }),
1340
+ t)
1332
1341
  end
1333
1342
 
1334
1343
  # 日の出の日時
@@ -1369,6 +1378,17 @@ module When::Ephemeris
1369
1378
  # @return [Numeric, When::TM::TemporalPosotion] 太陽の最大高度の日時(ユリウス日(Terrestrial Time)またはWhen::TM::DateAndTime
1370
1379
  #
1371
1380
  def sun_noon(t)
1381
+ day_event(t, nil, When.Resource('_ep:Sun'))
1382
+ end
1383
+
1384
+ # 太陽の南中の日時
1385
+ #
1386
+ # @param [Numeric] t ユリウス日(Terrestrial Time)
1387
+ # @param [When::TM::TemporalPosition] t
1388
+ #
1389
+ # @return [Numeric, When::TM::TemporalPosotion] 太陽の南中の日時(ユリウス日(Terrestrial Time)またはWhen::TM::DateAndTime
1390
+ #
1391
+ def meridian_passage_of_sun(t)
1372
1392
  day_event(t, 0, When.Resource('_ep:Sun'))
1373
1393
  end
1374
1394
 
@@ -1411,6 +1431,18 @@ module When::Ephemeris
1411
1431
  # 該当時刻がなければ nil
1412
1432
  #
1413
1433
  def moon_noon(t)
1434
+ _day_event(t, nil, When.Resource('_ep:Moon'))
1435
+ end
1436
+
1437
+ # 月の南中の日時
1438
+ #
1439
+ # @param [Numeric] t ユリウス日(Terrestrial Time)
1440
+ # @param [When::TM::TemporalPosition] t
1441
+ #
1442
+ # @return [Numeric, When::TM::TemporalPosotion] 月の南中の日時(ユリウス日(Terrestrial Time)またはWhen::TM::DateAndTime
1443
+ # 該当時刻がなければ nil
1444
+ #
1445
+ def meridian_passage_of_moon(t)
1414
1446
  _day_event(t, 0, When.Resource('_ep:Moon'))
1415
1447
  end
1416
1448