when_exe 0.3.6 → 0.3.7
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.
- checksums.yaml +7 -0
- data/README.md +171 -0
- data/lib/when_exe.rb +78 -47
- data/lib/when_exe/basictypes.rb +752 -747
- data/lib/when_exe/calendarnote.rb +805 -801
- data/lib/when_exe/calendartypes.rb +1583 -1531
- data/lib/when_exe/coordinates.rb +16 -15
- data/lib/when_exe/core/duration.rb +114 -110
- data/lib/when_exe/core/extension.rb +504 -504
- data/lib/when_exe/ephemeris.rb +1917 -1913
- data/lib/when_exe/ephemeris/moon.rb +333 -333
- data/lib/when_exe/ephemeris/notes.rb +389 -387
- data/lib/when_exe/ephemeris/planets.rb +585 -585
- data/lib/when_exe/ephemeris/sun.rb +214 -214
- data/lib/when_exe/googlecalendar.rb +144 -140
- data/lib/when_exe/icalendar.rb +1636 -1636
- data/lib/when_exe/inspect.rb +46 -22
- data/lib/when_exe/locales/akt.rb +176 -176
- data/lib/when_exe/locales/encoding_conversion.rb +134 -126
- data/lib/when_exe/locales/iast.rb +90 -90
- data/lib/when_exe/locales/locale.rb +750 -746
- data/lib/when_exe/locales/transliteration_table.rb +62 -62
- data/lib/when_exe/mini_application.rb +307 -305
- data/lib/when_exe/parts/enumerator.rb +2 -2
- data/lib/when_exe/parts/geometric_complex.rb +397 -397
- data/lib/when_exe/parts/method_cash.rb +224 -224
- data/lib/when_exe/parts/resource.rb +1069 -1071
- data/lib/when_exe/parts/timezone.rb +240 -230
- data/lib/when_exe/region/armenian.rb +56 -56
- data/lib/when_exe/region/babylonian.rb +405 -0
- data/lib/when_exe/region/bahai.rb +146 -146
- data/lib/when_exe/region/balinese.rb +622 -622
- data/lib/when_exe/region/chinese.rb +95 -25
- data/lib/when_exe/region/chinese/calendars.rb +1016 -1016
- data/lib/when_exe/region/chinese/epochs.rb +1 -1
- data/lib/when_exe/region/chinese/twins.rb +803 -795
- data/lib/when_exe/region/christian.rb +824 -824
- data/lib/when_exe/region/coptic.rb +106 -87
- data/lib/when_exe/region/discordian.rb +225 -225
- data/lib/when_exe/region/far_east.rb +188 -188
- data/lib/when_exe/region/french.rb +56 -56
- data/lib/when_exe/region/geologicalage.rb +639 -639
- data/lib/when_exe/region/goddess.rb +58 -58
- data/lib/when_exe/region/indian.rb +1254 -1251
- data/lib/when_exe/region/iranian.rb +8 -8
- data/lib/when_exe/region/islamic.rb +3 -3
- data/lib/when_exe/region/japanese.rb +93 -99
- data/lib/when_exe/region/japanese/calendars.rb +396 -397
- data/lib/when_exe/region/japanese/epochs.rb +26 -26
- data/lib/when_exe/region/japanese/nihon_shoki.rb +71 -71
- data/lib/when_exe/region/japanese/notes.rb +1383 -1386
- data/lib/when_exe/region/japanese/residues.rb +1306 -1306
- data/lib/when_exe/region/japanese/twins.rb +225 -225
- data/lib/when_exe/region/japanese/weeks.rb +112 -0
- data/lib/when_exe/region/javanese.rb +230 -230
- data/lib/when_exe/region/jewish.rb +126 -126
- data/lib/when_exe/region/korean.rb +378 -378
- data/lib/when_exe/region/m17n.rb +114 -113
- data/lib/when_exe/region/martian.rb +258 -255
- data/lib/when_exe/region/mayan.rb +32 -32
- data/lib/when_exe/region/residue.rb +89 -89
- data/lib/when_exe/region/roman.rb +36 -24
- data/lib/when_exe/region/ryukyu.rb +97 -97
- data/lib/when_exe/region/shire.rb +240 -240
- data/lib/when_exe/region/soviet.rb +209 -0
- data/lib/when_exe/region/symmetry.rb +50 -50
- data/lib/when_exe/region/thai.rb +336 -335
- data/lib/when_exe/region/tibetan.rb +316 -315
- data/lib/when_exe/region/vietnamese.rb +440 -439
- data/lib/when_exe/region/weekdate.rb +80 -80
- data/lib/when_exe/region/world.rb +175 -175
- data/lib/when_exe/region/yerm.rb +14 -14
- data/lib/when_exe/region/zoroastrian.rb +203 -203
- data/lib/when_exe/timestandard.rb +707 -681
- data/lib/when_exe/tmduration.rb +338 -330
- data/lib/when_exe/tmobjects.rb +1346 -1325
- data/lib/when_exe/tmposition.rb +2115 -2072
- data/lib/when_exe/tmreference.rb +1693 -1669
- data/lib/when_exe/version.rb +1 -1
- data/link_to_online_documents +1 -1
- data/test/examples/JapanHolidaysRFC6350.ics +1 -1
- data/test/test.rb +67 -61
- data/test/test/basictypes.rb +409 -409
- data/test/test/calendarnote.rb +86 -69
- data/test/test/calendartypes.rb +97 -97
- data/test/test/coordinates.rb +396 -396
- data/test/test/ephemeris.rb +83 -74
- data/test/test/ephemeris/moon.rb +14 -14
- data/test/test/ephemeris/planets.rb +14 -14
- data/test/test/ephemeris/sun.rb +14 -14
- data/test/test/googlecalendar.rb +194 -176
- data/test/test/icalendar.rb +867 -858
- data/test/test/inspect.rb +117 -117
- data/test/test/parts.rb +487 -487
- data/test/test/region/balinese.rb +34 -0
- data/test/test/region/chinese.rb +218 -206
- data/test/test/region/christian.rb +245 -245
- data/test/test/region/coptic.rb +27 -27
- data/test/test/region/french.rb +33 -33
- data/test/test/region/geologicalage.rb +17 -17
- data/test/test/region/indian.rb +57 -57
- data/test/test/region/iran.rb +54 -54
- data/test/test/region/islamic.rb +18 -18
- data/test/test/region/japanese.rb +237 -219
- data/test/test/region/jewish.rb +61 -61
- data/test/test/region/m17n.rb +184 -184
- data/test/test/region/mayan.rb +195 -195
- data/test/test/region/residue.rb +147 -139
- data/test/test/region/thai.rb +116 -116
- data/test/test/region/tibetan.rb +30 -30
- data/test/test/region/vietnamese.rb +102 -102
- data/test/test/region/yerm.rb +146 -146
- data/test/test/timestandard.rb +81 -81
- data/test/test/tmobjects.rb +328 -328
- data/test/test/tmposition.rb +397 -284
- data/test/test/tmreference.rb +157 -157
- metadata +13 -10
|
@@ -1,801 +1,805 @@
|
|
|
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
|
-
module When
|
|
9
|
-
|
|
10
|
-
#
|
|
11
|
-
# 暦注 - Calendar Note
|
|
12
|
-
#
|
|
13
|
-
class CalendarNote < TM::ReferenceSystem
|
|
14
|
-
|
|
15
|
-
#
|
|
16
|
-
# 暦注要素への名前アクセス機能提供
|
|
17
|
-
#
|
|
18
|
-
# @private
|
|
19
|
-
module LabelAccess
|
|
20
|
-
attr_reader :_pool
|
|
21
|
-
|
|
22
|
-
#
|
|
23
|
-
# 暦注要素への名前(label)によるアクセス
|
|
24
|
-
#
|
|
25
|
-
# @param [Numeric] key 配列インデックスと見なしてアクセス
|
|
26
|
-
# @param [String] key 名前(label)と見なしてアクセス
|
|
27
|
-
#
|
|
28
|
-
# @return [Object] 暦注要素
|
|
29
|
-
#
|
|
30
|
-
def [](key)
|
|
31
|
-
return super if key.kind_of?(Numeric)
|
|
32
|
-
@_pool ||= Hash[*(inject([]) {|pair, v| pair << v.label.to_s << v})]
|
|
33
|
-
@_pool[key]
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
#
|
|
38
|
-
# 暦注要素のひな形クラス
|
|
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
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
#
|
|
54
|
-
# 暦注検索結果を保存するコンテナ
|
|
55
|
-
#
|
|
56
|
-
module NotesContainer
|
|
57
|
-
|
|
58
|
-
class << self
|
|
59
|
-
#
|
|
60
|
-
# 永続データに暦注検索結果を登録する
|
|
61
|
-
#
|
|
62
|
-
# @private
|
|
63
|
-
def register(notes, persistence, sdn)
|
|
64
|
-
if persistence
|
|
65
|
-
persistence.store(sdn, notes)
|
|
66
|
-
persistence.extend(self)
|
|
67
|
-
end
|
|
68
|
-
notes.extend(self)
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
#
|
|
72
|
-
# 永続データから暦注検索結果を取り出す
|
|
73
|
-
#
|
|
74
|
-
# @private
|
|
75
|
-
def retrieve(persistence, sdn)
|
|
76
|
-
return false unless persistence
|
|
77
|
-
persistence.fetch(sdn, false)
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
#
|
|
81
|
-
# パターンの値の一致を判定する
|
|
82
|
-
#
|
|
83
|
-
# @private
|
|
84
|
-
def verify(pattern, value)
|
|
85
|
-
value = value.label if !value.kind_of?(When::BasicTypes::M17n) && value.respond_to?(:label)
|
|
86
|
-
pattern = When::EncodingConversion.to_internal_encoding(pattern)
|
|
87
|
-
pattern.kind_of?(Regexp) ? value =~ pattern : value == pattern
|
|
88
|
-
end
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
# 暦注検索結果コンテナの次元を下げる
|
|
92
|
-
#
|
|
93
|
-
# @param [Boolean] compact 余分な nil や空配列を除去するか否か
|
|
94
|
-
#
|
|
95
|
-
# @return [NotesContainer]
|
|
96
|
-
#
|
|
97
|
-
def simplify(compact=true)
|
|
98
|
-
if kind_of?(Hash) && !key?(:note)
|
|
99
|
-
# Persistent NotesContainer
|
|
100
|
-
simplified = {}
|
|
101
|
-
each_pair do |key, value|
|
|
102
|
-
value = value.simplify(compact) if value.kind_of?(NotesContainer)
|
|
103
|
-
simplified[key] = value if value
|
|
104
|
-
end
|
|
105
|
-
else
|
|
106
|
-
# Non-Persistent NotesContainer
|
|
107
|
-
simplified = self
|
|
108
|
-
simplified = _compact(simplified) if compact
|
|
109
|
-
simplified = simplified[0] while simplified.kind_of?(Array) && simplified.size <= 1
|
|
110
|
-
end
|
|
111
|
-
_bless(simplified)
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
# 暦注検索結果コンテナのハッシュ要素
|
|
115
|
-
#
|
|
116
|
-
# @param [Boolean] compact 余分な nil や空配列を除去するか否か
|
|
117
|
-
# @param [Symbol] symbol 取り出したいハッシュ要素(:note, :value, etc.)
|
|
118
|
-
#
|
|
119
|
-
# @return [Array] ハッシュ要素からなる配列(元の構造が配列であった場合)
|
|
120
|
-
#
|
|
121
|
-
# @note 引数 symbol が Integer の場合は添え字とみなして元の配列の要素を取り出す
|
|
122
|
-
#
|
|
123
|
-
def value(compact=true, symbol=:value)
|
|
124
|
-
if kind_of?(Hash) && !key?(:note)
|
|
125
|
-
# Persistent NotesContainer
|
|
126
|
-
sliced = {}
|
|
127
|
-
each_pair do |key, val|
|
|
128
|
-
sliced[key] = val[symbol]
|
|
129
|
-
end
|
|
130
|
-
else
|
|
131
|
-
# Non-Persistent NotesContainer
|
|
132
|
-
return _bless(slice(symbol)) if symbol.kind_of?(Integer)
|
|
133
|
-
sliced = _dig(self) {|target| target.fetch(symbol, nil)}
|
|
134
|
-
end
|
|
135
|
-
sliced = _bless(sliced)
|
|
136
|
-
compact ? sliced.simplify : sliced
|
|
137
|
-
end
|
|
138
|
-
|
|
139
|
-
# 暦注検索結果コンテナのハッシュ要素
|
|
140
|
-
#
|
|
141
|
-
# @param [Symbol] symbol 取り出したいハッシュ要素(:note, :value, etc.)
|
|
142
|
-
#
|
|
143
|
-
# @return [Array] ハッシュ要素からなる配列(元の構造が配列であった場合)
|
|
144
|
-
#
|
|
145
|
-
# @note 引数 symbol が Integer の場合は添え字とみなして元の配列の要素を取り出す
|
|
146
|
-
#
|
|
147
|
-
def [](symbol)
|
|
148
|
-
value(false, symbol)
|
|
149
|
-
end
|
|
150
|
-
|
|
151
|
-
# 暦注検索結果コンテナの条件に合う要素を抽出する
|
|
152
|
-
#
|
|
153
|
-
# @param [Hash{Symbol=>String or Regexp}] condition 条件
|
|
154
|
-
# @param [Boolean] compact 余分な nil や空配列を除去するか否か
|
|
155
|
-
#
|
|
156
|
-
# @return [Array] ハッシュ要素からなる配列(元の構造が配列であった場合)
|
|
157
|
-
#
|
|
158
|
-
def subset(condition, compact=true)
|
|
159
|
-
if kind_of?(Hash) && !key?(:note)
|
|
160
|
-
# Persistent NotesContainer
|
|
161
|
-
result = {}
|
|
162
|
-
each_pair do |key, value|
|
|
163
|
-
value = value.subset(condition, compact) if value.kind_of?(NotesContainer)
|
|
164
|
-
result[key] = value if value
|
|
165
|
-
end
|
|
166
|
-
else
|
|
167
|
-
# Non-Persistent NotesContainer
|
|
168
|
-
result = _dig(self) {|target|
|
|
169
|
-
(condition.each_pair {|key, pattern| break nil unless NotesContainer.verify(pattern, target[key])}) ? target : nil
|
|
170
|
-
}
|
|
171
|
-
result = _compact(result) if compact
|
|
172
|
-
end
|
|
173
|
-
_bless(result)
|
|
174
|
-
end
|
|
175
|
-
|
|
176
|
-
private
|
|
177
|
-
|
|
178
|
-
#
|
|
179
|
-
# 対象オブジェクトを NotesContainer にする
|
|
180
|
-
#
|
|
181
|
-
def _bless(target)
|
|
182
|
-
target.extend(NotesContainer) if target && !equal?(target)
|
|
183
|
-
target
|
|
184
|
-
end
|
|
185
|
-
|
|
186
|
-
#
|
|
187
|
-
# 多次元配列要素に対して再帰的に要素を抽出して操作を施す
|
|
188
|
-
#
|
|
189
|
-
def _dig(list, &block)
|
|
190
|
-
return yield(list) unless list.kind_of?(Array)
|
|
191
|
-
list.map {|element| _dig(element, &block)}
|
|
192
|
-
end
|
|
193
|
-
|
|
194
|
-
#
|
|
195
|
-
# 多次元配列要素に対して再帰的に作用し nil や空配列を削除する
|
|
196
|
-
#
|
|
197
|
-
def _compact(list)
|
|
198
|
-
return list unless list.kind_of?(Array)
|
|
199
|
-
result = list.map {|element| _compact(element)}.compact
|
|
200
|
-
return result unless result.empty?
|
|
201
|
-
nil
|
|
202
|
-
end
|
|
203
|
-
end
|
|
204
|
-
|
|
205
|
-
#
|
|
206
|
-
# 暦法によってイベントの動作を変えるか否か
|
|
207
|
-
#
|
|
208
|
-
CalendarDepend = false
|
|
209
|
-
|
|
210
|
-
# デフォルトイベント名
|
|
211
|
-
#
|
|
212
|
-
# @return [String]
|
|
213
|
-
#
|
|
214
|
-
# @note イベント名の後ろに数字が使われている場合、数字部分以降はイベントメソッドの引数になります。
|
|
215
|
-
# SolarTermsクラスで 'term180' は、太陽黄経180度のイベントすなわち秋分を意味します。
|
|
216
|
-
#
|
|
217
|
-
attr_accessor :event
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
# デフォルトイベントの指定
|
|
221
|
-
#
|
|
222
|
-
# @param [String] event 指定値を@eventとした新しいオブジェクトを作る
|
|
223
|
-
#
|
|
224
|
-
# @return [When::CalendarNote]
|
|
225
|
-
#
|
|
226
|
-
def copy(event)
|
|
227
|
-
c = self.clone
|
|
228
|
-
c.event
|
|
229
|
-
c
|
|
230
|
-
end
|
|
231
|
-
|
|
232
|
-
# 典型的なイベントの発生間隔
|
|
233
|
-
#
|
|
234
|
-
# @param [String] event
|
|
235
|
-
#
|
|
236
|
-
# @return [When::TM::PeriodDuration]
|
|
237
|
-
#
|
|
238
|
-
def duration(event=@event)
|
|
239
|
-
void, event, parameter = event.split(
|
|
240
|
-
send((event+'_delta').downcase.to_sym, parameter)
|
|
241
|
-
end
|
|
242
|
-
|
|
243
|
-
# 指定の日時が指定イベントに該当するか?
|
|
244
|
-
#
|
|
245
|
-
# @param [When::TM::TemporalPosition] date チェックされる日時
|
|
246
|
-
# @param [String] event チェックするイベント名
|
|
247
|
-
#
|
|
248
|
-
# @return [Boolean]
|
|
249
|
-
# [ true - 該当する ]
|
|
250
|
-
# [ false - 該当しない ]
|
|
251
|
-
#
|
|
252
|
-
def include?(date, event=@event)
|
|
253
|
-
enum_for(date, :forward, event.downcase).next.include?(date)
|
|
254
|
-
end
|
|
255
|
-
|
|
256
|
-
# Enumeratorの生成
|
|
257
|
-
#
|
|
258
|
-
# @overload enum_for(range, options={})
|
|
259
|
-
# @param [Range, When::Parts::GeometricComplex] range
|
|
260
|
-
# [ 始点 - range.first ]
|
|
261
|
-
# [ 終点 - range.last ]
|
|
262
|
-
# @param [Hash] options 以下の通り
|
|
263
|
-
# @option options [String] :event イベント名(デフォルトは@event)
|
|
264
|
-
# @option options [Integer] :count_limit 繰り返し回数(デフォルトは指定なし)
|
|
265
|
-
#
|
|
266
|
-
# @overload enum_for(first, direction=:forward, options={})
|
|
267
|
-
# @param [When::TM::TemporalPosition] first 始点
|
|
268
|
-
# @param [Symbol] direction (options[:direction]で渡してもよい)
|
|
269
|
-
# [:forward] 昇順(デフォルト)
|
|
270
|
-
# [:reverse] 降順
|
|
271
|
-
# @param [Hash] options 以下の通り
|
|
272
|
-
# @option options [String] :event イベント名(デフォルトは@event)
|
|
273
|
-
# @option options [Integer] :count_limit 繰り返し回数(デフォルトは指定なし)
|
|
274
|
-
#
|
|
275
|
-
# @return [Enumerator]
|
|
276
|
-
#
|
|
277
|
-
def enum_for(*args)
|
|
278
|
-
params = args.dup
|
|
279
|
-
options = params[-1].kind_of?(Hash) ? params.pop.dup : {}
|
|
280
|
-
options[:event] ||= @event
|
|
281
|
-
self.class::Enumerator.new(*(params[0].kind_of?(Range) ?
|
|
282
|
-
[self, params[0], options] :
|
|
283
|
-
[self, params[0], params[1] || :forward, options]))
|
|
284
|
-
end
|
|
285
|
-
alias :to_enum :enum_for
|
|
286
|
-
|
|
287
|
-
# 暦注の計算
|
|
288
|
-
#
|
|
289
|
-
# @param [When::TM::TemporalPosition] date 暦注を計算する日時
|
|
290
|
-
# @param [When::TM::TemporalPosition 以外] date When::TM::TemporalPosition に変換して使用する
|
|
291
|
-
# @param [String] options { :notes => String } という Hash の指定と等価
|
|
292
|
-
# @param [Integer] options { :indices => Integer} という Hash の指定と等価
|
|
293
|
-
# @param [Hash] options 下記のとおり
|
|
294
|
-
# @option options [Integer] :indices Integerで指定した暦座標の暦注を計算
|
|
295
|
-
# [ When::DAY ( 0) - 日 ]
|
|
296
|
-
# [ When::MONTH(-1) - 月 ]
|
|
297
|
-
# [ When::YEAR (-2) - 年 ]
|
|
298
|
-
#
|
|
299
|
-
# @option options [Array<Integer>] :indices Integerで指定したすべて暦座標の暦注を計算
|
|
300
|
-
# @option options [nil] :indices すべての暦座標の暦注を計算(デフォルト)
|
|
301
|
-
# @option options [String] :notes 計算する暦注名(日の暦注)
|
|
302
|
-
# @option options [Integer] :notes 計算する暦注のビット配列(日の暦注)
|
|
303
|
-
# @option options [Array<Array<String>>] :notes 計算する暦注名の Array の Array
|
|
304
|
-
# @option options [Array<Integer>] :notes 計算する暦注のビット配列の Array
|
|
305
|
-
# @option options [:all] :notes すべての暦注を計算
|
|
306
|
-
# @option options [:prime, nil] :notes @prime に登録した暦注を計算、@prime未登録なら :all と同じ(デフォルト)
|
|
307
|
-
# @option options [Hash] :persistence {ユリウス通日=>暦注計算結果}を保持する永続オブジェクト
|
|
308
|
-
# @option options [Hash] :conditions 暦注計算の条件
|
|
309
|
-
# [ :location => 暦注計算の基準となる場所(String or When::Coordinates::Spatial) ]
|
|
310
|
-
# [ その他のキー => 個々の暦注クラスごとにその他のキーを使用できる ]
|
|
311
|
-
#
|
|
312
|
-
# @option options [Hash] その他のキー date を When::TM::TemporalPosition に変換するために使用する
|
|
313
|
-
# see {When::TM::TemporalPosition._instance}
|
|
314
|
-
#
|
|
315
|
-
# @note CalendarNoteオブジェクト生成時に _normalize メソッド内で @prime 変数を設定しておけば、
|
|
316
|
-
# 本メソッドの :prime オプションで参照される。(Balinese#_normalize等参照)
|
|
317
|
-
#
|
|
318
|
-
# @note 暦注のビットアドレスは、暦注サブクラスのNotes定数の中の定義順序による。
|
|
319
|
-
# When::CalendarNote クラスの場合 new の引数とした暦注要素リストの定義順序による。
|
|
320
|
-
# ビットアドレスの値が 1 の暦注が計算対象となる。
|
|
321
|
-
#
|
|
322
|
-
# @return [Array<Array<Hash>>] 暦注計算結果(When::CalendarNote::NotesContainerモジュールをextendしている)
|
|
323
|
-
# [ :note => 暦注要素 (When::Coordinates::Residue, String, When::BasicTypes::M17n) ]
|
|
324
|
-
# [ :value => 暦注の値 (When::Coordinates::Residue, String, When::BasicTypes::M17n, When::TM::TemporalPosition) ]
|
|
325
|
-
#
|
|
326
|
-
# @note
|
|
327
|
-
# 戻り値の :value が When::TM::TemporalPosition の場合、その日時オブジェクトの events[0] に暦注名の入った
|
|
328
|
-
# 暦注に該当する日付である。(例) Christian クラス で easter を計算した場合、当該年の復活祭の日付オブジェクトが返る。
|
|
329
|
-
# @note
|
|
330
|
-
# 暦注サブクラスの場合、暦注要素が増えたり、:note の暦注要素の型が変わったりすることがある。
|
|
331
|
-
#
|
|
332
|
-
def notes(date, options={})
|
|
333
|
-
dates, indices, notes, persistence, conditions, options = _parse_note(date, options)
|
|
334
|
-
retrieved = NotesContainer.retrieve(persistence, date.to_i)
|
|
335
|
-
return retrieved unless retrieved == false
|
|
336
|
-
NotesContainer.register(indices.map {|i|
|
|
337
|
-
next [] unless i <= date.precision
|
|
338
|
-
_note_values(dates, notes[i-1], _all_keys[i-1], _elements[i-1]) do |dates, focused_notes, notes_hash|
|
|
339
|
-
focused_notes.each do |note|
|
|
340
|
-
notes_hash[note] ||= _note_element(note, i, conditions, dates)
|
|
341
|
-
end
|
|
342
|
-
notes_hash
|
|
343
|
-
end
|
|
344
|
-
}, persistence, date.to_i)
|
|
345
|
-
end
|
|
346
|
-
|
|
347
|
-
#
|
|
348
|
-
# 暦注の一致 or 不一致
|
|
349
|
-
#
|
|
350
|
-
# @param [When::TM::TemporalPosition] date 暦注を確認する日時
|
|
351
|
-
# @param [When::TM::TemporalPosition 以外] date When::TM::TemporalPosition に変換して使用する
|
|
352
|
-
# @param [String] options { :notes => String } または { :value => String } という Hash の指定と等価
|
|
353
|
-
# (指定の notes が存在する場合は前者、しない場合は後者)
|
|
354
|
-
# @param [Integer] options { :indices => Integer } という Hash の指定と等価
|
|
355
|
-
# @param [Hash] options 下記のとおり
|
|
356
|
-
# @option options [暦注の値] :value 確認する暦注の値(または正規表現)
|
|
357
|
-
# @option options [それぞれ] その他 {When::CalendarNote#notes} を参照
|
|
358
|
-
#
|
|
359
|
-
# @return [Boolean]
|
|
360
|
-
# [ true - 暦注が一致 ]
|
|
361
|
-
# [ false - 暦注が不一致 ]
|
|
362
|
-
#
|
|
363
|
-
def note?(date, options={})
|
|
364
|
-
options = _find_note(options) if options.kind_of?(String) || options.kind_of?(Regexp)
|
|
365
|
-
pattern = options.delete(:value) if options.kind_of?(Hash)
|
|
366
|
-
result = notes(date, options)
|
|
367
|
-
result.flatten!
|
|
368
|
-
result.delete_if {|hash| hash.empty?}
|
|
369
|
-
return false unless result.size > 0
|
|
370
|
-
return true unless pattern
|
|
371
|
-
result.each do |hash|
|
|
372
|
-
return true if NotesContainer.verify(pattern, hash[:value])
|
|
373
|
-
end
|
|
374
|
-
return false
|
|
375
|
-
end
|
|
376
|
-
|
|
377
|
-
# 年の名前を暦注として返す
|
|
378
|
-
# @method year
|
|
379
|
-
# @return [When::BasicTypes::M17n]
|
|
380
|
-
|
|
381
|
-
# 月の名前を暦注として返す
|
|
382
|
-
# @method month
|
|
383
|
-
# @return [When::BasicTypes::M17n]
|
|
384
|
-
|
|
385
|
-
# 日の名前を暦注として返す
|
|
386
|
-
# @method day
|
|
387
|
-
# @return [When::BasicTypes::M17n]
|
|
388
|
-
|
|
389
|
-
#
|
|
390
|
-
# 標準的な暦注として、暦座標の値の名前を暦注として返すメソッドを登録
|
|
391
|
-
#
|
|
392
|
-
# @private
|
|
393
|
-
['year', 'month', 'day'].each do |c|
|
|
394
|
-
module_eval %Q{
|
|
395
|
-
def #{c}(date)
|
|
396
|
-
date.name('#{c}')
|
|
397
|
-
end
|
|
398
|
-
}
|
|
399
|
-
end
|
|
400
|
-
|
|
401
|
-
private
|
|
402
|
-
|
|
403
|
-
#
|
|
404
|
-
# 年月日暦注計算の共通処理 - コールバック元
|
|
405
|
-
#
|
|
406
|
-
def _note_values(dates, focused_notes, all_notes, note_objects)
|
|
407
|
-
return [] unless dates && all_notes
|
|
408
|
-
|
|
409
|
-
# prepare focused notes
|
|
410
|
-
case focused_notes
|
|
411
|
-
when Integer
|
|
412
|
-
bits = ~focused_notes << 1
|
|
413
|
-
focused_notes = all_notes.dup.delete_if { (bits>>=1)[0] == 1 }
|
|
414
|
-
when []
|
|
415
|
-
focused_notes = all_notes
|
|
416
|
-
when nil
|
|
417
|
-
focused_notes = []
|
|
418
|
-
end
|
|
419
|
-
focused_notes = focused_notes.dup
|
|
420
|
-
not_focused_notes = all_notes - focused_notes
|
|
421
|
-
notes = {}
|
|
422
|
-
not_focused_notes.each do |note|
|
|
423
|
-
notes[note] = true
|
|
424
|
-
end
|
|
425
|
-
focused_notes.each do |note|
|
|
426
|
-
notes[note] = nil
|
|
427
|
-
end
|
|
428
|
-
|
|
429
|
-
# update notes
|
|
430
|
-
focused_notes_actual = focused_notes.dup
|
|
431
|
-
notes = yield(dates, focused_notes_actual, notes)
|
|
432
|
-
notes.keys.each do |note|
|
|
433
|
-
notes.delete(note) unless focused_notes_actual.include?(note)
|
|
434
|
-
end
|
|
435
|
-
|
|
436
|
-
# return Array of Hash
|
|
437
|
-
focused_notes.map {|note|
|
|
438
|
-
case notes[note]
|
|
439
|
-
when nil, false ; {}
|
|
440
|
-
when Hash ; {:note=>note_objects[note].label}.merge(notes[note])
|
|
441
|
-
else
|
|
442
|
-
if note_objects[note].respond_to?(:to_note_hash)
|
|
443
|
-
note_objects[note].to_note_hash(notes[note], dates)
|
|
444
|
-
else
|
|
445
|
-
{:note=>note_objects[note].label, :value=>notes[note]}
|
|
446
|
-
end
|
|
447
|
-
end
|
|
448
|
-
}
|
|
449
|
-
end
|
|
450
|
-
|
|
451
|
-
#
|
|
452
|
-
# オブジェクトの正規化
|
|
453
|
-
#
|
|
454
|
-
def _normalize(args=[], options={})
|
|
455
|
-
@_elements = (args.size == 0 && self.class.const_defined?(:Notes)) ?
|
|
456
|
-
When::Parts::Resource.base_uri + self.class.to_s.split(/::/)[1..-1].join('/') + '/Notes' :
|
|
457
|
-
_to_iri(args, options[:prefix] || '_co:')
|
|
458
|
-
if @_elements.kind_of?(Array)
|
|
459
|
-
@_elements.each do |e|
|
|
460
|
-
e.extend LabelAccess
|
|
461
|
-
end
|
|
462
|
-
end
|
|
463
|
-
end
|
|
464
|
-
|
|
465
|
-
#
|
|
466
|
-
# 再帰的に配列の中を Resource化する
|
|
467
|
-
#
|
|
468
|
-
def _to_iri(args, prefix)
|
|
469
|
-
args.map {|arg|
|
|
470
|
-
case arg
|
|
471
|
-
when String
|
|
472
|
-
arg, method = $1, $2 if (arg =~
|
|
473
|
-
obj = When.Resource(arg, prefix)
|
|
474
|
-
obj = obj.copy(method) if method
|
|
475
|
-
obj
|
|
476
|
-
when Array
|
|
477
|
-
_to_iri(arg, prefix)
|
|
478
|
-
else
|
|
479
|
-
arg
|
|
480
|
-
end
|
|
481
|
-
}
|
|
482
|
-
end
|
|
483
|
-
|
|
484
|
-
#
|
|
485
|
-
# 暦日を当該暦注計算用クラスに変換
|
|
486
|
-
#
|
|
487
|
-
# 基底クラスである本クラスでは何もしないで、引数をそのまま返す
|
|
488
|
-
#
|
|
489
|
-
def _to_date_for_note(date)
|
|
490
|
-
date
|
|
491
|
-
end
|
|
492
|
-
|
|
493
|
-
# 暦注要素
|
|
494
|
-
#
|
|
495
|
-
# @return [Array<Array<When::Parts::Resource>>]
|
|
496
|
-
#
|
|
497
|
-
def _elements
|
|
498
|
-
@_elements = When.Resource(@_elements) if @_elements.kind_of?(String)
|
|
499
|
-
@_elements
|
|
500
|
-
end
|
|
501
|
-
|
|
502
|
-
#
|
|
503
|
-
# [[暦注名]](全暦注)
|
|
504
|
-
#
|
|
505
|
-
# @return [Array<Array<String, When::BasicTypes::M17n>>]
|
|
506
|
-
#
|
|
507
|
-
def _all_keys
|
|
508
|
-
@_all_keys ||= _elements.map { |c|
|
|
509
|
-
c.map {|n|
|
|
510
|
-
n.label.to_s
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
end
|
|
514
|
-
|
|
515
|
-
#
|
|
516
|
-
# [[暦注名]](主要暦注)
|
|
517
|
-
#
|
|
518
|
-
# @return [Array<Array<When::Parts::Resource>>]
|
|
519
|
-
#
|
|
520
|
-
def _prime_keys
|
|
521
|
-
@prime ||= _all_keys
|
|
522
|
-
end
|
|
523
|
-
|
|
524
|
-
#
|
|
525
|
-
# notes メソッドの引数を parse する
|
|
526
|
-
#
|
|
527
|
-
# @return [Array] dates, indices, notes
|
|
528
|
-
#
|
|
529
|
-
def _parse_note(date, options)
|
|
530
|
-
options =
|
|
531
|
-
case options
|
|
532
|
-
when Hash ; When::EncodingConversion.to_internal_encoding(options)
|
|
533
|
-
when String ; {:notes => When::EncodingConversion.to_internal_encoding(options)}
|
|
534
|
-
when Integer ; {:indices => options}
|
|
535
|
-
else ; {}
|
|
536
|
-
end
|
|
537
|
-
conditions = options.delete(:conditions) || {}
|
|
538
|
-
_opt = options.dup
|
|
539
|
-
persistence = _opt.delete(:persistence)
|
|
540
|
-
notes = _notes(_opt.delete(:notes) || :prime)
|
|
541
|
-
indices = _indices(_opt.delete(:indices), notes)
|
|
542
|
-
_opt.keys.each do |key|
|
|
543
|
-
conditions[key] = _opt[key] unless date.class::FormOptions.include?(key)
|
|
544
|
-
end
|
|
545
|
-
[_to_date_for_note(date), indices, notes, persistence, conditions, options]
|
|
546
|
-
end
|
|
547
|
-
|
|
548
|
-
#
|
|
549
|
-
# 暦注を計算する暦座標の配列
|
|
550
|
-
#
|
|
551
|
-
# @return [Array<Integer>]
|
|
552
|
-
#
|
|
553
|
-
def _indices(indices, notes)
|
|
554
|
-
case indices
|
|
555
|
-
when nil ; (0...notes.size).to_a.reverse.map {|i| -i}
|
|
556
|
-
when Range ; indices.to_a
|
|
557
|
-
when Array ; indices
|
|
558
|
-
else ; [indices.to_i]
|
|
559
|
-
end
|
|
560
|
-
end
|
|
561
|
-
|
|
562
|
-
#
|
|
563
|
-
# notes メソッドの 文字列引数の意味を解釈する
|
|
564
|
-
#
|
|
565
|
-
# @return [Hash] options for note String
|
|
566
|
-
#
|
|
567
|
-
def _find_note(note)
|
|
568
|
-
note = When::EncodingConversion.to_internal_encoding(note)
|
|
569
|
-
_elements.each_index do |index|
|
|
570
|
-
return {:notes=>note, :indices => [-index]} if _elements[-1-index]._pool[note]
|
|
571
|
-
end
|
|
572
|
-
{:value => note}
|
|
573
|
-
end
|
|
574
|
-
|
|
575
|
-
#
|
|
576
|
-
# 計算する暦注
|
|
577
|
-
#
|
|
578
|
-
# @return [Array<Array<String>, Integer>]
|
|
579
|
-
#
|
|
580
|
-
def _notes(notes)
|
|
581
|
-
case notes
|
|
582
|
-
when :all ; _all_keys
|
|
583
|
-
when :prime ; _prime_keys
|
|
584
|
-
when Integer ; [notes]
|
|
585
|
-
when String ; [[notes]]
|
|
586
|
-
else ; notes
|
|
587
|
-
end
|
|
588
|
-
end
|
|
589
|
-
|
|
590
|
-
#
|
|
591
|
-
# 暦注の計算
|
|
592
|
-
#
|
|
593
|
-
# @return [Object] 暦注の値
|
|
594
|
-
#
|
|
595
|
-
def _note_element(note, index, conditions, dates)
|
|
596
|
-
void, event, *parameter = note.split(
|
|
597
|
-
method = event.downcase
|
|
598
|
-
parameter << conditions unless conditions.empty?
|
|
599
|
-
return send(method, dates, *parameter) if respond_to?(method)
|
|
600
|
-
root = _elements[index-1][note]
|
|
601
|
-
parent, leaf = root.iri.split('/Notes') if root.kind_of?(When::Parts::Resource)
|
|
602
|
-
parent = When.Resource(parent) if leaf
|
|
603
|
-
return parent.send(method, dates, *parameter) if parent.respond_to?(method)
|
|
604
|
-
root.send(When::Coordinates::PRECISION_NAME[index].downcase, dates)
|
|
605
|
-
end
|
|
606
|
-
|
|
607
|
-
#
|
|
608
|
-
# イベントを取得する Enumerator
|
|
609
|
-
#
|
|
610
|
-
class Enumerator < When::Parts::Enumerator
|
|
611
|
-
|
|
612
|
-
#
|
|
613
|
-
# 次のイベントを得る
|
|
614
|
-
#
|
|
615
|
-
# @return [When::TM::TemporalPosition]
|
|
616
|
-
#
|
|
617
|
-
def _succ
|
|
618
|
-
@current = (@current==:first) ? @first : event_eval(@current + @delta)
|
|
619
|
-
end
|
|
620
|
-
|
|
621
|
-
# オブジェクトの生成
|
|
622
|
-
#
|
|
623
|
-
# @overload initialize(parent, range, options)
|
|
624
|
-
# @param [When::CalendarNote] parent 暦注アルゴリズム
|
|
625
|
-
# @param [Range, When::Parts::GeometricComplex] range
|
|
626
|
-
# [ 始点 - range.first ]
|
|
627
|
-
# [ 終点 - range.last ]
|
|
628
|
-
# @param [Hash] options 以下の通り
|
|
629
|
-
# @option options [String] :event イベント名
|
|
630
|
-
# @option options [Integer] :count_limit 繰り返し回数(デフォルトは指定なし)
|
|
631
|
-
#
|
|
632
|
-
# @overload initialize(parent, first, direction, options)
|
|
633
|
-
# @param [When::CalendarNote] parent 暦注アルゴリズム
|
|
634
|
-
# @param [When::TM::TemporalPosition] first 始点
|
|
635
|
-
# @param [Symbol] direction (options[:direction]で渡してもよい)
|
|
636
|
-
# [:forward] 昇順(デフォルト)
|
|
637
|
-
# [:reverse] 降順
|
|
638
|
-
# @param [Hash] options 以下の通り
|
|
639
|
-
# @option options [String] :event イベント名
|
|
640
|
-
# @option options [Integer] :count_limit 繰り返し回数(デフォルトは指定なし)
|
|
641
|
-
#
|
|
642
|
-
def initialize(*args)
|
|
643
|
-
if args[1].kind_of?(Range)
|
|
644
|
-
parent, range, options = args
|
|
645
|
-
first = range.first
|
|
646
|
-
last = range.last
|
|
647
|
-
direction = first < last ? :forward : :reverse
|
|
648
|
-
else
|
|
649
|
-
parent, first, direction, options = args
|
|
650
|
-
end
|
|
651
|
-
direction = options[:direction] if options[:direction]
|
|
652
|
-
@parent = parent
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
#
|
|
690
|
-
#
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
#
|
|
730
|
-
#
|
|
731
|
-
#
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
#
|
|
741
|
-
#
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
#
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
end
|
|
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
|
+
module When
|
|
9
|
+
|
|
10
|
+
#
|
|
11
|
+
# 暦注 - Calendar Note
|
|
12
|
+
#
|
|
13
|
+
class CalendarNote < TM::ReferenceSystem
|
|
14
|
+
|
|
15
|
+
#
|
|
16
|
+
# 暦注要素への名前アクセス機能提供
|
|
17
|
+
#
|
|
18
|
+
# @private
|
|
19
|
+
module LabelAccess
|
|
20
|
+
attr_reader :_pool
|
|
21
|
+
|
|
22
|
+
#
|
|
23
|
+
# 暦注要素への名前(label)によるアクセス
|
|
24
|
+
#
|
|
25
|
+
# @param [Numeric] key 配列インデックスと見なしてアクセス
|
|
26
|
+
# @param [String] key 名前(label)と見なしてアクセス
|
|
27
|
+
#
|
|
28
|
+
# @return [Object] 暦注要素
|
|
29
|
+
#
|
|
30
|
+
def [](key)
|
|
31
|
+
return super if key.kind_of?(Numeric)
|
|
32
|
+
@_pool ||= Hash[*(inject([]) {|pair, v| pair << v.label.to_s << v})]
|
|
33
|
+
@_pool[key]
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
#
|
|
38
|
+
# 暦注要素のひな形クラス
|
|
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
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
#
|
|
54
|
+
# 暦注検索結果を保存するコンテナ
|
|
55
|
+
#
|
|
56
|
+
module NotesContainer
|
|
57
|
+
|
|
58
|
+
class << self
|
|
59
|
+
#
|
|
60
|
+
# 永続データに暦注検索結果を登録する
|
|
61
|
+
#
|
|
62
|
+
# @private
|
|
63
|
+
def register(notes, persistence, sdn)
|
|
64
|
+
if persistence
|
|
65
|
+
persistence.store(sdn, notes)
|
|
66
|
+
persistence.extend(self)
|
|
67
|
+
end
|
|
68
|
+
notes.extend(self)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
#
|
|
72
|
+
# 永続データから暦注検索結果を取り出す
|
|
73
|
+
#
|
|
74
|
+
# @private
|
|
75
|
+
def retrieve(persistence, sdn)
|
|
76
|
+
return false unless persistence
|
|
77
|
+
persistence.fetch(sdn, false)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
#
|
|
81
|
+
# パターンの値の一致を判定する
|
|
82
|
+
#
|
|
83
|
+
# @private
|
|
84
|
+
def verify(pattern, value)
|
|
85
|
+
value = value.label if !value.kind_of?(When::BasicTypes::M17n) && value.respond_to?(:label)
|
|
86
|
+
pattern = When::EncodingConversion.to_internal_encoding(pattern)
|
|
87
|
+
pattern.kind_of?(Regexp) ? value =~ pattern : value == pattern
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# 暦注検索結果コンテナの次元を下げる
|
|
92
|
+
#
|
|
93
|
+
# @param [Boolean] compact 余分な nil や空配列を除去するか否か
|
|
94
|
+
#
|
|
95
|
+
# @return [NotesContainer]
|
|
96
|
+
#
|
|
97
|
+
def simplify(compact=true)
|
|
98
|
+
if kind_of?(Hash) && !key?(:note)
|
|
99
|
+
# Persistent NotesContainer
|
|
100
|
+
simplified = {}
|
|
101
|
+
each_pair do |key, value|
|
|
102
|
+
value = value.simplify(compact) if value.kind_of?(NotesContainer)
|
|
103
|
+
simplified[key] = value if value
|
|
104
|
+
end
|
|
105
|
+
else
|
|
106
|
+
# Non-Persistent NotesContainer
|
|
107
|
+
simplified = self
|
|
108
|
+
simplified = _compact(simplified) if compact
|
|
109
|
+
simplified = simplified[0] while simplified.kind_of?(Array) && simplified.size <= 1
|
|
110
|
+
end
|
|
111
|
+
_bless(simplified)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# 暦注検索結果コンテナのハッシュ要素
|
|
115
|
+
#
|
|
116
|
+
# @param [Boolean] compact 余分な nil や空配列を除去するか否か
|
|
117
|
+
# @param [Symbol] symbol 取り出したいハッシュ要素(:note, :value, etc.)
|
|
118
|
+
#
|
|
119
|
+
# @return [Array] ハッシュ要素からなる配列(元の構造が配列であった場合)
|
|
120
|
+
#
|
|
121
|
+
# @note 引数 symbol が Integer の場合は添え字とみなして元の配列の要素を取り出す
|
|
122
|
+
#
|
|
123
|
+
def value(compact=true, symbol=:value)
|
|
124
|
+
if kind_of?(Hash) && !key?(:note)
|
|
125
|
+
# Persistent NotesContainer
|
|
126
|
+
sliced = {}
|
|
127
|
+
each_pair do |key, val|
|
|
128
|
+
sliced[key] = val[symbol]
|
|
129
|
+
end
|
|
130
|
+
else
|
|
131
|
+
# Non-Persistent NotesContainer
|
|
132
|
+
return _bless(slice(symbol)) if symbol.kind_of?(Integer)
|
|
133
|
+
sliced = _dig(self) {|target| target.fetch(symbol, nil)}
|
|
134
|
+
end
|
|
135
|
+
sliced = _bless(sliced)
|
|
136
|
+
compact ? sliced.simplify : sliced
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# 暦注検索結果コンテナのハッシュ要素
|
|
140
|
+
#
|
|
141
|
+
# @param [Symbol] symbol 取り出したいハッシュ要素(:note, :value, etc.)
|
|
142
|
+
#
|
|
143
|
+
# @return [Array] ハッシュ要素からなる配列(元の構造が配列であった場合)
|
|
144
|
+
#
|
|
145
|
+
# @note 引数 symbol が Integer の場合は添え字とみなして元の配列の要素を取り出す
|
|
146
|
+
#
|
|
147
|
+
def [](symbol)
|
|
148
|
+
value(false, symbol)
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# 暦注検索結果コンテナの条件に合う要素を抽出する
|
|
152
|
+
#
|
|
153
|
+
# @param [Hash{Symbol=>String or Regexp}] condition 条件
|
|
154
|
+
# @param [Boolean] compact 余分な nil や空配列を除去するか否か
|
|
155
|
+
#
|
|
156
|
+
# @return [Array] ハッシュ要素からなる配列(元の構造が配列であった場合)
|
|
157
|
+
#
|
|
158
|
+
def subset(condition, compact=true)
|
|
159
|
+
if kind_of?(Hash) && !key?(:note)
|
|
160
|
+
# Persistent NotesContainer
|
|
161
|
+
result = {}
|
|
162
|
+
each_pair do |key, value|
|
|
163
|
+
value = value.subset(condition, compact) if value.kind_of?(NotesContainer)
|
|
164
|
+
result[key] = value if value
|
|
165
|
+
end
|
|
166
|
+
else
|
|
167
|
+
# Non-Persistent NotesContainer
|
|
168
|
+
result = _dig(self) {|target|
|
|
169
|
+
(condition.each_pair {|key, pattern| break nil unless NotesContainer.verify(pattern, target[key])}) ? target : nil
|
|
170
|
+
}
|
|
171
|
+
result = _compact(result) if compact
|
|
172
|
+
end
|
|
173
|
+
_bless(result)
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
private
|
|
177
|
+
|
|
178
|
+
#
|
|
179
|
+
# 対象オブジェクトを NotesContainer にする
|
|
180
|
+
#
|
|
181
|
+
def _bless(target)
|
|
182
|
+
target.extend(NotesContainer) if target && !equal?(target)
|
|
183
|
+
target
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
#
|
|
187
|
+
# 多次元配列要素に対して再帰的に要素を抽出して操作を施す
|
|
188
|
+
#
|
|
189
|
+
def _dig(list, &block)
|
|
190
|
+
return yield(list) unless list.kind_of?(Array)
|
|
191
|
+
list.map {|element| _dig(element, &block)}
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
#
|
|
195
|
+
# 多次元配列要素に対して再帰的に作用し nil や空配列を削除する
|
|
196
|
+
#
|
|
197
|
+
def _compact(list)
|
|
198
|
+
return list unless list.kind_of?(Array)
|
|
199
|
+
result = list.map {|element| _compact(element)}.compact
|
|
200
|
+
return result unless result.empty?
|
|
201
|
+
nil
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
#
|
|
206
|
+
# 暦法によってイベントの動作を変えるか否か
|
|
207
|
+
#
|
|
208
|
+
CalendarDepend = false
|
|
209
|
+
|
|
210
|
+
# デフォルトイベント名
|
|
211
|
+
#
|
|
212
|
+
# @return [String]
|
|
213
|
+
#
|
|
214
|
+
# @note イベント名の後ろに数字が使われている場合、数字部分以降はイベントメソッドの引数になります。
|
|
215
|
+
# SolarTermsクラスで 'term180' は、太陽黄経180度のイベントすなわち秋分を意味します。
|
|
216
|
+
#
|
|
217
|
+
attr_accessor :event
|
|
218
|
+
private :event=
|
|
219
|
+
|
|
220
|
+
# デフォルトイベントの指定
|
|
221
|
+
#
|
|
222
|
+
# @param [String] event 指定値を@eventとした新しいオブジェクトを作る
|
|
223
|
+
#
|
|
224
|
+
# @return [When::CalendarNote]
|
|
225
|
+
#
|
|
226
|
+
def copy(event)
|
|
227
|
+
c = self.clone
|
|
228
|
+
c.send(:event=, event)
|
|
229
|
+
c
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
# 典型的なイベントの発生間隔
|
|
233
|
+
#
|
|
234
|
+
# @param [String] event
|
|
235
|
+
#
|
|
236
|
+
# @return [When::TM::PeriodDuration]
|
|
237
|
+
#
|
|
238
|
+
def duration(event=@event)
|
|
239
|
+
void, event, parameter = event.split(/\A([^\d]+)/)
|
|
240
|
+
send((event+'_delta').downcase.to_sym, parameter)
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
# 指定の日時が指定イベントに該当するか?
|
|
244
|
+
#
|
|
245
|
+
# @param [When::TM::TemporalPosition] date チェックされる日時
|
|
246
|
+
# @param [String] event チェックするイベント名
|
|
247
|
+
#
|
|
248
|
+
# @return [Boolean]
|
|
249
|
+
# [ true - 該当する ]
|
|
250
|
+
# [ false - 該当しない ]
|
|
251
|
+
#
|
|
252
|
+
def include?(date, event=@event)
|
|
253
|
+
enum_for(date, :forward, event.downcase).next.include?(date)
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
# Enumeratorの生成
|
|
257
|
+
#
|
|
258
|
+
# @overload enum_for(range, options={})
|
|
259
|
+
# @param [Range, When::Parts::GeometricComplex] range
|
|
260
|
+
# [ 始点 - range.first ]
|
|
261
|
+
# [ 終点 - range.last ]
|
|
262
|
+
# @param [Hash] options 以下の通り
|
|
263
|
+
# @option options [String] :event イベント名(デフォルトは@event)
|
|
264
|
+
# @option options [Integer] :count_limit 繰り返し回数(デフォルトは指定なし)
|
|
265
|
+
#
|
|
266
|
+
# @overload enum_for(first, direction=:forward, options={})
|
|
267
|
+
# @param [When::TM::TemporalPosition] first 始点
|
|
268
|
+
# @param [Symbol] direction (options[:direction]で渡してもよい)
|
|
269
|
+
# [:forward] 昇順(デフォルト)
|
|
270
|
+
# [:reverse] 降順
|
|
271
|
+
# @param [Hash] options 以下の通り
|
|
272
|
+
# @option options [String] :event イベント名(デフォルトは@event)
|
|
273
|
+
# @option options [Integer] :count_limit 繰り返し回数(デフォルトは指定なし)
|
|
274
|
+
#
|
|
275
|
+
# @return [Enumerator]
|
|
276
|
+
#
|
|
277
|
+
def enum_for(*args)
|
|
278
|
+
params = args.dup
|
|
279
|
+
options = params[-1].kind_of?(Hash) ? params.pop.dup : {}
|
|
280
|
+
options[:event] ||= @event
|
|
281
|
+
self.class::Enumerator.new(*(params[0].kind_of?(Range) ?
|
|
282
|
+
[self, params[0], options] :
|
|
283
|
+
[self, params[0], params[1] || :forward, options]))
|
|
284
|
+
end
|
|
285
|
+
alias :to_enum :enum_for
|
|
286
|
+
|
|
287
|
+
# 暦注の計算
|
|
288
|
+
#
|
|
289
|
+
# @param [When::TM::TemporalPosition] date 暦注を計算する日時
|
|
290
|
+
# @param [When::TM::TemporalPosition 以外] date When::TM::TemporalPosition に変換して使用する
|
|
291
|
+
# @param [String] options { :notes => String } という Hash の指定と等価
|
|
292
|
+
# @param [Integer] options { :indices => Integer} という Hash の指定と等価
|
|
293
|
+
# @param [Hash] options 下記のとおり
|
|
294
|
+
# @option options [Integer] :indices Integerで指定した暦座標の暦注を計算
|
|
295
|
+
# [ When::DAY ( 0) - 日 ]
|
|
296
|
+
# [ When::MONTH(-1) - 月 ]
|
|
297
|
+
# [ When::YEAR (-2) - 年 ]
|
|
298
|
+
#
|
|
299
|
+
# @option options [Array<Integer>] :indices Integerで指定したすべて暦座標の暦注を計算
|
|
300
|
+
# @option options [nil] :indices すべての暦座標の暦注を計算(デフォルト)
|
|
301
|
+
# @option options [String] :notes 計算する暦注名(日の暦注)
|
|
302
|
+
# @option options [Integer] :notes 計算する暦注のビット配列(日の暦注)
|
|
303
|
+
# @option options [Array<Array<String>>] :notes 計算する暦注名の Array の Array
|
|
304
|
+
# @option options [Array<Integer>] :notes 計算する暦注のビット配列の Array
|
|
305
|
+
# @option options [:all] :notes すべての暦注を計算
|
|
306
|
+
# @option options [:prime, nil] :notes @prime に登録した暦注を計算、@prime未登録なら :all と同じ(デフォルト)
|
|
307
|
+
# @option options [Hash] :persistence {ユリウス通日=>暦注計算結果}を保持する永続オブジェクト
|
|
308
|
+
# @option options [Hash] :conditions 暦注計算の条件
|
|
309
|
+
# [ :location => 暦注計算の基準となる場所(String or When::Coordinates::Spatial) ]
|
|
310
|
+
# [ その他のキー => 個々の暦注クラスごとにその他のキーを使用できる ]
|
|
311
|
+
#
|
|
312
|
+
# @option options [Hash] その他のキー date を When::TM::TemporalPosition に変換するために使用する
|
|
313
|
+
# see {When::TM::TemporalPosition._instance}
|
|
314
|
+
#
|
|
315
|
+
# @note CalendarNoteオブジェクト生成時に _normalize メソッド内で @prime 変数を設定しておけば、
|
|
316
|
+
# 本メソッドの :prime オプションで参照される。(Balinese#_normalize等参照)
|
|
317
|
+
#
|
|
318
|
+
# @note 暦注のビットアドレスは、暦注サブクラスのNotes定数の中の定義順序による。
|
|
319
|
+
# When::CalendarNote クラスの場合 new の引数とした暦注要素リストの定義順序による。
|
|
320
|
+
# ビットアドレスの値が 1 の暦注が計算対象となる。
|
|
321
|
+
#
|
|
322
|
+
# @return [Array<Array<Hash>>] 暦注計算結果(When::CalendarNote::NotesContainerモジュールをextendしている)
|
|
323
|
+
# [ :note => 暦注要素 (When::Coordinates::Residue, String, When::BasicTypes::M17n) ]
|
|
324
|
+
# [ :value => 暦注の値 (When::Coordinates::Residue, String, When::BasicTypes::M17n, When::TM::TemporalPosition) ]
|
|
325
|
+
#
|
|
326
|
+
# @note
|
|
327
|
+
# 戻り値の :value が When::TM::TemporalPosition の場合、その日時オブジェクトの events[0] に暦注名の入った
|
|
328
|
+
# 暦注に該当する日付である。(例) Christian クラス で easter を計算した場合、当該年の復活祭の日付オブジェクトが返る。
|
|
329
|
+
# @note
|
|
330
|
+
# 暦注サブクラスの場合、暦注要素が増えたり、:note の暦注要素の型が変わったりすることがある。
|
|
331
|
+
#
|
|
332
|
+
def notes(date, options={})
|
|
333
|
+
dates, indices, notes, persistence, conditions, options = _parse_note(date, options)
|
|
334
|
+
retrieved = NotesContainer.retrieve(persistence, date.to_i)
|
|
335
|
+
return retrieved unless retrieved == false
|
|
336
|
+
NotesContainer.register(indices.map {|i|
|
|
337
|
+
next [] unless i <= date.precision
|
|
338
|
+
_note_values(dates, notes[i-1], _all_keys[i-1], _elements[i-1]) do |dates, focused_notes, notes_hash|
|
|
339
|
+
focused_notes.each do |note|
|
|
340
|
+
notes_hash[note] ||= _note_element(note, i, conditions, dates)
|
|
341
|
+
end
|
|
342
|
+
notes_hash
|
|
343
|
+
end
|
|
344
|
+
}, persistence, date.to_i)
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
#
|
|
348
|
+
# 暦注の一致 or 不一致
|
|
349
|
+
#
|
|
350
|
+
# @param [When::TM::TemporalPosition] date 暦注を確認する日時
|
|
351
|
+
# @param [When::TM::TemporalPosition 以外] date When::TM::TemporalPosition に変換して使用する
|
|
352
|
+
# @param [String] options { :notes => String } または { :value => String } という Hash の指定と等価
|
|
353
|
+
# (指定の notes が存在する場合は前者、しない場合は後者)
|
|
354
|
+
# @param [Integer] options { :indices => Integer } という Hash の指定と等価
|
|
355
|
+
# @param [Hash] options 下記のとおり
|
|
356
|
+
# @option options [暦注の値] :value 確認する暦注の値(または正規表現)
|
|
357
|
+
# @option options [それぞれ] その他 {When::CalendarNote#notes} を参照
|
|
358
|
+
#
|
|
359
|
+
# @return [Boolean]
|
|
360
|
+
# [ true - 暦注が一致 ]
|
|
361
|
+
# [ false - 暦注が不一致 ]
|
|
362
|
+
#
|
|
363
|
+
def note?(date, options={})
|
|
364
|
+
options = _find_note(options) if options.kind_of?(String) || options.kind_of?(Regexp)
|
|
365
|
+
pattern = options.delete(:value) if options.kind_of?(Hash)
|
|
366
|
+
result = notes(date, options)
|
|
367
|
+
result.flatten!
|
|
368
|
+
result.delete_if {|hash| hash.empty?}
|
|
369
|
+
return false unless result.size > 0
|
|
370
|
+
return true unless pattern
|
|
371
|
+
result.each do |hash|
|
|
372
|
+
return true if NotesContainer.verify(pattern, hash[:value])
|
|
373
|
+
end
|
|
374
|
+
return false
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
# 年の名前を暦注として返す
|
|
378
|
+
# @method year
|
|
379
|
+
# @return [When::BasicTypes::M17n]
|
|
380
|
+
|
|
381
|
+
# 月の名前を暦注として返す
|
|
382
|
+
# @method month
|
|
383
|
+
# @return [When::BasicTypes::M17n]
|
|
384
|
+
|
|
385
|
+
# 日の名前を暦注として返す
|
|
386
|
+
# @method day
|
|
387
|
+
# @return [When::BasicTypes::M17n]
|
|
388
|
+
|
|
389
|
+
#
|
|
390
|
+
# 標準的な暦注として、暦座標の値の名前を暦注として返すメソッドを登録
|
|
391
|
+
#
|
|
392
|
+
# @private
|
|
393
|
+
['year', 'month', 'day'].each do |c|
|
|
394
|
+
module_eval %Q{
|
|
395
|
+
def #{c}(date)
|
|
396
|
+
date.name('#{c}')
|
|
397
|
+
end
|
|
398
|
+
}
|
|
399
|
+
end
|
|
400
|
+
|
|
401
|
+
private
|
|
402
|
+
|
|
403
|
+
#
|
|
404
|
+
# 年月日暦注計算の共通処理 - コールバック元
|
|
405
|
+
#
|
|
406
|
+
def _note_values(dates, focused_notes, all_notes, note_objects)
|
|
407
|
+
return [] unless dates && all_notes
|
|
408
|
+
|
|
409
|
+
# prepare focused notes
|
|
410
|
+
case focused_notes
|
|
411
|
+
when Integer
|
|
412
|
+
bits = ~focused_notes << 1
|
|
413
|
+
focused_notes = all_notes.dup.delete_if { (bits>>=1)[0] == 1 }
|
|
414
|
+
when []
|
|
415
|
+
focused_notes = all_notes
|
|
416
|
+
when nil
|
|
417
|
+
focused_notes = []
|
|
418
|
+
end
|
|
419
|
+
focused_notes = focused_notes.dup
|
|
420
|
+
not_focused_notes = all_notes - focused_notes
|
|
421
|
+
notes = {}
|
|
422
|
+
not_focused_notes.each do |note|
|
|
423
|
+
notes[note] = true
|
|
424
|
+
end
|
|
425
|
+
focused_notes.each do |note|
|
|
426
|
+
notes[note] = nil
|
|
427
|
+
end
|
|
428
|
+
|
|
429
|
+
# update notes
|
|
430
|
+
focused_notes_actual = focused_notes.dup
|
|
431
|
+
notes = yield(dates, focused_notes_actual, notes)
|
|
432
|
+
notes.keys.each do |note|
|
|
433
|
+
notes.delete(note) unless focused_notes_actual.include?(note)
|
|
434
|
+
end
|
|
435
|
+
|
|
436
|
+
# return Array of Hash
|
|
437
|
+
focused_notes.map {|note|
|
|
438
|
+
case notes[note]
|
|
439
|
+
when nil, false ; {}
|
|
440
|
+
when Hash ; {:note=>note_objects[note].label}.merge(notes[note])
|
|
441
|
+
else
|
|
442
|
+
if note_objects[note].respond_to?(:to_note_hash)
|
|
443
|
+
note_objects[note].to_note_hash(notes[note], dates)
|
|
444
|
+
else
|
|
445
|
+
{:note=>note_objects[note].label, :value=>notes[note]}
|
|
446
|
+
end
|
|
447
|
+
end
|
|
448
|
+
}
|
|
449
|
+
end
|
|
450
|
+
|
|
451
|
+
#
|
|
452
|
+
# オブジェクトの正規化
|
|
453
|
+
#
|
|
454
|
+
def _normalize(args=[], options={})
|
|
455
|
+
@_elements = (args.size == 0 && self.class.const_defined?(:Notes)) ?
|
|
456
|
+
When::Parts::Resource.base_uri + self.class.to_s.split(/::/)[1..-1].join('/') + '/Notes' :
|
|
457
|
+
_to_iri(args, options[:prefix] || '_co:')
|
|
458
|
+
if @_elements.kind_of?(Array)
|
|
459
|
+
@_elements.each do |e|
|
|
460
|
+
e.extend LabelAccess
|
|
461
|
+
end
|
|
462
|
+
end
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
#
|
|
466
|
+
# 再帰的に配列の中を Resource化する
|
|
467
|
+
#
|
|
468
|
+
def _to_iri(args, prefix)
|
|
469
|
+
args.map {|arg|
|
|
470
|
+
case arg
|
|
471
|
+
when String
|
|
472
|
+
arg, method = $1, $2 if (arg =~ /\A(.+)#([_A-Z0-9]+)\z/i)
|
|
473
|
+
obj = When.Resource(arg, prefix)
|
|
474
|
+
obj = obj.copy(method) if method
|
|
475
|
+
obj
|
|
476
|
+
when Array
|
|
477
|
+
_to_iri(arg, prefix)
|
|
478
|
+
else
|
|
479
|
+
arg
|
|
480
|
+
end
|
|
481
|
+
}
|
|
482
|
+
end
|
|
483
|
+
|
|
484
|
+
#
|
|
485
|
+
# 暦日を当該暦注計算用クラスに変換
|
|
486
|
+
#
|
|
487
|
+
# 基底クラスである本クラスでは何もしないで、引数をそのまま返す
|
|
488
|
+
#
|
|
489
|
+
def _to_date_for_note(date)
|
|
490
|
+
date
|
|
491
|
+
end
|
|
492
|
+
|
|
493
|
+
# 暦注要素
|
|
494
|
+
#
|
|
495
|
+
# @return [Array<Array<When::Parts::Resource>>]
|
|
496
|
+
#
|
|
497
|
+
def _elements
|
|
498
|
+
@_elements = When.Resource(@_elements) if @_elements.kind_of?(String)
|
|
499
|
+
@_elements
|
|
500
|
+
end
|
|
501
|
+
|
|
502
|
+
#
|
|
503
|
+
# [[暦注名]](全暦注)
|
|
504
|
+
#
|
|
505
|
+
# @return [Array<Array<String, When::BasicTypes::M17n>>]
|
|
506
|
+
#
|
|
507
|
+
def _all_keys
|
|
508
|
+
@_all_keys ||= _elements.map { |c|
|
|
509
|
+
c.map {|n|
|
|
510
|
+
n.label.to_s
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
end
|
|
514
|
+
|
|
515
|
+
#
|
|
516
|
+
# [[暦注名]](主要暦注)
|
|
517
|
+
#
|
|
518
|
+
# @return [Array<Array<When::Parts::Resource>>]
|
|
519
|
+
#
|
|
520
|
+
def _prime_keys
|
|
521
|
+
@prime ||= _all_keys
|
|
522
|
+
end
|
|
523
|
+
|
|
524
|
+
#
|
|
525
|
+
# notes メソッドの引数を parse する
|
|
526
|
+
#
|
|
527
|
+
# @return [Array] dates, indices, notes
|
|
528
|
+
#
|
|
529
|
+
def _parse_note(date, options)
|
|
530
|
+
options =
|
|
531
|
+
case options
|
|
532
|
+
when Hash ; When::EncodingConversion.to_internal_encoding(options)
|
|
533
|
+
when String ; {:notes => When::EncodingConversion.to_internal_encoding(options)}
|
|
534
|
+
when Integer ; {:indices => options}
|
|
535
|
+
else ; {}
|
|
536
|
+
end
|
|
537
|
+
conditions = options.delete(:conditions) || {}
|
|
538
|
+
_opt = options.dup
|
|
539
|
+
persistence = _opt.delete(:persistence)
|
|
540
|
+
notes = _notes(_opt.delete(:notes) || :prime)
|
|
541
|
+
indices = _indices(_opt.delete(:indices), notes)
|
|
542
|
+
_opt.keys.each do |key|
|
|
543
|
+
conditions[key] = _opt[key] unless date.class::FormOptions.include?(key)
|
|
544
|
+
end
|
|
545
|
+
[_to_date_for_note(date), indices, notes, persistence, conditions, options]
|
|
546
|
+
end
|
|
547
|
+
|
|
548
|
+
#
|
|
549
|
+
# 暦注を計算する暦座標の配列
|
|
550
|
+
#
|
|
551
|
+
# @return [Array<Integer>]
|
|
552
|
+
#
|
|
553
|
+
def _indices(indices, notes)
|
|
554
|
+
case indices
|
|
555
|
+
when nil ; (0...notes.size).to_a.reverse.map {|i| -i}
|
|
556
|
+
when Range ; indices.to_a
|
|
557
|
+
when Array ; indices
|
|
558
|
+
else ; [indices.to_i]
|
|
559
|
+
end
|
|
560
|
+
end
|
|
561
|
+
|
|
562
|
+
#
|
|
563
|
+
# notes メソッドの 文字列引数の意味を解釈する
|
|
564
|
+
#
|
|
565
|
+
# @return [Hash] options for note String
|
|
566
|
+
#
|
|
567
|
+
def _find_note(note)
|
|
568
|
+
note = When::EncodingConversion.to_internal_encoding(note)
|
|
569
|
+
_elements.each_index do |index|
|
|
570
|
+
return {:notes=>note, :indices => [-index]} if _elements[-1-index]._pool[note]
|
|
571
|
+
end
|
|
572
|
+
{:value => note}
|
|
573
|
+
end
|
|
574
|
+
|
|
575
|
+
#
|
|
576
|
+
# 計算する暦注
|
|
577
|
+
#
|
|
578
|
+
# @return [Array<Array<String>, Integer>]
|
|
579
|
+
#
|
|
580
|
+
def _notes(notes)
|
|
581
|
+
case notes
|
|
582
|
+
when :all ; _all_keys
|
|
583
|
+
when :prime ; _prime_keys
|
|
584
|
+
when Integer ; [notes]
|
|
585
|
+
when String ; [[notes]]
|
|
586
|
+
else ; notes
|
|
587
|
+
end
|
|
588
|
+
end
|
|
589
|
+
|
|
590
|
+
#
|
|
591
|
+
# 暦注の計算
|
|
592
|
+
#
|
|
593
|
+
# @return [Object] 暦注の値
|
|
594
|
+
#
|
|
595
|
+
def _note_element(note, index, conditions, dates)
|
|
596
|
+
void, event, *parameter = note.split(/\A([^\d]+)/)
|
|
597
|
+
method = event.downcase
|
|
598
|
+
parameter << conditions unless conditions.empty?
|
|
599
|
+
return send(method, dates, *parameter) if respond_to?(method)
|
|
600
|
+
root = _elements[index-1][note]
|
|
601
|
+
parent, leaf = root.iri.split('/Notes') if root.kind_of?(When::Parts::Resource)
|
|
602
|
+
parent = When.Resource(parent) if leaf
|
|
603
|
+
return parent.send(method, dates, *parameter) if parent.respond_to?(method)
|
|
604
|
+
root.send(When::Coordinates::PRECISION_NAME[index].downcase, dates)
|
|
605
|
+
end
|
|
606
|
+
|
|
607
|
+
#
|
|
608
|
+
# イベントを取得する Enumerator
|
|
609
|
+
#
|
|
610
|
+
class Enumerator < When::Parts::Enumerator
|
|
611
|
+
|
|
612
|
+
#
|
|
613
|
+
# 次のイベントを得る
|
|
614
|
+
#
|
|
615
|
+
# @return [When::TM::TemporalPosition]
|
|
616
|
+
#
|
|
617
|
+
def _succ
|
|
618
|
+
@current = (@current==:first) ? @first : event_eval(@current + @delta)
|
|
619
|
+
end
|
|
620
|
+
|
|
621
|
+
# オブジェクトの生成
|
|
622
|
+
#
|
|
623
|
+
# @overload initialize(parent, range, options)
|
|
624
|
+
# @param [When::CalendarNote] parent 暦注アルゴリズム
|
|
625
|
+
# @param [Range, When::Parts::GeometricComplex] range
|
|
626
|
+
# [ 始点 - range.first ]
|
|
627
|
+
# [ 終点 - range.last ]
|
|
628
|
+
# @param [Hash] options 以下の通り
|
|
629
|
+
# @option options [String] :event イベント名
|
|
630
|
+
# @option options [Integer] :count_limit 繰り返し回数(デフォルトは指定なし)
|
|
631
|
+
#
|
|
632
|
+
# @overload initialize(parent, first, direction, options)
|
|
633
|
+
# @param [When::CalendarNote] parent 暦注アルゴリズム
|
|
634
|
+
# @param [When::TM::TemporalPosition] first 始点
|
|
635
|
+
# @param [Symbol] direction (options[:direction]で渡してもよい)
|
|
636
|
+
# [:forward] 昇順(デフォルト)
|
|
637
|
+
# [:reverse] 降順
|
|
638
|
+
# @param [Hash] options 以下の通り
|
|
639
|
+
# @option options [String] :event イベント名
|
|
640
|
+
# @option options [Integer] :count_limit 繰り返し回数(デフォルトは指定なし)
|
|
641
|
+
#
|
|
642
|
+
def initialize(*args)
|
|
643
|
+
if args[1].kind_of?(Range)
|
|
644
|
+
parent, range, options = args
|
|
645
|
+
first = range.first
|
|
646
|
+
last = range.last
|
|
647
|
+
direction = first < last ? :forward : :reverse
|
|
648
|
+
else
|
|
649
|
+
parent, first, direction, options = args
|
|
650
|
+
end
|
|
651
|
+
direction = options[:direction] if options[:direction]
|
|
652
|
+
@parent = parent
|
|
653
|
+
event = options.delete(:event)
|
|
654
|
+
case event
|
|
655
|
+
when String ; void, @event, @parameter = event.split(/\A([^\d]+)/)
|
|
656
|
+
else ; @event, @parameter = [parent.event, event]
|
|
657
|
+
end
|
|
658
|
+
@delta = @parent.send((@event+'_delta').to_sym, @parameter)
|
|
659
|
+
instance_eval %Q{
|
|
660
|
+
def event_eval(date)
|
|
661
|
+
@parent.#{@event}(date, @parameter)
|
|
662
|
+
end
|
|
663
|
+
}
|
|
664
|
+
date = event_eval(first)
|
|
665
|
+
if direction == :reverse
|
|
666
|
+
@delta = -@delta
|
|
667
|
+
date = event_eval(first + @delta) if first.to_i < date.to_i
|
|
668
|
+
else
|
|
669
|
+
date = event_eval(first + @delta) if first.to_i > date.to_i
|
|
670
|
+
end
|
|
671
|
+
range ?
|
|
672
|
+
super(@parent, range.exclude_end? ? date...last : date..last, options) :
|
|
673
|
+
super(@parent, date, direction, options)
|
|
674
|
+
end
|
|
675
|
+
end
|
|
676
|
+
|
|
677
|
+
#
|
|
678
|
+
# 暦週
|
|
679
|
+
#
|
|
680
|
+
class Week < CalendarNote
|
|
681
|
+
|
|
682
|
+
#
|
|
683
|
+
# 暦週要素
|
|
684
|
+
#
|
|
685
|
+
class DayOfWeek < When::BasicTypes::M17n
|
|
686
|
+
|
|
687
|
+
# 当該暦週要素の標準的な出現間隔
|
|
688
|
+
#
|
|
689
|
+
# @return [Integer]
|
|
690
|
+
#
|
|
691
|
+
attr_reader :delta
|
|
692
|
+
|
|
693
|
+
# 所属する暦週オブジェクト
|
|
694
|
+
#
|
|
695
|
+
# @return [When::CalendarNote]
|
|
696
|
+
#
|
|
697
|
+
def week_note
|
|
698
|
+
@week_note ||= When.CalendarNote(iri.split('/Notes').first)
|
|
699
|
+
end
|
|
700
|
+
|
|
701
|
+
# 当日または直前に当該暦週要素が現れる日付
|
|
702
|
+
#
|
|
703
|
+
# @return [When::TM::TemporalPosition]
|
|
704
|
+
#
|
|
705
|
+
def just_or_last(date)
|
|
706
|
+
date = week_note._to_date_for_note(date)
|
|
707
|
+
([parent.child.length, @delta[When::DAY]].max*2).times do
|
|
708
|
+
if equal?(week_note.week(date)[:value])
|
|
709
|
+
date.events ||= []
|
|
710
|
+
date.events << self
|
|
711
|
+
return date
|
|
712
|
+
end
|
|
713
|
+
date -= When::P1D
|
|
714
|
+
end
|
|
715
|
+
raise ArgumentError, "#{self} not found"
|
|
716
|
+
end
|
|
717
|
+
|
|
718
|
+
private
|
|
719
|
+
|
|
720
|
+
#
|
|
721
|
+
# オブジェクトの正規化
|
|
722
|
+
#
|
|
723
|
+
def initialize(*args)
|
|
724
|
+
super
|
|
725
|
+
@delta = When::P1D * @delta.to_i if @delta && ! @delta.kind_of?(When::TM::Duration)
|
|
726
|
+
end
|
|
727
|
+
end
|
|
728
|
+
|
|
729
|
+
#
|
|
730
|
+
# 曜日の名前の一覧
|
|
731
|
+
#
|
|
732
|
+
# @param [When::TM::TemporalPosition] date
|
|
733
|
+
#
|
|
734
|
+
# @return [Array<When::CalendarNote::Week::DayOfWeek>]
|
|
735
|
+
#
|
|
736
|
+
def week_labels(date)
|
|
737
|
+
@days_of_week.child[0...week(date)[:position].last]
|
|
738
|
+
end
|
|
739
|
+
|
|
740
|
+
# 七曜
|
|
741
|
+
#
|
|
742
|
+
# @param [When::TM::TemporalPosition] date
|
|
743
|
+
#
|
|
744
|
+
# @return [When::Coordinates::Residue] 七曜
|
|
745
|
+
#
|
|
746
|
+
def common_week(date)
|
|
747
|
+
When.Residue('Week')[date.to_i % 7]
|
|
748
|
+
end
|
|
749
|
+
|
|
750
|
+
#
|
|
751
|
+
# オブジェクトの正規化
|
|
752
|
+
#
|
|
753
|
+
def _normalize(args=[], options={})
|
|
754
|
+
super
|
|
755
|
+
@days_of_week ||= When.CalendarNote("#{self.class.to_s.split('::').last}/Notes::day::Week")
|
|
756
|
+
@days_of_week.child.length.times do |index|
|
|
757
|
+
name = @days_of_week.child[index].translate('en').downcase.gsub(/[- ]/, '_')
|
|
758
|
+
self.class.module_eval %Q{
|
|
759
|
+
def #{name}(date, parameter=nil)
|
|
760
|
+
@days_of_week.child[#{index}].just_or_last(date)
|
|
761
|
+
end
|
|
762
|
+
} unless respond_to?(name)
|
|
763
|
+
self.class.module_eval %Q{
|
|
764
|
+
def #{name}_delta(parameter=nil)
|
|
765
|
+
@days_of_week.child[#{index}].delta
|
|
766
|
+
end
|
|
767
|
+
} unless respond_to?(name + '_delta')
|
|
768
|
+
end
|
|
769
|
+
end
|
|
770
|
+
|
|
771
|
+
#
|
|
772
|
+
# イベントを取得する Enumerator
|
|
773
|
+
#
|
|
774
|
+
class Enumerator < When::CalendarNote::Enumerator
|
|
775
|
+
|
|
776
|
+
#
|
|
777
|
+
# 次のイベントを得る
|
|
778
|
+
#
|
|
779
|
+
# @return [When::TM::TemporalPosition]
|
|
780
|
+
#
|
|
781
|
+
def succ
|
|
782
|
+
value = @current
|
|
783
|
+
plus = @delta.sign > 0
|
|
784
|
+
if @current==:first
|
|
785
|
+
@first = event_eval(@first) unless plus
|
|
786
|
+
@current = @first
|
|
787
|
+
else
|
|
788
|
+
if plus
|
|
789
|
+
@current = event_eval(@current + @delta)
|
|
790
|
+
else
|
|
791
|
+
@last = event_eval(@current - When::P1D)
|
|
792
|
+
@current = event_eval(@current + @delta)
|
|
793
|
+
unless [@current.to_i, value.to_i].include?(@last.to_i)
|
|
794
|
+
@current = @last
|
|
795
|
+
return value
|
|
796
|
+
end
|
|
797
|
+
end
|
|
798
|
+
@current = event_eval(@current + @delta * 2) if @current.to_i == value.to_i
|
|
799
|
+
end
|
|
800
|
+
return value
|
|
801
|
+
end
|
|
802
|
+
end
|
|
803
|
+
end
|
|
804
|
+
end
|
|
805
|
+
end
|