when_exe 0.4.2 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (144) hide show
  1. checksums.yaml +5 -5
  2. data/LICENSE.ja.txt +8 -21
  3. data/LICENSE.txt +5 -27
  4. data/README.md +25 -79
  5. data/bin/.pryrc +9 -0
  6. data/bin/make_ttl.rb +3 -2
  7. data/bin/make_ttl.rb.config +3 -3
  8. data/lib/when_exe.rb +101 -5
  9. data/lib/when_exe/basictypes.rb +47 -16
  10. data/lib/when_exe/calendarnote.rb +27 -18
  11. data/lib/when_exe/calendartypes.rb +12 -50
  12. data/lib/when_exe/coordinates.rb +37 -391
  13. data/lib/when_exe/ephemeris.rb +53 -14
  14. data/lib/when_exe/ephemeris/eclipse.rb +8 -8
  15. data/lib/when_exe/ephemeris/moon.rb +333 -333
  16. data/lib/when_exe/ephemeris/notes.rb +29 -17
  17. data/lib/when_exe/ephemeris/phase_table.rb +825 -0
  18. data/lib/when_exe/ephemeris/term_table.rb +603 -0
  19. data/lib/when_exe/events.rb +1888 -0
  20. data/lib/when_exe/google_api.rb +26 -31
  21. data/lib/when_exe/icalendar.rb +129 -12
  22. data/lib/when_exe/inspect.rb +5 -5
  23. data/lib/when_exe/linkeddata.rb +43 -23
  24. data/lib/when_exe/locales/akt.rb +63 -0
  25. data/lib/when_exe/locales/encoding_conversion.rb +134 -134
  26. data/lib/when_exe/locales/iast.rb +90 -90
  27. data/lib/when_exe/locales/locale.rb +88 -18
  28. data/lib/when_exe/locales/transliteration_table.rb +62 -62
  29. data/lib/when_exe/mini_application.rb +14 -8
  30. data/lib/when_exe/namespace.rb +42 -0
  31. data/lib/when_exe/parts/enumerator.rb +16 -5
  32. data/lib/when_exe/parts/geometric_complex.rb +52 -2
  33. data/lib/when_exe/parts/method_cash.rb +229 -224
  34. data/lib/when_exe/parts/resource.rb +65 -35
  35. data/lib/when_exe/parts/timezone.rb +25 -34
  36. data/lib/when_exe/region/balinese.rb +5 -3
  37. data/lib/when_exe/region/chinese.rb +39 -11
  38. data/lib/when_exe/region/chinese/calendars.rb +1016 -1016
  39. data/lib/when_exe/region/chinese/epochs.rb +7 -7
  40. data/lib/when_exe/region/chinese/notes.rb +3 -3
  41. data/lib/when_exe/region/chinese/twins.rb +134 -11
  42. data/lib/when_exe/region/dee.rb +4 -4
  43. data/lib/when_exe/region/discordian.rb +1 -1
  44. data/lib/when_exe/region/geologicalage.rb +139 -128
  45. data/lib/when_exe/region/hanke_henry.rb +4 -4
  46. data/lib/when_exe/region/indian.rb +77 -8
  47. data/lib/when_exe/region/international_fixed.rb +3 -3
  48. data/lib/when_exe/region/islamic.rb +1 -1
  49. data/lib/when_exe/region/japanese.rb +12 -8
  50. data/lib/when_exe/region/japanese/calendars.rb +397 -397
  51. data/lib/when_exe/region/japanese/eclipses.rb +1194 -1194
  52. data/lib/when_exe/region/japanese/epochs.rb +8 -4
  53. data/lib/when_exe/region/japanese/location.rb +93 -0
  54. data/lib/when_exe/region/japanese/nihon_shoki.rb +70 -70
  55. data/lib/when_exe/region/japanese/notes.rb +57 -18
  56. data/lib/when_exe/region/japanese/residues.rb +33 -11
  57. data/lib/when_exe/region/japanese/twins.rb +27 -14
  58. data/lib/when_exe/region/japanese/weeks.rb +7 -7
  59. data/lib/when_exe/region/korean.rb +384 -384
  60. data/lib/when_exe/region/location.rb +40 -0
  61. data/lib/when_exe/region/martian.rb +1 -1
  62. data/lib/when_exe/region/mayan.rb +2 -2
  63. data/lib/when_exe/region/roman.rb +2 -2
  64. data/lib/when_exe/region/ryukyu.rb +101 -101
  65. data/lib/when_exe/region/saudi_arabian.rb +57 -0
  66. data/lib/when_exe/region/shire.rb +1 -1
  67. data/lib/when_exe/region/world.rb +3 -3
  68. data/lib/when_exe/region/zoroastrian.rb +1 -1
  69. data/lib/when_exe/spatial.rb +611 -0
  70. data/lib/when_exe/timestandard.rb +9 -7
  71. data/lib/when_exe/tmobjects.rb +34 -2
  72. data/lib/when_exe/tmposition.rb +225 -1322
  73. data/lib/when_exe/tmptypes.rb +1279 -0
  74. data/lib/when_exe/tmreference.rb +42 -7
  75. data/lib/when_exe/version.rb +3 -3
  76. data/test/events/example-datasets +6 -0
  77. data/test/events/history-dataset.csv +22 -0
  78. data/test/events/japanese-holiday-index.csv +28 -0
  79. data/test/events/japanese-holiday.csv +94 -0
  80. data/test/events/japanese-holiday.ttl +948 -0
  81. data/test/events/make_events_ttl.rb +18 -0
  82. data/test/events/mori_wikichoshi.csv +14 -0
  83. data/test/events/ndl_koyomi.csv +220 -0
  84. data/test/events/ndl_koyomi_index.csv +44 -0
  85. data/test/events/primeminister-dataset.csv +19 -0
  86. data/test/events/shogun-dataset.csv +22 -0
  87. data/test/events/test-history-dataset-edge-sparql.csv +26 -0
  88. data/test/events/test-history-dataset-edge.csv +27 -0
  89. data/test/events/test-history-dataset-sparql.csv +22 -0
  90. data/test/events/test-history-dataset.csv +23 -0
  91. data/test/events/test-history-events-edge.ttl +89 -0
  92. data/test/events/test-history-events.csv +6 -0
  93. data/test/examples/JapanHolidays.ics +2 -2
  94. data/test/examples/JapanHolidaysRFC6350.ics +3 -3
  95. data/test/examples/Residue.m17n +2 -2
  96. data/test/examples/Spatial.m17n +3 -3
  97. data/test/examples/Terms.m17n +3 -3
  98. data/test/scripts/8.ext.rb +6 -6
  99. data/test/scripts/8.rb +6 -6
  100. data/test/scripts/geometric_complex.rb +41 -41
  101. data/test/scripts/korea.rb +59 -59
  102. data/test/scripts/thai.rb +36 -36
  103. data/test/test.rb +6 -0
  104. data/test/test/basictypes.rb +431 -431
  105. data/test/test/calendarnote.rb +86 -86
  106. data/test/test/calendartypes.rb +97 -97
  107. data/test/test/coordinates.rb +399 -397
  108. data/test/test/ephemeris.rb +115 -115
  109. data/test/test/ephemeris/moon.rb +14 -14
  110. data/test/test/ephemeris/planets.rb +14 -14
  111. data/test/test/ephemeris/sun.rb +14 -14
  112. data/test/test/events.rb +32 -0
  113. data/test/test/google_api.rb +45 -32
  114. data/test/test/inspect.rb +153 -153
  115. data/test/test/parts.rb +488 -488
  116. data/test/test/region/armenian.rb +20 -20
  117. data/test/test/region/bahai.rb +58 -58
  118. data/test/test/region/balinese.rb +34 -34
  119. data/test/test/region/chinese.rb +229 -229
  120. data/test/test/region/christian.rb +226 -226
  121. data/test/test/region/coptic.rb +27 -27
  122. data/test/test/region/discordian.rb +20 -20
  123. data/test/test/region/french.rb +33 -33
  124. data/test/test/region/geologicalage.rb +17 -17
  125. data/test/test/region/indian.rb +14 -1
  126. data/test/test/region/iran.rb +54 -54
  127. data/test/test/region/islamic.rb +64 -54
  128. data/test/test/region/japanese.rb +281 -261
  129. data/test/test/region/jewish.rb +63 -63
  130. data/test/test/region/m17n.rb +21 -21
  131. data/test/test/region/mayan.rb +17 -16
  132. data/test/test/region/reforms.rb +2 -2
  133. data/test/test/region/residue.rb +7 -7
  134. data/test/test/region/shire.rb +58 -58
  135. data/test/test/region/swedish.rb +45 -45
  136. data/test/test/region/thai.rb +116 -116
  137. data/test/test/region/tibetan.rb +30 -30
  138. data/test/test/region/vietnamese.rb +102 -102
  139. data/test/test/region/zoroastrian.rb +58 -58
  140. data/test/test/timestandard.rb +81 -81
  141. data/test/test/tmobjects.rb +402 -402
  142. data/test/test/tmposition.rb +66 -4
  143. data/test/test/tmreference.rb +157 -157
  144. metadata +36 -93
@@ -1,6 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  =begin
3
- Copyright (C) 2011-2015 Takashi SUGA
3
+ Copyright (C) 2011-2021 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
@@ -29,7 +29,7 @@ module When
29
29
  # @option options [Integer] :extra_year_digits ISO8601拡大表記のための年の構成要素拡大桁数(省略時 1桁)
30
30
  # @option options [Integer] :ordinal_date_digits ISO8601拡大表記の年内通日の桁数(省略時 3桁)
31
31
  #
32
- # @return [Array] format, date, time, clock, era
32
+ # @return [Array] format, date, time, clock, era, r
33
33
  #
34
34
  # format (Symbol, nil)
35
35
  # nil 通常形式
@@ -45,11 +45,14 @@ module When
45
45
  #
46
46
  # era (String, Array<String, Integer>) 年号(Integerは0年に対応する通年)
47
47
  #
48
+ # r (Hash<Integer=>When::Coordinates::Residue or String>) 剰余類などの指定
49
+ #
48
50
  def _to_array(date_time, options={})
49
51
  raise TypeError, "Argument is not ISO 8601 String" unless date_time.kind_of?(String)
50
52
  if options[:abbr].kind_of?(When::TimeValue)
51
53
  options[:abbr] = ((options[:frame]||When::Gregorian) ^ options[:abbr]).cal_date
52
54
  end
55
+ date_time = _parse(date_time, options.delete(:parse), options[:abbr]||[]) if options[:parse]
53
56
  date_time = date_time.gsub(/[_\s]+([\d])/, '\1')
54
57
  begin
55
58
  return _to_array_basic(date_time, options)
@@ -106,7 +109,6 @@ module When
106
109
  # extended date & time format (JIS X0301)
107
110
  when /\A((.+::)?(\[[^\]]+\]|[^-+\d{]+))(([-+*&%@!>=<?\dW.\(\)]|\{.+?\})+)?(?:(T([:*=.,\d]+)?)([A-Z]+(\?.+)?|[-+][:\d]+)?)?\z/
108
111
  era, parent, child, d, v, t, time, clock = $~[1..8]
109
- d0 = d
110
112
  d, r = _split_residue(d, options[:abbr]) if d =~ /\{/
111
113
  format, date, era = Date._to_array_extended_X0301(d, era, options)
112
114
  era ||= options[:era_name] if d =~ /\./
@@ -126,19 +128,48 @@ module When
126
128
 
127
129
  # 剰余類の指定を置き換える
128
130
  def _split_residue(d, abbr)
129
- abbr, = abbr
130
- residue = {}
131
+ abbr, = abbr
132
+ options = {}
131
133
  count = 0
132
134
  sign, d = d =~ /^-/ ? ['-', d[1..-1]] : ['', d]
133
135
  [sign + d.gsub(/[-+*&%@!>=<?.]|(\d)?\{(.+?)\}/) {|s|
134
136
  if $2
135
- residue[count] = $2
136
- count == 0 ? ($1 || abbr || 1) : $1
137
+ digit = $1
138
+ operation = $2.strip
139
+ residue = When.Residue(operation) unless operation =~ /[#,]|[^:][-+]/
140
+ options[count] = residue && residue.shifted ? residue : operation
141
+ count == 0 ? (digit || abbr || 1) : digit
137
142
  else
138
143
  count += 1
139
144
  s
140
145
  end
141
- }, residue]
146
+ }, options]
147
+ end
148
+
149
+ # 日付文字列を事前に変換する
150
+ def _parse(date_time, parse, abbr)
151
+ format, locale = parse
152
+ case format
153
+ when String, Hash
154
+ h = When::Locale._to_date_time_hash(date_time, format, locale)
155
+ date_time = (h[:wday] ? "%4d-%02d-01{%d&%s}" : "%4d-%02d-%02d") % [
156
+ h[:year] || abbr[0] || ::Date.today.year,
157
+ h[:mon] || abbr[1] || 1,
158
+ h[:mday] || abbr[2] || 1,
159
+ When::V::Event::DayOfWeek[h[:wday]||0]]
160
+ date_time << "T%02d:%02d:%02d" % [
161
+ h[:hour] || abbr[3] || 0,
162
+ h[:min] || abbr[4] || 0,
163
+ h[:sec] || abbr[5] || 0] if h[:hour]
164
+ date_time << When::TM::Clock.to_hms(h[:offset]) if h[:offset]
165
+ when Array
166
+ parse.each do |item|
167
+ item[2] ? date_time.gsub!(item[0], item[1]) :
168
+ item[1] ? date_time.sub!( item[0], item[1]) :
169
+ date_time.gsub!(When::Locale.const_get(item[0])) {|digit| When::Locale.k2a_digits(digit, true)}
170
+ end unless date_time =~ /\{/
171
+ end
172
+ date_time
142
173
  end
143
174
  end
144
175
  end
@@ -354,12 +385,12 @@ module When
354
385
  else
355
386
  tt = [0]
356
387
  end
357
- while time =~ /\A(\d{2}(?:\.\d+)?|-)([:*=])(.+)/
388
+ while time =~ /\A(\d{1,2}(?:\.\d+)?|-)([:*=])(.+)/
358
389
  time = $3
359
390
  tt << Coordinates::Pair._en_pair($1=='-' ? abbr.shift : $1, $2)
360
391
  end
361
392
  case time
362
- when /\A(\d{2}(\.\d+)?)\z/
393
+ when /\A(\d{1,2}(\.\d+)?)\z/
363
394
  tt << Coordinates::Pair._en_number($1, nil)
364
395
  when ''
365
396
  else
@@ -588,14 +619,14 @@ module When
588
619
  # prefix: - namespace 引数の指定により URI に展開する
589
620
  #
590
621
  # @example
591
- # M17n.new(['3月', 'fr:Mars=http://fr.wikipedia.org/wiki/Mars_(mois)', 'March'],
592
- # {'en_wikipedia'=>'http://en.wikipedia.org/wiki/',
593
- # 'ja_wikipedia'=>'http://ja.wikipedia.org/wiki/'},
622
+ # M17n.new(['3月', 'fr:Mars=https://fr.wikipedia.org/wiki/Mars_(mois)', 'March'],
623
+ # {'en_wikipedia'=>'https://en.wikipedia.org/wiki/',
624
+ # 'ja_wikipedia'=>'https://ja.wikipedia.org/wiki/'},
594
625
  # ['=ja_wikipedia:', '*en=en_wikipedia:']) を行うと、生成された M17n では、
595
626
  # @names = {'' =>'3月', 'fr'=>'Mars', 'en'=>'March'}
596
- # @namespace = {'' =>'http://ja.wikipedia.org/wiki/3%E6%9C%88',
597
- # 'fr'=>'http://fr.wikipedia.org/wiki/Mars_(mois)',
598
- # 'en'=>'http://en.wikipedia.org/wiki/March'}
627
+ # @namespace = {'' =>'https://ja.wikipedia.org/wiki/3%E6%9C%88',
628
+ # 'fr'=>'https://fr.wikipedia.org/wiki/Mars_(mois)',
629
+ # 'en'=>'https://en.wikipedia.org/wiki/March'}
599
630
  # となり、通常の String として振舞う場合は 'March' として振舞う
600
631
  #
601
632
  def initialize(*args)
@@ -1,6 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  =begin
3
- Copyright (C) 2011-2015 Takashi SUGA
3
+ Copyright (C) 2011-2021 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
@@ -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
  #
@@ -118,7 +108,7 @@ module When
118
108
  #
119
109
  # @return [Array] ハッシュ要素からなる配列(元の構造が配列であった場合)
120
110
  #
121
- # @note 引数 symbol が Integer の場合は添え字とみなして元の配列の要素を取り出す
111
+ # @note 引数 symbol が Symbol でも String でもない場合は添え字とみなして元の配列の要素を取り出す
122
112
  #
123
113
  def value(compact=true, symbol=:value)
124
114
  if kind_of?(Hash) && !key?(:note)
@@ -129,8 +119,12 @@ module When
129
119
  end
130
120
  else
131
121
  # Non-Persistent NotesContainer
132
- return _bless(slice(symbol)) if symbol.kind_of?(Integer)
133
- sliced = _dig(self) {|target| target.fetch(symbol, nil)}
122
+ case symbol
123
+ when Symbol, String
124
+ sliced = _dig(self) {|target| target.fetch(symbol, nil)}
125
+ else
126
+ return _bless(slice(symbol))
127
+ end
134
128
  end
135
129
  sliced = _bless(sliced)
136
130
  compact ? sliced.simplify : sliced
@@ -335,7 +329,7 @@ module When
335
329
  def notes(date, options={})
336
330
  dates, indices, notes, persistence, conditions, options = _parse_note(date, options)
337
331
  retrieved = NotesContainer.retrieve(persistence, date.to_i)
338
- return retrieved unless retrieved == false
332
+ return retrieved if retrieved
339
333
  NotesContainer.register(indices.map {|i|
340
334
  next [] unless i <= date.precision
341
335
  _note_values(dates, notes[i-1], _all_keys[i-1], _elements[i-1]) do |dates, focused_notes, notes_hash|
@@ -441,7 +435,7 @@ module When
441
435
  nobj = note_objects[note]
442
436
  case notes[note]
443
437
  when nil, false ; {}
444
- when Hash ; {:note=>nobj.label}.merge(notes[note])
438
+ when Hash ; {:note=>nobj}.merge(notes[note])
445
439
  else
446
440
  if nobj.respond_to?(:to_note_hash)
447
441
  nobj.to_note_hash(notes[note], dates)
@@ -476,6 +470,7 @@ module When
476
470
  arg, method = $1, $2 if (arg =~ /\A(.+)#([_A-Z0-9]+)\z/i)
477
471
  obj = When.Resource(arg, prefix)
478
472
  obj = obj.copy(method) if method
473
+ obj.extend NoteElement
479
474
  obj
480
475
  when Array
481
476
  _to_iri(arg, prefix)
@@ -608,6 +603,20 @@ module When
608
603
  root.send(When::Coordinates::PRECISION_NAME[index].downcase, dates)
609
604
  end
610
605
 
606
+ #
607
+ # イベントの標準的な間隔を返す
608
+ #
609
+ # @param [String] parameter 座標の分子と分母("#{ num }/#{ den }" の形式)
610
+ #
611
+ # @return [When::TM::IntervalLength]
612
+ #
613
+ # @private
614
+ def event_delta(parameter=nil)
615
+ return @delta unless parameter
616
+ num, den = parameter.kind_of?(String) ? parameter.split(/\//, 2) : parameter
617
+ When::TM::IntervalLength.new([(den || @den).to_f,1].max*0.9, 'day')
618
+ end
619
+
611
620
  #
612
621
  # イベントを取得する Enumerator
613
622
  #
@@ -1,6 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  =begin
3
- Copyright (C) 2011-2015 Takashi SUGA
3
+ Copyright (C) 2011-2021 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
@@ -73,33 +73,6 @@ module When::CalendarTypes
73
73
  #
74
74
  class LocalTime < UTC
75
75
 
76
- # 128秒単位の実数による参照事象の時刻
77
- #
78
- # Fraction time of the reference event
79
- #
80
- # @param [Integer] sdn 参照事象の通し番号
81
- #
82
- # @return [Numeric]
83
- #
84
- # T00:00:00Z からの参照事象の経過時間 / 128秒
85
- #
86
- def universal_time(sdn=nil)
87
- return super - @time_standard.localtime_difference unless sdn
88
- time = When::TM::JulianDate._d_to_t(sdn-0.5)
89
- @time_standard.to_dynamical_time(time) - When::TimeStandard.to_dynamical_time(time)
90
- end
91
-
92
- # この時法の時刻を128秒単位の実数に変換する
93
- #
94
- # @param [Array<Numeric>] clk_time
95
- # @param [Integer] sdn 参照事象の通し番号(ダミー)
96
- #
97
- # @return [Numeric]
98
- #
99
- def to_local_time(clk_time, sdn=nil)
100
- super - universal_time(sdn)
101
- end
102
-
103
76
  #
104
77
  # Zone 名
105
78
  #
@@ -108,14 +81,6 @@ module When::CalendarTypes
108
81
  def zone
109
82
  iri.split('/')[-1]
110
83
  end
111
-
112
- private
113
-
114
- # オブジェクトの正規化
115
- def _normalize(args=[], options={})
116
- @origin_of_LSC = - @time_standard.localtime_difference / When::TM::Duration::SECOND
117
- super
118
- end
119
84
  end
120
85
 
121
86
  #
@@ -419,7 +384,7 @@ module When::CalendarTypes
419
384
  #
420
385
  def _length(date)
421
386
  y, m = date
422
- if (m)
387
+ if m
423
388
  # 指定した月に含まれる日の数を返します。
424
389
  return @unit[2] if @unit[2]
425
390
  rule = _rule(_key([y]))
@@ -443,7 +408,7 @@ module When::CalendarTypes
443
408
  # rule_table
444
409
  # @rule_table = @rule_table.dup
445
410
  @rule_table = {'T' => {'Rule' => @rule_table }} if @rule_table.kind_of?(Array)
446
- @_m_cash_ = {}
411
+ @_m_cash_ = Hash.new {|hash,key| hash[key]={}}
447
412
  @_m_cash_["_rule"] = @rule_table
448
413
 
449
414
  # unit length
@@ -454,7 +419,7 @@ module When::CalendarTypes
454
419
 
455
420
  # mean month length
456
421
  if @entry_key
457
- ::Rational
422
+ Rational
458
423
  @mean_month = Rational(@rule_table[@entry_key]['Days'], @rule_table[@entry_key]['Months'])
459
424
  @mean_year = Rational(@rule_table[@entry_key]['Days'], @rule_table[@entry_key]['Years' ])
460
425
  end
@@ -497,8 +462,6 @@ module When::CalendarTypes
497
462
  n_sdn = (@_m_cash_["_sdn"][n_key] ||= _sdn_(n_date))
498
463
  key = (n_sdn - c_sdn).to_i
499
464
  rule = (@_m_cash_["_rule"][key] ||= _rule_(key))
500
- @_m_cash_["_key"] ||= {}
501
- @_m_cash_["_ids"] ||= {}
502
465
  @_m_cash_["_key"][c_key] ||= key
503
466
  @_m_cash_["_ids"][c_key] ||= rule['IDs']
504
467
  return c_sdn
@@ -646,7 +609,7 @@ module When::CalendarTypes
646
609
  difference.each_pair do |year, pattern|
647
610
  offset = year - hash['origin_of_MSC']
648
611
  hash['rule_table'][offset] =
649
- if pattern.kind_of?(Hash)
612
+ if pattern.kind_of?(Hash)
650
613
  rule = hash['rule_table'][offset].dup
651
614
  pattern.each_pair do |key,value|
652
615
  raise ArgumentError, "Can't patch \"#{rule}\" by {#{key}=>#{value}} at #{year}" unless rule.sub!(key,value)
@@ -772,8 +735,6 @@ module When::CalendarTypes
772
735
  count, year = c_date[0].divmod(root_rule['Years'])
773
736
  key, dd, mm = root_rule['Rule'][year]
774
737
  rule = (@_m_cash_["_rule"][key] ||= _rule_(key))
775
- @_m_cash_["_key"] ||= {}
776
- @_m_cash_["_ids"] ||= {}
777
738
  @_m_cash_["_key"][c_key] ||= key
778
739
  @_m_cash_["_ids"][c_key] ||= rule['IDs']
779
740
  @_m_cash_["_sdn"][c_key] ||= @origin_of_LSC + dd + count * root_rule['Days']
@@ -1027,8 +988,6 @@ module When::CalendarTypes
1027
988
  sdn, y, key = _read_period(@entry_key,
1028
989
  'Years', value,
1029
990
  'Days', @origin_of_LSC + count * root_rule['Days'])
1030
- @_m_cash_["_key"] ||= {}
1031
- @_m_cash_["_ids"] ||= {}
1032
991
  @_m_cash_["_key"][c_key] ||= key
1033
992
  @_m_cash_["_ids"][c_key] ||= @_m_cash_["_rule"][key]['IDs']
1034
993
  @_m_cash_["_sdn"][c_key] ||= sdn
@@ -1331,10 +1290,11 @@ module When::CalendarTypes
1331
1290
  #
1332
1291
  def _normalize(args=[], options={})
1333
1292
  @cycle_offset ||= -1.5
1334
- @formula ||= "Formula?formula=#{@months_in_year||12}S"
1293
+ @formula ||= (When::CalendarNote::LuniSolarPositions.table_off ?
1294
+ "Formula?formula=#{@months_in_year||12}S" : 'SolarFormulaWithTable')
1335
1295
  super
1336
1296
  end
1337
- end
1297
+ end
1338
1298
 
1339
1299
  # 月日の配当が月の位相によって決定される純太陰暦
1340
1300
  #
@@ -1424,7 +1384,7 @@ module When::CalendarTypes
1424
1384
  if m
1425
1385
  # 指定した月に含まれる日の数を返します。
1426
1386
  m += _new_year_month(+y)
1427
- _new_month(m+1) - _new_month(m)
1387
+ _new_month(+m+1) - _new_month(+m)
1428
1388
  else
1429
1389
  # 指定した年に含まれる月の数を返します。
1430
1390
  _ids([y]).length
@@ -1478,7 +1438,9 @@ module When::CalendarTypes
1478
1438
  # notes = to_a でデフォルトとして用いる暦注
1479
1439
  #
1480
1440
  def _normalize(args=[], options={})
1481
- @formula ||= ['Formula?formula=12S', 'Formula?formula=1L']
1441
+ @formula ||= (When::CalendarNote::LuniSolarPositions.table_off ?
1442
+ ['Formula?formula=12S', 'Formula?formula=1L'] :
1443
+ ['SolarFormulaWithTable','LunarFormulaWithTable'])
1482
1444
  super
1483
1445
  end
1484
1446
  end
@@ -1,6 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  =begin
3
- Copyright (C) 2011-2015 Takashi SUGA
3
+ Copyright (C) 2011-2021 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
@@ -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
@@ -919,8 +933,8 @@ module When::Coordinates
919
933
  when nil
920
934
  form += c
921
935
  else
922
- suffix = DL2[m17ns[i ? i.to_i : index]*0] || s if s
923
- form += t + ({nil=>'', '%'=>'%%'}[suffix] || suffix)
936
+ suffix = DL2[m17ns[i ? i.to_i : index] * 0] || s if s
937
+ form += t + ({nil=>'', '%'=>'%%'}[suffix] || suffix)
924
938
  index += t.length - t.gsub(/\*/,'').length + 1
925
939
  end
926
940
  form
@@ -933,14 +947,14 @@ module When::Coordinates
933
947
  #
934
948
  # @return [Numeric] 年番号,月番号,日番号など暦要素の幹となる部分
935
949
  #
936
- attr_accessor :trunk
950
+ attr_reader :trunk
937
951
 
938
952
  #
939
953
  # 暦要素の枝
940
954
  #
941
955
  # @return [Numeric] 暦要素のうち(閏であるかなど)幹で表現しきれない枝の部分
942
956
  #
943
- attr_accessor :branch
957
+ attr_reader :branch
944
958
 
945
959
  #
946
960
  # 暦要素の幹と枝の和
@@ -1096,6 +1110,15 @@ module When::Coordinates
1096
1110
  return @trunk.to_s + (@branch==0 ? zero : DL2[@branch])
1097
1111
  end
1098
1112
 
1113
+ # 整数化
1114
+ # Array の index 値を提供する場合に呼ばれる
1115
+ #
1116
+ # @return [Integer]
1117
+ #
1118
+ def to_i
1119
+ @sum.to_i
1120
+ end
1121
+
1099
1122
  # 強制型変換
1100
1123
  # @private
1101
1124
  def coerce(other)
@@ -1123,19 +1146,6 @@ module When::Coordinates
1123
1146
  @sum += @branch if (@trunk)
1124
1147
  end
1125
1148
  end
1126
-
1127
- # その他のメソッド
1128
- # When::Coordinates:Pair で定義されていないメソッドは
1129
- # 処理を @sum (type:Numeric) に委譲する
1130
- #
1131
- def method_missing(name, *args, &block)
1132
- self.class.module_eval %Q{
1133
- def #{name}(*args, &block)
1134
- @sum.send("#{name}", *args, &block)
1135
- end
1136
- } unless When::Parts::MethodCash.escape(name)
1137
- @sum.send(name, *args, &block)
1138
- end
1139
1149
  end
1140
1150
 
1141
1151
  # 暦座標値
@@ -1243,370 +1253,6 @@ module When::Coordinates
1243
1253
  end
1244
1254
  end
1245
1255
 
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
1256
  #
1611
1257
  # 暦座標を扱う処理をまとめたモジュール
1612
1258
  #