when_exe 0.4.4 → 0.4.5

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 (67) hide show
  1. checksums.yaml +4 -4
  2. data/lib/when_exe.rb +89 -3
  3. data/lib/when_exe/basictypes.rb +37 -7
  4. data/lib/when_exe/calendarnote.rb +18 -13
  5. data/lib/when_exe/calendartypes.rb +3 -9
  6. data/lib/when_exe/coordinates.rb +23 -373
  7. data/lib/when_exe/ephemeris.rb +7 -7
  8. data/lib/when_exe/ephemeris/notes.rb +0 -14
  9. data/lib/when_exe/events.rb +1851 -0
  10. data/lib/when_exe/icalendar.rb +121 -4
  11. data/lib/when_exe/linkeddata.rb +29 -18
  12. data/lib/when_exe/locales/akt.rb +63 -0
  13. data/lib/when_exe/locales/locale.rb +60 -11
  14. data/lib/when_exe/mini_application.rb +14 -8
  15. data/lib/when_exe/namespace.rb +42 -0
  16. data/lib/when_exe/parts/enumerator.rb +13 -2
  17. data/lib/when_exe/parts/geometric_complex.rb +51 -1
  18. data/lib/when_exe/parts/method_cash.rb +15 -10
  19. data/lib/when_exe/parts/resource.rb +47 -29
  20. data/lib/when_exe/region/chinese.rb +4 -3
  21. data/lib/when_exe/region/chinese/calendars.rb +4 -4
  22. data/lib/when_exe/region/chinese/epochs.rb +6 -6
  23. data/lib/when_exe/region/chinese/notes.rb +3 -3
  24. data/lib/when_exe/region/chinese/twins.rb +6 -6
  25. data/lib/when_exe/region/islamic.rb +1 -1
  26. data/lib/when_exe/region/japanese.rb +4 -4
  27. data/lib/when_exe/region/japanese/eclipses.rb +2 -2
  28. data/lib/when_exe/region/japanese/location.rb +93 -0
  29. data/lib/when_exe/region/japanese/notes.rb +29 -11
  30. data/lib/when_exe/region/japanese/residues.rb +1 -1
  31. data/lib/when_exe/region/japanese/twins.rb +18 -6
  32. data/lib/when_exe/region/location.rb +40 -0
  33. data/lib/when_exe/region/martian.rb +1 -1
  34. data/lib/when_exe/region/ryukyu.rb +1 -1
  35. data/lib/when_exe/spatial.rb +611 -0
  36. data/lib/when_exe/timestandard.rb +3 -3
  37. data/lib/when_exe/tmobjects.rb +32 -0
  38. data/lib/when_exe/tmposition.rb +211 -1318
  39. data/lib/when_exe/tmptypes.rb +1265 -0
  40. data/lib/when_exe/tmreference.rb +35 -0
  41. data/lib/when_exe/version.rb +3 -3
  42. data/test/events/example-datasets +7 -0
  43. data/test/events/history-dataset.csv +22 -0
  44. data/test/events/japanese-holiday-index.csv +28 -0
  45. data/test/events/japanese-holiday.csv +77 -0
  46. data/test/events/japanese-holiday.ttl +778 -0
  47. data/test/events/make_events_ttl.rb +18 -0
  48. data/test/events/mori_wikichoshi.csv +14 -0
  49. data/test/events/ndl_koyomi.csv +220 -0
  50. data/test/events/ndl_koyomi_index.csv +44 -0
  51. data/test/events/primeminister-dataset.csv +19 -0
  52. data/test/events/shogun-dataset.csv +22 -0
  53. data/test/events/test-history-dataset-edge-sparql.csv +26 -0
  54. data/test/events/test-history-dataset-edge.csv +27 -0
  55. data/test/events/test-history-dataset-sparql.csv +22 -0
  56. data/test/events/test-history-dataset.csv +23 -0
  57. data/test/events/test-history-events-edge.ttl +89 -0
  58. data/test/events/test-history-events.csv +6 -0
  59. data/test/examples/Terms.m17n +1 -1
  60. data/test/test.rb +6 -0
  61. data/test/test/coordinates.rb +2 -2
  62. data/test/test/events.rb +32 -0
  63. data/test/test/region/japanese.rb +20 -0
  64. data/test/test/region/m17n.rb +2 -2
  65. data/test/test/region/mayan.rb +6 -6
  66. data/test/test/tmposition.rb +63 -1
  67. metadata +26 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9b9bc44ba4bb20ae30d7045497d49f25fd503dfd
4
- data.tar.gz: ffe446a7242476d41521a3d6d0476976fa23f3fd
3
+ metadata.gz: 69630f5514eefbea95c1ddca1274582e19e337d0
4
+ data.tar.gz: 34bdb14391d28c9014e8b9b7229f1b03f52c10da
5
5
  SHA512:
6
- metadata.gz: cbaf55a5f8bc08cfde7cead93da6d72a9436405ced2efe0630c824f0bcb0749a5767385d8e2ff79bad0a83ecb8f1ec127ed864d79456ab8060a924d9371ea64e
7
- data.tar.gz: ed61811070132482a71402702c2ea9aeff47cff2f4c6f97c4d213f77add98472a4f622b8a3d52a70fcaaf541af412f440566d799d615a038eeafdeccd9543934
6
+ metadata.gz: c616bb66c59cac0b12cf6fc0305e2c514c021ea9c3cf1e31a37c0cf9cc1d578dc8b7990200972bbcc83b9b8bcf4b8ddbcd7909fd3280e95aa5af7d30b3d5200a
7
+ data.tar.gz: 648c7b04e05f2c9759112a6c2dc967a78fd61f3800bc7a3f04bf874539f9b785f4e5cc644904aff3649947a74741096c836eb813e2fba8938e7b6811e66da707
@@ -1,6 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  =begin
3
- Copyright (C) 2011-2015 Takashi SUGA
3
+ Copyright (C) 2011-2016 Takashi SUGA
4
4
 
5
5
  You may use and/or modify this file according to the license described in the LICENSE.txt file included in this archive.
6
6
  =end
@@ -19,11 +19,12 @@ begin
19
19
  rescue LoadError, NoMethodError
20
20
  end
21
21
 
22
- autoload :URI, 'uri'
22
+ autoload :CGI, 'cgi'
23
23
  autoload :OpenURI, 'open-uri'
24
24
  autoload :OpenSSL, 'openssl'
25
25
  autoload :FileUtils, 'fileutils'
26
26
  autoload :REXML, 'rexml/document'
27
+ autoload :CSV, 'csv'
27
28
  autoload :Mutex, 'thread' unless Object.const_defined?(:Mutex)
28
29
 
29
30
  #
@@ -157,6 +158,7 @@ module When
157
158
 
158
159
  require 'when_exe/locales/locale'
159
160
  require 'when_exe/locales/autoload'
161
+ require 'when_exe/namespace'
160
162
  require 'when_exe/parts/enumerator'
161
163
  require 'when_exe/parts/resource'
162
164
  require 'when_exe/parts/geometric_complex'
@@ -165,11 +167,13 @@ module When
165
167
  require 'when_exe/basictypes'
166
168
  require 'when_exe/ephemeris'
167
169
  require 'when_exe/coordinates'
170
+ require 'when_exe/spatial'
168
171
  require 'when_exe/icalendar'
169
172
  require 'when_exe/google_api'
170
173
  require 'when_exe/tmobjects'
171
174
  require 'when_exe/timestandard'
172
175
  require 'when_exe/tmposition'
176
+ require 'when_exe/tmptypes'
173
177
  require 'when_exe/tmreference'
174
178
  require 'when_exe/calendartypes'
175
179
  require 'when_exe/calendarnote'
@@ -228,6 +232,14 @@ module When
228
232
  # eucJP encoding
229
233
  EUCJP = '.eucJP'
230
234
 
235
+ module Events
236
+ autoload :TS, 'when_exe/events'
237
+ autoload :DataSets, 'when_exe/events'
238
+ autoload :DataSet, 'when_exe/events'
239
+ autoload :Event, 'when_exe/events'
240
+ autoload :Range, 'when_exe/events'
241
+ end
242
+
231
243
  class BasicTypes::M17n
232
244
  autoload :Japanese, 'when_exe/region/japanese'
233
245
  autoload :JapaneseHoliday, 'when_exe/region/japanese'
@@ -272,6 +284,20 @@ module When
272
284
  autoload :IAST, 'when_exe/locales/iast'
273
285
  autoload :IASTR, 'when_exe/locales/iast'
274
286
  autoload :AKT, 'when_exe/locales/akt'
287
+ autoload :NumRExp3, 'when_exe/locales/akt'
288
+
289
+ sb = (When::Parts::Resource._instance('_co:Common::干支::*') +
290
+ When::Parts::Resource._instance('_co:Common::干::*') +
291
+ When::Parts::Resource._instance('_co:Common::支::*')).map {|r| r.label.to_s}.join('|')
292
+ DigitParser = [[:NumRExp3]]
293
+ TimeParser = [[/閏(\d+)時/, 'T\1='], [/(\d+)時/, 'T\1:'], [/(\d+)分/, '\1:'], [/(\d+)秒/, '\1']]
294
+ DateParser = [[/(#{sb})/, '{1\1}', true], [/([^\d])\{/, '\11{', true],
295
+ [/元年/, '1-'], [/(\d+|\})[年|載|歳]/, '\1-'], [/閏(\d+)月/, '\1='], [/(\d+)月/, '\1-'],
296
+ [/(\d+)日/, '\1']]
297
+ EasternParser = DigitParser + DateParser + TimeParser
298
+ JapaneseParser = [[/\A(\d+)/, '日本\1']] + EasternParser
299
+ KoreanParser = [[/\A(\d+)/, '朝鮮\1']] + EasternParser
300
+ ChineseParser = [[/\A(\d+)/, '中国\1']] + EasternParser
275
301
  end
276
302
 
277
303
  module CalendarTypes
@@ -404,6 +430,7 @@ module When
404
430
  autoload :Russian, 'when_exe/region/russian'
405
431
  autoload :Roman, 'when_exe/region/roman'
406
432
  autoload :Mayan, 'when_exe/region/mayan'
433
+ autoload :LocationTable, 'when_exe/region/location'
407
434
 
408
435
  # default index for day coordinate
409
436
  DefaultDayIndex = Index.new
@@ -528,7 +555,7 @@ module When
528
555
  when Array ; begin options = TM::TemporalPosition._options(options) ; specification.map {|e| when?(e, options)} end
529
556
  when /\Atoday((\^|%5E){1,2}(.+))?\z/i ; today($3 ? {:frame=>$3}.update(options) : options)
530
557
  when /\Anow((\^|%5E){1,2}(.+))?\z/i ; now( $3 ? {:frame=>$3}.update(options) : options)
531
- when /(JDN|MJD|SDN|CEP)(\z|\^|%5E)/i ; TM::JulianDate.parse(specification, options)
558
+ when /(JDN|MJD|SDN|CEP|DTB)(\z|\^|%5E)/i ; TM::JulianDate.parse(specification, options)
532
559
  when /[\n\r]+/ ; when?(specification.split(/[\n\r]+/), options)
533
560
  when String ; TM::TemporalPosition._instance(EncodingConversion.to_internal_encoding(specification), options)
534
561
  when Numeric ; TM::JulianDate.new(+specification, TM::TemporalPosition._options(options))
@@ -561,6 +588,40 @@ module When
561
588
  alias :tm_pos :TemporalPosition
562
589
  module_function :tm_pos
563
590
 
591
+ # 書式文字列に従った When::TM::TemporalPosition の生成
592
+ #
593
+ # @param [String] date_time 日時を表す文字列
594
+ # @param [String] format その書式
595
+ # @param [Hash] options 暦法や時法などの指定
596
+ # @option options [String] :locale 言語指定
597
+ # @option options [Object] :その他 When::TM::TemporalPosition._instance に渡す
598
+ # @see When::TM::TemporalPosition._instance
599
+ #
600
+ # @return [When::TM::TemporalPosition]
601
+ # @raise [ArgumentError]
602
+ # options[ :invalid ] が :raise で、日時が存在しない場合
603
+ #
604
+ # see {strptime}[link:http://docs.ruby-lang.org/ja/search/query:strptime/]
605
+ #
606
+ def strptime(date_time, format, options={})
607
+ h = When::Locale._to_date_time_hash(date_time, format, options[:locale])
608
+ abbr_y, abbr_m, abbr_d, =
609
+ options[:abbr].kind_of?(When::TimeValue) ?
610
+ ((options[:frame]||When::Gregorian) ^ options[:abbr]).cal_date : options[:abbr]
611
+ args = [h[:year] || abbr_y || ::Date.today.year]
612
+ args << (h[:mon] || abbr_m || 1) if h[:hour] || h[:mon]
613
+ args << (h[:mday] || abbr_d || 1) if h[:hour] || (h[:mon] && h[:mday])
614
+ args << h[:hour] if h[:hour]
615
+ args << h[:min] if h[:hour] && h[:min]
616
+ args << h[:sec] if h[:hour] && h[:min] && h[:sec]
617
+ args << options.dup
618
+ args[-1].delete(:locale)
619
+ args[-1].delete(:abbr)
620
+ args[-1].update({:parse=>{:residue=>{2=>When.Residue((h[:wday]-1)%7)}}}) if h[:wday]
621
+ args[-1].update({:clock=>When::TM::Clock.to_hms(h[:offset])}) if h[:offset]
622
+ TM::TemporalPosition._temporal_position(*args)
623
+ end
624
+
564
625
  # 指定日時に対応する When::TM::TemporalPosition の生成
565
626
  # (When::TM::DateAndTime of specified Time)
566
627
  #
@@ -709,6 +770,20 @@ module When
709
770
  TM::CalendarEra._instance(*args)
710
771
  end
711
772
 
773
+ # When::TM::TemporalPosition または When::TM::CalendarEraの検索
774
+ #
775
+ # @param [Array<Object>] args when? または era にそのまま渡される
776
+ #
777
+ # @return [When::TM::TemporalPosition or When::TM::CalendarEra]
778
+ #
779
+ def date_or_era(*args)
780
+ begin
781
+ when?(*args)
782
+ rescue
783
+ era(*args).first
784
+ end
785
+ end
786
+
712
787
  # When::TM::Clock の生成/参照
713
788
  #
714
789
  # @param [When::Parts::Timezone::Base] clock なにもせず clock をそのまま返す
@@ -782,6 +857,17 @@ module When
782
857
  Parts::Resource._instance(iri)
783
858
  end
784
859
 
860
+
861
+ # 地名を空間座標化する
862
+ #
863
+ # @param [String] name 地名または座標
864
+ #
865
+ # @return [When::Coordinates::Spatial or When::Coordinates::Spatial::Range]
866
+ #
867
+ def where?(name)
868
+ When::Coordinates::Spatial::Range[name]
869
+ end
870
+
785
871
  # When::Coordinates::Border の生成/参照
786
872
  #
787
873
  # @param [String] border 年/日境界を表す文字列
@@ -50,6 +50,7 @@ module When
50
50
  if options[:abbr].kind_of?(When::TimeValue)
51
51
  options[:abbr] = ((options[:frame]||When::Gregorian) ^ options[:abbr]).cal_date
52
52
  end
53
+ date_time = _parse(date_time, options.delete(:parse), options[:abbr]||[]) if options[:parse]
53
54
  date_time = date_time.gsub(/[_\s]+([\d])/, '\1')
54
55
  begin
55
56
  return _to_array_basic(date_time, options)
@@ -126,19 +127,48 @@ module When
126
127
 
127
128
  # 剰余類の指定を置き換える
128
129
  def _split_residue(d, abbr)
129
- abbr, = abbr
130
- residue = {}
130
+ abbr, = abbr
131
+ options = {}
131
132
  count = 0
132
133
  sign, d = d =~ /^-/ ? ['-', d[1..-1]] : ['', d]
133
134
  [sign + d.gsub(/[-+*&%@!>=<?.]|(\d)?\{(.+?)\}/) {|s|
134
135
  if $2
135
- residue[count] = $2
136
- count == 0 ? ($1 || abbr || 1) : $1
136
+ digit = $1
137
+ operation = $2.strip
138
+ residue = When.Residue(operation) unless operation =~ /[#,]|[^:][-+]/
139
+ options[count] = residue && residue.shifted ? residue : operation
140
+ count == 0 ? (digit || abbr || 1) : digit
137
141
  else
138
142
  count += 1
139
143
  s
140
144
  end
141
- }, residue]
145
+ }, options]
146
+ end
147
+
148
+ # 日付文字列を事前に変換する
149
+ def _parse(date_time, parse, abbr)
150
+ format, locale = parse
151
+ case format
152
+ when String, Hash
153
+ h = When::Locale._to_date_time_hash(date_time, format, locale)
154
+ date_time = (h[:wday] ? "%4d-%02d-01{%d&%s}" : "%4d-%02d-%02d") % [
155
+ h[:year] || abbr[0] || ::Date.today.year,
156
+ h[:mon] || abbr[1] || 1,
157
+ h[:mday] || abbr[2] || 1,
158
+ When::V::Event::DayOfWeek[h[:wday]||0]]
159
+ date_time << "T%02d:%02d:%02d" % [
160
+ h[:hour] || abbr[3] || 0,
161
+ h[:min] || abbr[4] || 0,
162
+ h[:sec] || abbr[5] || 0] if h[:hour]
163
+ date_time << When::TM::Clock.to_hms(h[:offset]) if h[:offset]
164
+ when Array
165
+ parse.each do |item|
166
+ item[2] ? date_time.gsub!(item[0], item[1]) :
167
+ item[1] ? date_time.sub!( item[0], item[1]) :
168
+ date_time.gsub!(When::Locale::NumRExp3) {|digit| When::Locale.k2a_digits(digit, true)}
169
+ end unless date_time =~ /\{/
170
+ end
171
+ date_time
142
172
  end
143
173
  end
144
174
  end
@@ -354,12 +384,12 @@ module When
354
384
  else
355
385
  tt = [0]
356
386
  end
357
- while time =~ /\A(\d{2}(?:\.\d+)?|-)([:*=])(.+)/
387
+ while time =~ /\A(\d{1,2}(?:\.\d+)?|-)([:*=])(.+)/
358
388
  time = $3
359
389
  tt << Coordinates::Pair._en_pair($1=='-' ? abbr.shift : $1, $2)
360
390
  end
361
391
  case time
362
- when /\A(\d{2}(\.\d+)?)\z/
392
+ when /\A(\d{1,2}(\.\d+)?)\z/
363
393
  tt << Coordinates::Pair._en_number($1, nil)
364
394
  when ''
365
395
  else
@@ -35,19 +35,9 @@ module When
35
35
  end
36
36
 
37
37
  #
38
- # 暦注要素のひな形クラス
38
+ # 暦注要素であることを示す
39
39
  #
40
- # @private
41
- class NoteElement < When::BasicTypes::Object
42
- #
43
- # _m17n_form のための要素生成
44
- #
45
- # @param [Hash] options 下記のとおり
46
- # @option options [Symbol] :method :to_m17n なら label を返す、その他は When::Parts::Resource#to_h 参照
47
- #
48
- def _to_hash_value(options={})
49
- options[:method] == :to_m17n ? label : super
50
- end
40
+ module NoteElement
51
41
  end
52
42
 
53
43
  #
@@ -441,7 +431,7 @@ module When
441
431
  nobj = note_objects[note]
442
432
  case notes[note]
443
433
  when nil, false ; {}
444
- when Hash ; {:note=>nobj.label}.merge(notes[note])
434
+ when Hash ; {:note=>nobj}.merge(notes[note])
445
435
  else
446
436
  if nobj.respond_to?(:to_note_hash)
447
437
  nobj.to_note_hash(notes[note], dates)
@@ -476,6 +466,7 @@ module When
476
466
  arg, method = $1, $2 if (arg =~ /\A(.+)#([_A-Z0-9]+)\z/i)
477
467
  obj = When.Resource(arg, prefix)
478
468
  obj = obj.copy(method) if method
469
+ obj.extend NoteElement
479
470
  obj
480
471
  when Array
481
472
  _to_iri(arg, prefix)
@@ -608,6 +599,20 @@ module When
608
599
  root.send(When::Coordinates::PRECISION_NAME[index].downcase, dates)
609
600
  end
610
601
 
602
+ #
603
+ # イベントの標準的な間隔を返す
604
+ #
605
+ # @param [String] parameter 座標の分子と分母("#{ num }/#{ den }" の形式)
606
+ #
607
+ # @return [When::TM::IntervalLength]
608
+ #
609
+ # @private
610
+ def event_delta(parameter=nil)
611
+ return @delta unless parameter
612
+ num, den = parameter.kind_of?(String) ? parameter.split(/\//, 2) : parameter
613
+ When::TM::IntervalLength.new([(den || @den).to_f,1].max*0.9, 'day')
614
+ end
615
+
611
616
  #
612
617
  # イベントを取得する Enumerator
613
618
  #
@@ -419,7 +419,7 @@ module When::CalendarTypes
419
419
  #
420
420
  def _length(date)
421
421
  y, m = date
422
- if (m)
422
+ if m
423
423
  # 指定した月に含まれる日の数を返します。
424
424
  return @unit[2] if @unit[2]
425
425
  rule = _rule(_key([y]))
@@ -443,7 +443,7 @@ module When::CalendarTypes
443
443
  # rule_table
444
444
  # @rule_table = @rule_table.dup
445
445
  @rule_table = {'T' => {'Rule' => @rule_table }} if @rule_table.kind_of?(Array)
446
- @_m_cash_ = {}
446
+ @_m_cash_ = Hash.new {|hash,key| hash[key]={}}
447
447
  @_m_cash_["_rule"] = @rule_table
448
448
 
449
449
  # unit length
@@ -497,8 +497,6 @@ module When::CalendarTypes
497
497
  n_sdn = (@_m_cash_["_sdn"][n_key] ||= _sdn_(n_date))
498
498
  key = (n_sdn - c_sdn).to_i
499
499
  rule = (@_m_cash_["_rule"][key] ||= _rule_(key))
500
- @_m_cash_["_key"] ||= {}
501
- @_m_cash_["_ids"] ||= {}
502
500
  @_m_cash_["_key"][c_key] ||= key
503
501
  @_m_cash_["_ids"][c_key] ||= rule['IDs']
504
502
  return c_sdn
@@ -772,8 +770,6 @@ module When::CalendarTypes
772
770
  count, year = c_date[0].divmod(root_rule['Years'])
773
771
  key, dd, mm = root_rule['Rule'][year]
774
772
  rule = (@_m_cash_["_rule"][key] ||= _rule_(key))
775
- @_m_cash_["_key"] ||= {}
776
- @_m_cash_["_ids"] ||= {}
777
773
  @_m_cash_["_key"][c_key] ||= key
778
774
  @_m_cash_["_ids"][c_key] ||= rule['IDs']
779
775
  @_m_cash_["_sdn"][c_key] ||= @origin_of_LSC + dd + count * root_rule['Days']
@@ -1027,8 +1023,6 @@ module When::CalendarTypes
1027
1023
  sdn, y, key = _read_period(@entry_key,
1028
1024
  'Years', value,
1029
1025
  'Days', @origin_of_LSC + count * root_rule['Days'])
1030
- @_m_cash_["_key"] ||= {}
1031
- @_m_cash_["_ids"] ||= {}
1032
1026
  @_m_cash_["_key"][c_key] ||= key
1033
1027
  @_m_cash_["_ids"][c_key] ||= @_m_cash_["_rule"][key]['IDs']
1034
1028
  @_m_cash_["_sdn"][c_key] ||= sdn
@@ -1424,7 +1418,7 @@ module When::CalendarTypes
1424
1418
  if m
1425
1419
  # 指定した月に含まれる日の数を返します。
1426
1420
  m += _new_year_month(+y)
1427
- _new_month(m+1) - _new_month(m)
1421
+ _new_month(+m+1) - _new_month(+m)
1428
1422
  else
1429
1423
  # 指定した年に含まれる月の数を返します。
1430
1424
  _ids([y]).length
@@ -26,14 +26,15 @@ module When::Coordinates
26
26
  #
27
27
  # @param [String] src 60進法で表した方向付きの数値
28
28
  # @param [String] dir 方向 ('NS' または 'EW')
29
+ # @param [Numeric] degree 角度の単位 (1 => 1度, 225=> 1/225 度)
29
30
  #
30
31
  # @return [Numeric] 10進変換した数値 (src が nil なら0.0を、Numeric なら 225*src を返す)
31
32
  #
32
- def self.to_deg_225(src, dir)
33
+ def self.to_deg_225(src, dir, degree=Spatial::DEGREE)
33
34
  case src
34
35
  when String
35
36
  src = src.gsub(/_+/,'').gsub(/@/, '.')
36
- return src.to_r * Spatial::DEGREE if (src =~ /E[-+]/ || src !~ MATCH[dir])
37
+ return src.to_r * degree if (src =~ /E[-+]/ || src !~ MATCH[dir])
37
38
  sign = ($1 == dir[1..1]) ? -1 : +1
38
39
  value = src.gsub(MATCH[dir], '').strip
39
40
  if ((value + "00000") =~ /\A(\d+)\.(\d{2})(\d{2})(\d+)\z/)
@@ -42,13 +43,13 @@ module When::Coordinates
42
43
  else
43
44
  deg, min, sec = value.split(/[^\d.]+/)
44
45
  end
45
- return sign * (deg.to_i * Spatial::DEGREE +
46
- (min||0).to_f * (Spatial::DEGREE/60.0) +
47
- (sec||0).to_f * (Spatial::DEGREE/3600.0))
46
+ return sign * (deg.to_i * degree +
47
+ (min||0).to_f * (degree/60.0) +
48
+ (sec||0).to_f * (degree/3600.0))
48
49
  when NilClass
49
50
  0.0
50
51
  when Numeric
51
- src * Spatial::DEGREE
52
+ src * degree
52
53
  else
53
54
  raise TypeError, "Invalid Location Type"
54
55
  end
@@ -121,13 +122,14 @@ module When::Coordinates
121
122
  else ; return nil
122
123
  end
123
124
 
124
- day, shift = day.split(':', 2)
125
+ day, shift = day =~ /\A([-+\d]+)(.+)/ ? [$2, $1] : day.split(':', 2)
125
126
  residue = day.split('&').inject(nil) {|res,d|
126
127
  r = _day_of_week(d.strip, dow)
127
128
  return nil unless r
128
129
  res ? res & r : r
129
130
  }
130
131
  return residue unless shift
132
+ shift << '1' unless shift =~ /\d/
131
133
  shift = shift.to_i
132
134
  shift -= 1 if shift > 0
133
135
  residue >> shift
@@ -238,6 +240,13 @@ module When::Coordinates
238
240
  attr_accessor :carry
239
241
  protected :carry=
240
242
 
243
+ # 周期分の補正の有無
244
+ #
245
+ # @return [Boolean]
246
+ #
247
+ attr_accessor :shifted
248
+ protected :shifted=
249
+
241
250
  # 単位
242
251
  #
243
252
  # @return [Hash] { String=>Numeric }
@@ -346,7 +355,9 @@ module When::Coordinates
346
355
  # @return [When::Coordinates::Residue]
347
356
  #
348
357
  def >>(other)
349
- return self.class.new(@remainder, @divisor, @carry+other, @units)
358
+ result = self.class.new(@remainder, @divisor, @carry+other, @units)
359
+ result.shifted = true
360
+ result
350
361
  end
351
362
 
352
363
  # carryの減算
@@ -356,7 +367,9 @@ module When::Coordinates
356
367
  # @return [When::Coordinates::Residue]
357
368
  #
358
369
  def <<(other)
359
- return self.class.new(@remainder, @divisor, @carry-other, @units)
370
+ result = self.class.new(@remainder, @divisor, @carry-other, @units)
371
+ result.shifted = true
372
+ result
360
373
  end
361
374
 
362
375
  # 剰余類の共通集合
@@ -488,6 +501,7 @@ module When::Coordinates
488
501
  raise RangeError, "Divisor shoud be Positive Numeric" if (@divisor <= 0)
489
502
  carry, @remainder = @remainder.divmod(@divisor)
490
503
  @carry += carry
504
+ @shifted = @carry != 0
491
505
  end
492
506
 
493
507
  private
@@ -1243,370 +1257,6 @@ module When::Coordinates
1243
1257
  end
1244
1258
  end
1245
1259
 
1246
- #
1247
- # 空間位置
1248
- #
1249
- class Spatial < When::BasicTypes::Object
1250
-
1251
- LabelProperty = 'label'
1252
-
1253
- include When::Ephemeris
1254
-
1255
- require 'when_exe/ephemeris/eclipse'
1256
-
1257
- class << self
1258
- # When::Coordinates::Spatial のグローバルな設定を行う
1259
- #
1260
- # @param [When::Coordinates::Spatial, String] location デフォルトの空間位置を使用する場合、指定する
1261
- #
1262
- # @return [void]
1263
- #
1264
- # @note
1265
- # 本メソッドでマルチスレッド対応の管理変数の初期化を行っている。
1266
- # このため、本メソッド自体はスレッドセーフでない。
1267
- #
1268
- def _setup_(location=nil)
1269
- @_lock_ = Mutex.new if When.multi_thread
1270
- @_pool = {}
1271
- @default_location = location
1272
- end
1273
-
1274
- # デフォルトの空間位置
1275
- #
1276
- # @param [When::Coordinates::Spatial, String] local デフォルトの空間位置
1277
- #
1278
- # @return [When::Coordinates::Spatial, String]
1279
- #
1280
- # @note
1281
- # @default_locationは、原則、ライブラリ立ち上げ時に _setup_ で初期化する。
1282
- # 以降、@default_locationに代入を行っても、すでに生成した When::TM::TemporalPosition 等には反映されない。
1283
- #
1284
- def default_location=(local)
1285
- if @_pool
1286
- @default_location = local
1287
- else
1288
- _setup_(local)
1289
- end
1290
- end
1291
-
1292
- # 設定情報を取得する
1293
- #
1294
- # @return [Hash] 設定情報
1295
- #
1296
- def _setup_info
1297
- {:location => @default_location}
1298
- end
1299
-
1300
- # デフォルトの空間位置を読みだす
1301
- #
1302
- # @return [When::Coordinates::Spatial]
1303
- #
1304
- def default_location
1305
- _default_location[1]
1306
- end
1307
-
1308
- # デフォルトの空間位置が When::TM::Clock のローカルタイムから生成されたか?
1309
- #
1310
- # @return [true, false]
1311
- #
1312
- def is_default_location_derived?
1313
- location = _default_location
1314
- location[0] && location[1]
1315
- end
1316
-
1317
- private
1318
-
1319
- # 共通処理
1320
- def _default_location
1321
- case @default_location
1322
- when nil ;
1323
- when Array ; return @default_location unless @default_location[0]
1324
- when String ; return (@default_location = [false, When.Resource(@default_location)])
1325
- else ; return (@default_location = [false, @default_location])
1326
- end
1327
- timezone = When::TM::Clock.local_time
1328
- location = timezone.location if timezone.kind_of?(When::Parts::Timezone)
1329
- return [true, location]
1330
- end
1331
- end
1332
-
1333
- # @private
1334
- HashProperty = [:label, :longitude, :latitude, [:altitude, 0.0], [:datum, When::Ephemeris::Earth], :ref]
1335
-
1336
- # Degree / Internal Location Unit(16")
1337
- #
1338
- # (3600 を 2 の因数で割りつくした値を単位とする)
1339
- DEGREE = 225
1340
-
1341
- # 黄道座標 (ecliptic coordinate system)
1342
- ECLIPTIC = 0
1343
-
1344
- # 赤道座標 (equatorial coordinate system)
1345
- EQUATORIAL = 1
1346
-
1347
- # 赤道座標[時角] (equatorial coordinate system with hour angle)
1348
- EQUATORIAL_HA = 2
1349
-
1350
- # 地平座標 (horizontal coordinate system)
1351
- HORIZONTAL = 3
1352
-
1353
- # 惑星中心の高度
1354
- CENTER = :center
1355
-
1356
- # 北緯を正とする緯度 / 16秒
1357
- #
1358
- # @return [Numeric]
1359
- #
1360
- attr_reader :lat
1361
-
1362
- # 東経を正とする経度 / 16秒
1363
- #
1364
- # @return [Numeric]
1365
- #
1366
- attr_reader :long
1367
-
1368
- # 高度 / m
1369
- #
1370
- # @return [Numeric]
1371
- # @return [:Center] 天体の中心の場合
1372
- #
1373
- attr_reader :alt
1374
- alias :altitude :alt
1375
-
1376
- # 座標系
1377
- #
1378
- # @return [When::Ephemeris::Datum]
1379
- #
1380
- attr_reader :datum
1381
-
1382
- # 参照
1383
- #
1384
- # @return [String] URI
1385
- #
1386
- attr_reader :ref
1387
-
1388
- # 時間帯(オプショナル)
1389
- #
1390
- # @return [TZInfo::CountryTimezone]
1391
- #
1392
- # TZInfoライブラリから経緯度を取得して使用する
1393
- #
1394
- attr_reader :tz
1395
-
1396
- # 緯度文字列
1397
- #
1398
- # @param [Integer] round 秒の小数点以下最大桁数
1399
- #
1400
- # @return [String] 緯度文字列(DD.MMSSsss[NS])
1401
- #
1402
- def lat_s
1403
- When::Coordinates.to_dms(lat / When::Coordinates::Spatial::DEGREE, 'NS', round=6)
1404
- end
1405
- alias :latitude :lat_s
1406
-
1407
- # 経度文字列
1408
- #
1409
- # @param [Integer] round 秒の小数点以下最大桁数
1410
- #
1411
- # @return [String] 経度文字列(DDD.MMSSsss[EW])
1412
- #
1413
- def long_s
1414
- When::Coordinates.to_dms(long / When::Coordinates::Spatial::DEGREE, 'EW', round=6)
1415
- end
1416
- alias :longitude :long_s
1417
-
1418
- # 高度 / m
1419
- #
1420
- # @return [Numeric]
1421
- # @return [:Center] 天体の中心の場合
1422
- #
1423
- attr_reader :alt
1424
-
1425
- # 観測地の地心距離 / kmを返します。
1426
- #
1427
- # @return [Numeric]
1428
- #
1429
- def obserber_distance
1430
- l = PI / (90 * DEGREE) * @lat
1431
- @datum.surface_radius * (@datum.shape[0]+@datum.shape[1]*cos(l)+@datum.shape[2]*cos(2*l))
1432
- end
1433
-
1434
- # 観測地での‘大地’の視半径
1435
- #
1436
- # @return [Numeric]
1437
- #
1438
- def horizon
1439
- # 地面以下なら 90度とみなす
1440
- return 0.25 if @alt == :Center || @alt <= 0
1441
-
1442
- # 観測地の地心距離 / m
1443
- r = obserber_distance * 1000.0
1444
-
1445
- # 大気効果
1446
- air_effect = @datum.air[1] * @alt / (@datum.air[2] * @alt + r)
1447
-
1448
- # ‘大地’の視半径
1449
- asin((1.0+air_effect) * r / (r+@alt)) / CIRCLE
1450
- end
1451
-
1452
- # 観測地の地方恒星時 / 時を返します。
1453
- #
1454
- # @param [Numeric] t ユリウス日(Terrestrial Time)
1455
- # @param [When::TM::TemporalPosition] t
1456
- #
1457
- # @return [Numeric]
1458
- #
1459
- def local_sidereal_time(t)
1460
- t = +t
1461
- c = julian_century_from_2000(t)
1462
- result = @datum.sid[0] + c * (@datum.sid[1] + c * @datum.sid[2]) + @long / (15.0 * DEGREE)
1463
- result += (cosc(obl(c)) * delta_p(c) +
1464
- (t-When::TimeStandard.delta_t_observed(t)/86400+0.5) % 1) * 24 if @datum.kind_of?(Earth)
1465
- result
1466
- end
1467
-
1468
- # 観測地の日心三次元座標(黄道座標)
1469
- #
1470
- # @param [Numeric] t ユリウス日(Terrestrial Time)
1471
- # @param [When::TM::TemporalPosition] t
1472
- #
1473
- # @return [Numeric]
1474
- #
1475
- def _coords(t)
1476
- t = +t
1477
- @datum._coords(t) + _coords_diff(t)
1478
- end
1479
-
1480
- private
1481
-
1482
- # 要素の正規化
1483
- def _normalize(args=[], options={})
1484
-
1485
- # 同一視
1486
- @long ||= @longitude
1487
- @lat ||= @latitude
1488
- @alt ||= @altitude
1489
-
1490
- # 時間帯による指定
1491
- @tz = When::Parts::Timezone.tz_info[@tz] if @tz.kind_of?(String)
1492
- if @tz
1493
- @label ||= When.m17n(@tz.identifier)
1494
- @long ||= @tz.longitude
1495
- @lat ||= @tz.latitude
1496
- end
1497
-
1498
- # データの整形
1499
- @label = When::BasicTypes::M17n.new(@label) if @label.kind_of?(Hash)
1500
- @long = When::Coordinates.to_deg_225(@long, 'EW') if @long
1501
- @lat = When::Coordinates.to_deg_225(@lat, 'NS') if @lat
1502
- @datum = When.Resource(@datum || 'Earth', '_ep:')
1503
- @long ||= 0.0
1504
- @lat ||= 0.0
1505
- @alt =
1506
- case @alt
1507
- when String ; @alt.gsub(/@/, '.').to_f
1508
- when Numeric ; @alt.to_f
1509
- when Symbol ; @alt
1510
- else ; 0.0
1511
- end
1512
-
1513
- # 日月食用作業変数
1514
- @mean = When.Resource(@mean || '_ep:Formula?formula=1L')
1515
- @ecls = {}
1516
- end
1517
-
1518
- # 観測地の惑星中心を原点とする三次元座標
1519
- #
1520
- # @param [Numeric] t ユリウス日(Terrestrial Time)
1521
- # @param [When::TM::TemporalPosition] t
1522
- # @param [Integer] system : 座標系
1523
- # [ ECLIPTIC = 黄道座標 ]
1524
- # [ EQUATORIAL = 赤道座標 ]
1525
- # [ EQUATORIAL_HA = 赤道座標[時角] ]
1526
- # [ HORIZONTAL = 地平座標 ]
1527
- #
1528
- def _coords_diff(t, system=ECLIPTIC)
1529
- return Coords.polar(0,0,0) if alt == :Center
1530
- t = +t
1531
- lat = @lat.to_f / DEGREE
1532
- coords = Coords.polar(
1533
- local_sidereal_time(t) / 24.0,
1534
- (lat + @datum.shape[3] * sind(2*lat)) / 360.0,
1535
- (obserber_distance + @alt/1000.0) / AU)
1536
- case system
1537
- when ECLIPTIC ; coords.r_to_y(t, @datum)
1538
- when EQUATORIAL ; coords
1539
- when EQUATORIAL_HA ; coords.r_to_rh(t, self)
1540
- when HORIZONTAL ; coords.r_to_h(t, self)
1541
- end
1542
- end
1543
-
1544
- # その他のメソッド
1545
- # When::Coordinates::Spatial で定義されていないメソッドは
1546
- # 処理を @datum (type: When::Ephemeris::Datum) に委譲する
1547
- #
1548
- def method_missing(name, *args, &block)
1549
- self.class.module_eval %Q{
1550
- def #{name}(*args, &block)
1551
- @datum.send("#{name}", *args, &block)
1552
- end
1553
- } unless When::Parts::MethodCash.escape(name)
1554
- @datum.send(name, *args, &block)
1555
- end
1556
-
1557
- # @private
1558
- module Normalize
1559
-
1560
- private
1561
-
1562
- # 位置情報
1563
- #
1564
- # @return [When::Coordinates::Spatial]
1565
- #
1566
- #attr_reader :location
1567
-
1568
- # 日時要素の境界オブジェクト
1569
- #
1570
- # @return [When::Coordinates::Border]
1571
- #
1572
- #attr_reader :border
1573
-
1574
- # 境界計算用の計算オブジェクト
1575
- #
1576
- # @return [When::Ephemeris::Formula]
1577
- #
1578
- #attr_reader :formula
1579
-
1580
- #
1581
- # Temporal Module の Spatial Parts の初期化
1582
- #
1583
- def _normalize_spatial
1584
-
1585
- # Location
1586
- if (@location||@long||@lat||@alt).kind_of?(String)
1587
- @location ||= "_l:long=#{@long||0}&lat=#{@lat||0}&alt=#{@alt||0}"
1588
- @location = When.Resource(@location)
1589
- end
1590
- @location ||= @tz_prop.location if @tz_prop
1591
-
1592
- # Border
1593
- @border = When.Border(@border) if @border.kind_of?(String)
1594
-
1595
- # Formula
1596
- instance_eval('class << self; attr_reader :formula; end') if @location && @border
1597
- if respond_to?(:formula)
1598
- extend When::Ephemeris::Formula::ForwardedFormula
1599
- unless @formula
1600
- options = {:formula => kind_of?(When::CalendarTypes::SolarYearTableBased) ? '1S' : '1L'}
1601
- options[:location] = @location if @location
1602
- @formula = When::Ephemeris::Formula.new(options)
1603
- end
1604
- @formula = When.Resource(Array(@formula), '_ep:')
1605
- end
1606
- end
1607
- end
1608
- end
1609
-
1610
1260
  #
1611
1261
  # 暦座標を扱う処理をまとめたモジュール
1612
1262
  #