when_exe 0.3.2 → 0.3.3
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE.ja.txt +25 -25
- data/LICENSE.txt +31 -31
- data/bin/locales.rb +2 -1
- data/bin/when.rb.config +1 -1
- data/lib/when_exe.rb +70 -48
- data/lib/when_exe/basictypes.rb +99 -65
- data/lib/when_exe/calendartypes.rb +40 -178
- data/lib/when_exe/coordinates.rb +156 -62
- data/lib/when_exe/core/compatibility.rb +10 -0
- data/lib/when_exe/core/extension.rb +40 -0
- data/lib/when_exe/ephemeris.rb +112 -50
- data/lib/when_exe/icalendar.rb +125 -91
- data/lib/when_exe/inspect.rb +100 -48
- data/lib/when_exe/locales/ar.rb +48 -48
- data/lib/when_exe/locales/bg.rb +1 -1
- data/lib/when_exe/locales/bs.rb +4 -2
- data/lib/when_exe/locales/ca.rb +1 -1
- data/lib/when_exe/locales/en_CA.rb +3 -4
- data/lib/when_exe/locales/en_IE.rb +88 -0
- data/lib/when_exe/locales/en_US.rb +87 -0
- data/lib/when_exe/locales/es_CR.rb +84 -0
- data/lib/when_exe/locales/es_EC.rb +85 -0
- data/lib/when_exe/locales/es_PA.rb +85 -0
- data/lib/when_exe/locales/fr.rb +39 -39
- data/lib/when_exe/locales/hu.rb +15 -14
- data/lib/when_exe/locales/it.rb +1 -1
- data/lib/when_exe/locales/ja.rb +2 -2
- data/lib/when_exe/locales/locales.rb +7 -0
- data/lib/when_exe/locales/lt.rb +21 -19
- data/lib/when_exe/locales/ms.rb +84 -0
- data/lib/when_exe/locales/nl.rb +2 -2
- data/lib/when_exe/locales/ru.rb +1 -1
- data/lib/when_exe/locales/uk.rb +1 -1
- data/lib/when_exe/locales/ur.rb +84 -0
- data/lib/when_exe/mini_application.rb +44 -43
- data/lib/when_exe/parts/enumerator.rb +3 -3
- data/lib/when_exe/parts/geometric_complex.rb +6 -1
- data/lib/when_exe/parts/locale.rb +49 -18
- data/lib/when_exe/parts/method_cash.rb +61 -0
- data/lib/when_exe/parts/resource.rb +221 -106
- data/lib/when_exe/parts/timezone.rb +70 -33
- data/lib/when_exe/region/bahai.rb +2 -2
- data/lib/when_exe/region/balinese.rb +40 -43
- data/lib/when_exe/region/chinese.rb +93 -33
- data/lib/when_exe/region/chinese_calendar.rb +117 -1
- data/lib/when_exe/region/chinese_epoch.rb +65 -10
- data/lib/when_exe/region/christian.rb +97 -2
- data/lib/when_exe/region/ephemeric_notes.rb +353 -0
- data/lib/when_exe/region/french.rb +1 -1
- data/lib/when_exe/region/geologicalage.rb +171 -171
- data/lib/when_exe/region/indian.rb +18 -14
- data/lib/when_exe/region/iranian.rb +1 -1
- data/lib/when_exe/region/japanese.rb +49 -12
- data/lib/when_exe/region/japanese_notes.rb +838 -507
- data/lib/when_exe/region/japanese_residues.rb +724 -662
- data/lib/when_exe/region/javanese.rb +7 -7
- data/lib/when_exe/region/mayan.rb +19 -17
- data/lib/when_exe/region/nihon_shoki.rb +3 -3
- data/lib/when_exe/region/residue.rb +29 -28
- data/lib/when_exe/region/shire.rb +2 -2
- data/lib/when_exe/region/tibetan.rb +87 -5
- data/lib/when_exe/region/world.rb +1 -1
- data/lib/when_exe/timestandard.rb +85 -7
- data/lib/when_exe/tmobjects.rb +32 -4
- data/lib/when_exe/tmposition.rb +104 -55
- data/lib/when_exe/tmreference.rb +157 -60
- data/lib/when_exe/version.rb +2 -2
- data/test/examples/JapanHolidays.ics +3 -3
- data/test/examples/JapanHolidaysRFC6350.ics +499 -0
- data/test/examples/Residue.m17n +3 -2
- data/test/examples/Spatial.m17n +3 -3
- data/test/examples/USA-DST.ics +27 -27
- data/test/examples/today.rb +1 -1
- data/test/test.rb +4 -2
- data/test/test/basictypes.rb +40 -15
- data/test/test/coordinates.rb +9 -4
- data/test/test/icalendar.rb +24 -14
- data/test/test/inspect.rb +5 -3
- data/test/test/parts.rb +11 -2
- data/test/test/region/chinese.rb +4 -4
- data/test/test/region/civil.rb +124 -0
- data/test/test/region/geologicalage.rb +5 -2
- data/test/test/region/indian.rb +2 -0
- data/test/test/region/japanese.rb +156 -1
- data/test/test/region/jewish.rb +3 -3
- data/test/test/region/m17n.rb +9 -9
- data/test/test/region/mayan.rb +122 -5
- data/test/test/region/residue.rb +1 -1
- data/test/test/tmobjects.rb +27 -64
- data/test/test/tmposition.rb +48 -1
- data/test/test/tmreference.rb +66 -4
- data/when_exe.gemspec +1 -1
- metadata +15 -6
data/lib/when_exe/icalendar.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
=begin
|
3
|
-
Copyright (C) 2011-
|
3
|
+
Copyright (C) 2011-2014 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
|
@@ -86,7 +86,7 @@ module When::V
|
|
86
86
|
|
87
87
|
#
|
88
88
|
# iCalendar クラス群の属性
|
89
|
-
# @return [Hash] { String => When::Parts::Resource::
|
89
|
+
# @return [Hash] { String => When::Parts::Resource::ContentLine }
|
90
90
|
#
|
91
91
|
attr_reader :property
|
92
92
|
|
@@ -128,9 +128,27 @@ module When::V
|
|
128
128
|
raise ArgumentError, "No enumerator exists" if (enumerators.length==0)
|
129
129
|
|
130
130
|
# Enumerator の生成
|
131
|
-
|
132
|
-
|
133
|
-
|
131
|
+
enumerator =
|
132
|
+
if (enumerators.length==1 && exdate.node.size==0)
|
133
|
+
enumerators[0]
|
134
|
+
else
|
135
|
+
options[:exdate] = exdate
|
136
|
+
When::Parts::Enumerator::Integrated.new(self, enumerators, *args)
|
137
|
+
end
|
138
|
+
if ::Object.const_defined?(:Date) && (args[0].kind_of?(Range) ? args[0].first : args[0]).kind_of?(::Date)
|
139
|
+
enumerator.instance_eval %Q{
|
140
|
+
alias :_succ_of_super :succ
|
141
|
+
def succ
|
142
|
+
result = _succ_of_super
|
143
|
+
case result
|
144
|
+
when When::TM::DateAndTime ; result.to_date_time
|
145
|
+
when When::TM::CalDate ; result.to_date
|
146
|
+
else ; result
|
147
|
+
end
|
148
|
+
end
|
149
|
+
}
|
150
|
+
end
|
151
|
+
enumerator
|
134
152
|
end
|
135
153
|
alias :to_enum :_enumerator
|
136
154
|
alias :enum_for :_enumerator
|
@@ -147,7 +165,14 @@ module When::V
|
|
147
165
|
@_pool['..'] = options['..']
|
148
166
|
|
149
167
|
# parsed 部の属性化
|
150
|
-
|
168
|
+
@property = {}
|
169
|
+
@namespace = @_pool['..'].respond_to?(:namespace) ? @_pool['..'].namespace : {}
|
170
|
+
if options['.']
|
171
|
+
_parse_from_file(options)
|
172
|
+
else
|
173
|
+
_parse_from_code(options)
|
174
|
+
end
|
175
|
+
_set_variables
|
151
176
|
|
152
177
|
# 属性の存在チェック & 設定
|
153
178
|
_initialize_attributes(_attribute_appearance(self.class::Properties)) # .const_get(:Properties)))
|
@@ -156,29 +181,47 @@ module When::V
|
|
156
181
|
_child(options, self.class::Classes) #.const_get(:Classes))
|
157
182
|
end
|
158
183
|
|
159
|
-
#
|
160
|
-
def
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
184
|
+
# ファイルからの属性読み込み
|
185
|
+
def _parse_from_file(options)
|
186
|
+
options['.'].each do |v|
|
187
|
+
v = When::Parts::Resource._parse(v)
|
188
|
+
_parse_altid(@property, v) if v.kind_of?(ContentLine)
|
189
|
+
end
|
190
|
+
|
191
|
+
keys = @property.keys
|
192
|
+
if keys.delete('namespace')
|
193
|
+
content = @property['namespace'][0]
|
194
|
+
@property['namespace'] = content if @property['namespace'].size == 1
|
195
|
+
if content.attribute['prefix']
|
196
|
+
begin
|
197
|
+
@namespace[content.attribute['prefix'].object] = content.object
|
198
|
+
end while (content = content.same_altid)
|
199
|
+
else
|
200
|
+
@namespace.update(When::Parts::Locale._namespace(content.object))
|
172
201
|
end
|
173
|
-
|
174
|
-
|
175
|
-
|
202
|
+
end
|
203
|
+
|
204
|
+
keys.each do |key|
|
205
|
+
@property[key].each do |content|
|
206
|
+
content.object = When::BasicTypes::M17n.new(content, @namespace, []) if content.same_altid
|
176
207
|
end
|
177
|
-
@property[
|
178
|
-
|
179
|
-
|
180
|
-
|
208
|
+
@property[key] = @property[key][0] if @property[key].size == 1
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
# コードからの属性読み込み
|
213
|
+
def _parse_from_code(options)
|
214
|
+
options.each_pair do |key, value|
|
215
|
+
@property[key] = ContentLine.new(key, value) if key.kind_of?(String)
|
181
216
|
end
|
217
|
+
@property['dtstamp'] ||= ContentLine.new('dtstamp',
|
218
|
+
When.now.to_s.gsub(/[-:]/,'')) if self.class::Properties[0].index('dtstamp')
|
219
|
+
@property['uid'] ||= ContentLine.new('uid',
|
220
|
+
@property['dtstamp'].object + '-auto') if self.class::Properties[0].index('uid')
|
221
|
+
end
|
222
|
+
|
223
|
+
# @propertyの個別属性化
|
224
|
+
def _set_variables
|
182
225
|
@property.each_key do |key|
|
183
226
|
next if respond_to?(key)
|
184
227
|
instance_eval %Q{
|
@@ -220,7 +263,7 @@ module When::V
|
|
220
263
|
|
221
264
|
# REQUIRED but MUST NOT occur more than once
|
222
265
|
require_unique.each do |key|
|
223
|
-
unless @property[key].kind_of?(When::Parts::Resource::
|
266
|
+
unless @property[key].kind_of?(When::Parts::Resource::ContentLine)
|
224
267
|
raise ArgumentError, "The #{key.upcase.gsub(/_/,'-')} is REQUIRED but MUST NOT occur more than once"
|
225
268
|
end
|
226
269
|
end
|
@@ -230,7 +273,7 @@ module When::V
|
|
230
273
|
unless @property[key]
|
231
274
|
raise ArgumentError, "The #{key.upcase.gsub(/_/,'-')} is REQUIRED and MAY occur more than once"
|
232
275
|
end
|
233
|
-
@property[key] = [@property[key]] if (@property[key].kind_of?(When::Parts::Resource::
|
276
|
+
@property[key] = [@property[key]] if (@property[key].kind_of?(When::Parts::Resource::ContentLine))
|
234
277
|
end
|
235
278
|
|
236
279
|
# OPTIONAL but MUST NOT occur more than once
|
@@ -249,7 +292,7 @@ module When::V
|
|
249
292
|
|
250
293
|
# OPTIONAL and MAY occur more than once
|
251
294
|
(optional + DefaultOptional).each do |key|
|
252
|
-
@property[key] = [@property[key]] if (@property[key].kind_of?(When::Parts::Resource::
|
295
|
+
@property[key] = [@property[key]] if (@property[key].kind_of?(When::Parts::Resource::ContentLine))
|
253
296
|
end
|
254
297
|
|
255
298
|
# Other Properties
|
@@ -269,10 +312,6 @@ module When::V
|
|
269
312
|
@calscale = @property['calscale'].object if @property['calscale']
|
270
313
|
@calscale = When.Resource((@calscale||'GREGORIAN').capitalize, '_c:') unless (@calscale.kind_of?(When::TM::Calendar))
|
271
314
|
|
272
|
-
# namespace の登録
|
273
|
-
@namespace = @_pool['..'].respond_to?(:namespace) ? @_pool['..'].namespace : {}
|
274
|
-
@namespace.update(When::Parts::Locale._namespace(@property['namespace'].object)) if @property['namespace']
|
275
|
-
|
276
315
|
# locale の登録
|
277
316
|
@locale = @_pool['..'].respond_to?(:locale) ? @_pool['..'].locale : []
|
278
317
|
@locale = When::Parts::Locale._locale(@property['locale'].object) if @property['locale']
|
@@ -367,7 +406,7 @@ module When::V
|
|
367
406
|
@exdate = When::Parts::GeometricComplex.new()
|
368
407
|
if (@property['rdate'])
|
369
408
|
@rdate = @property['rdate'].inject([]) do |sum, v|
|
370
|
-
if When::Parts::Resource::
|
409
|
+
if v.kind_of?(When::Parts::Resource::ContentLine)
|
371
410
|
if new_zone == ''
|
372
411
|
sum += When.when?(v.attribute['.'].split(/,/), date_options)
|
373
412
|
else
|
@@ -388,7 +427,7 @@ module When::V
|
|
388
427
|
# exdate の登録
|
389
428
|
if @property['exdate']
|
390
429
|
dates = @property['exdate'].inject([]) do |sum, v|
|
391
|
-
if When::Parts::Resource::
|
430
|
+
if v.kind_of?(When::Parts::Resource::ContentLine)
|
392
431
|
sum += When.when?(v.attribute['.'].split(/,/), date_options)
|
393
432
|
else
|
394
433
|
sum << v
|
@@ -416,7 +455,7 @@ module When::V
|
|
416
455
|
@freebusy = []
|
417
456
|
if (@property['freebusy'])
|
418
457
|
@freebusy = @property['freebusy'].inject([]) do |sum, v|
|
419
|
-
if When::Parts::Resource::
|
458
|
+
if v.kind_of?(When::Parts::Resource::ContentLine)
|
420
459
|
sum += When.when?((v.attribute['.']||v.object).split(/,/), date_options)
|
421
460
|
else
|
422
461
|
sum << v
|
@@ -454,8 +493,10 @@ module When::V
|
|
454
493
|
copy.child = @child.select {|ev|
|
455
494
|
if ev.kind_of?(Event)
|
456
495
|
keys.each_pair do |key, value|
|
457
|
-
|
458
|
-
break unless
|
496
|
+
case value
|
497
|
+
when String ; break unless ev.property[key].object.index(value)
|
498
|
+
when Regexp ; break unless (ev.property[key].object =~ value)
|
499
|
+
end
|
459
500
|
end
|
460
501
|
else
|
461
502
|
true
|
@@ -467,7 +508,7 @@ module When::V
|
|
467
508
|
# @private
|
468
509
|
def _enumerator_list(args)
|
469
510
|
(@child.reject {|el| !el.kind_of?(Event)}).inject([]) { |sum, ev|
|
470
|
-
|
511
|
+
sum += ev._enumerator_list(args)
|
471
512
|
}
|
472
513
|
end
|
473
514
|
end
|
@@ -517,6 +558,12 @@ module When::V
|
|
517
558
|
end
|
518
559
|
end
|
519
560
|
|
561
|
+
# SUMMARY Property
|
562
|
+
#
|
563
|
+
# @return [String, When::BasicTypes::M17n]
|
564
|
+
#
|
565
|
+
attr_reader :summary
|
566
|
+
|
520
567
|
# RRULE Property
|
521
568
|
#
|
522
569
|
# @return [Hash]
|
@@ -587,7 +634,7 @@ module When::V
|
|
587
634
|
# @return [String]
|
588
635
|
#
|
589
636
|
def label
|
590
|
-
@property['uid'].object
|
637
|
+
@label ||= @property['uid'].object
|
591
638
|
end
|
592
639
|
|
593
640
|
# 最後のイベント
|
@@ -679,7 +726,7 @@ module When::V
|
|
679
726
|
# ユニーク識別名 - ACTION Property をユニーク識別名とする。
|
680
727
|
# @return [String]
|
681
728
|
def label
|
682
|
-
@property['action'].object # TODO
|
729
|
+
@label ||= @property['action'].object # TODO
|
683
730
|
end
|
684
731
|
|
685
732
|
# @private
|
@@ -692,7 +739,7 @@ module When::V
|
|
692
739
|
_parsed(options)
|
693
740
|
|
694
741
|
# 属性の存在チェック
|
695
|
-
case (@property['action'].kind_of?(When::Parts::Resource::
|
742
|
+
case (@property['action'].kind_of?(When::Parts::Resource::ContentLine) && @property['action'].object)
|
696
743
|
when 'AUDIO'
|
697
744
|
aware = _attribute_appearance([
|
698
745
|
['action', 'trigger'], [],
|
@@ -808,7 +855,7 @@ module When::V
|
|
808
855
|
# ユニーク識別名 - DTSTART Property をユニーク識別名とする
|
809
856
|
# @return [String]
|
810
857
|
def label
|
811
|
-
@property['dtstart'].attribute['.']
|
858
|
+
@label ||= @property['dtstart'].attribute['.']
|
812
859
|
end
|
813
860
|
end
|
814
861
|
|
@@ -838,22 +885,12 @@ module When::V
|
|
838
885
|
|
839
886
|
class << self; include When::Parts::Resource::Pool; end
|
840
887
|
|
841
|
-
|
842
|
-
# @return [When::TM::Clock]
|
843
|
-
attr_reader :standard
|
844
|
-
|
845
|
-
# 夏時間帯の時計
|
846
|
-
# @return [When::TM::Clock]
|
847
|
-
attr_reader :daylight
|
848
|
-
|
849
|
-
# 夏時間帯と標準時間帯の時間差
|
850
|
-
# @return [When::TM:IntervalLength]
|
851
|
-
attr_reader :difference
|
888
|
+
include When::Parts::Timezone::Base
|
852
889
|
|
853
890
|
# ユニーク識別名 - TZID Property をユニーク識別名とする
|
854
891
|
# @return [String]
|
855
892
|
def label
|
856
|
-
@property['tzid'].object
|
893
|
+
@label ||= @property['tzid'].object
|
857
894
|
end
|
858
895
|
|
859
896
|
# 同一の時間帯を用いた期間
|
@@ -866,24 +903,21 @@ module When::V
|
|
866
903
|
#
|
867
904
|
def current_period(current_date=Time.now)
|
868
905
|
current_date = When.when?(current_date) unless current_date.kind_of?(When::TM::TemporalPosition)
|
869
|
-
period = _tz_period(current_date)
|
906
|
+
period = _tz_period(current_date.universal_time)
|
870
907
|
range = period[1]
|
871
908
|
return range if range.kind_of?(Range)
|
872
909
|
GeometricComplex.new([period], !range)
|
873
910
|
end
|
874
911
|
|
875
912
|
# @private
|
876
|
-
def _daylight(
|
913
|
+
def _daylight(time)
|
877
914
|
raise ArgumentError, "Needless daylight saving time evaluation" unless _need_validate
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
deltad = zdate.universal_time - ndate.universal_time
|
885
|
-
return nprop.tzoffsetto if (deltad >= 0)
|
886
|
-
return nprop.tzoffsetfrom
|
915
|
+
frame, cal_date, clk_time = time
|
916
|
+
time = frame.to_universal_time(cal_date, clk_time, @standard) if clk_time
|
917
|
+
ndate = _neighbor_event_date(time)
|
918
|
+
nprop = ndate.clock.tz_prop
|
919
|
+
time = frame.to_universal_time(cal_date, clk_time, nprop.tzoffsetfrom) if clk_time && !@standard.equal?(nprop.tzoffsetfrom)
|
920
|
+
(time >= ndate.universal_time) ? nprop.tzoffsetto : nprop.tzoffsetfrom
|
887
921
|
end
|
888
922
|
|
889
923
|
# @private
|
@@ -922,43 +956,42 @@ module When::V
|
|
922
956
|
|
923
957
|
# 指定の日時に最も近い、時間帯変更イベントの日時
|
924
958
|
#
|
925
|
-
# @param [
|
959
|
+
# @param [Numeric] current_time 捜索の基点の日時の universal time
|
926
960
|
#
|
927
961
|
# @return [When::TM::TemporalPosition] 捜索の基点の日時に最も近い、時間帯変更イベントの日時
|
928
962
|
#
|
929
|
-
def _neighbor_event_date(
|
930
|
-
_tz_period(
|
963
|
+
def _neighbor_event_date(current_time)
|
964
|
+
_tz_period(current_time)[0]
|
931
965
|
end
|
932
966
|
|
933
|
-
def _tz_period(
|
934
|
-
|
935
|
-
return [@dtstart, false] if (universal_time <= @dtstart.universal_time)
|
967
|
+
def _tz_period(current_time)
|
968
|
+
return [@dtstart, false] if (current_time <= @dtstart.universal_time)
|
936
969
|
return [@dtstop, true ] if (@dtstop.kind_of?(When::TimeValue) &&
|
937
|
-
|
970
|
+
current_time >= @dtstop.universal_time)
|
938
971
|
|
939
972
|
# Thread 要注意 - @range は生成後に更新
|
940
973
|
synchronize do
|
941
974
|
@range.each do |range|
|
942
|
-
from =
|
943
|
-
to = range.last.universal_time -
|
975
|
+
from = current_time - range.first.universal_time
|
976
|
+
to = range.last.universal_time - current_time
|
944
977
|
return [(from < to) ? range.first : range.last, range] if (from >= 0 && to > 0)
|
945
978
|
end
|
946
|
-
early = _neighbor(
|
947
|
-
late = _neighbor(
|
948
|
-
from =
|
949
|
-
to = late.universal_time -
|
979
|
+
early = _neighbor(current_time, :reverse)
|
980
|
+
late = _neighbor(current_time, :forward)
|
981
|
+
from = current_time - early.universal_time
|
982
|
+
to = late.universal_time - current_time
|
950
983
|
@range << (early...late)
|
951
984
|
return [(from < to) ? early : late, @range[-1]]
|
952
985
|
end
|
953
986
|
end
|
954
987
|
|
955
|
-
def _neighbor(
|
988
|
+
def _neighbor(current_time, direction)
|
956
989
|
event = nil
|
957
990
|
minimum = nil
|
958
991
|
@child.each do |prop|
|
959
|
-
date = prop.enum_for(
|
992
|
+
date = prop.enum_for(current_time, direction, 1).succ
|
960
993
|
if (date)
|
961
|
-
diff = (date -
|
994
|
+
diff = (date.universal_time - current_time).abs
|
962
995
|
if (minimum == nil || minimum > diff)
|
963
996
|
event = date
|
964
997
|
minimum = diff
|
@@ -1020,14 +1053,14 @@ module When::V
|
|
1020
1053
|
|
1021
1054
|
# オブジェクトの生成
|
1022
1055
|
def initialize(*args)
|
1023
|
-
@options
|
1024
|
-
@exdate
|
1025
|
-
@exevent
|
1056
|
+
@options = When::Parts::Enumerator._options(args)
|
1057
|
+
@exdate = @options.delete(:exdate)
|
1058
|
+
@exevent = @options.delete(:exevent)
|
1026
1059
|
@parent, @rule, @dtstart, @duration, *args = args
|
1027
|
-
@dtstart
|
1028
|
-
@rule
|
1029
|
-
@logics
|
1030
|
-
@tz_prop
|
1060
|
+
@dtstart = When.when?(@dtstart)
|
1061
|
+
@rule = self.class._decode_rule(@rule, @dtstart) if (@rule.kind_of?(String))
|
1062
|
+
@logics = @rule[:logics]
|
1063
|
+
@tz_prop = nil
|
1031
1064
|
if (@dtstart.kind_of?(When::TM::DateAndTime))
|
1032
1065
|
clock = @dtstart.clock
|
1033
1066
|
if (clock.kind_of?(When::TM::Clock) &&
|
@@ -1054,10 +1087,11 @@ module When::V
|
|
1054
1087
|
else
|
1055
1088
|
@interval = When::TM::PeriodDuration.new(@rule['INTERVAL'], FreqIndex[@rule['FREQ']])
|
1056
1089
|
end
|
1057
|
-
return dtstart if (
|
1090
|
+
return dtstart if (dtstart == target)
|
1058
1091
|
interval_time = (dtstart + @interval) - dtstart
|
1059
1092
|
return dtstart if (interval_time == 0)
|
1060
|
-
|
1093
|
+
duration = target.kind_of?(Numeric) ? target - dtstart.universal_time : (target - dtstart).duration
|
1094
|
+
div, mod = duration.divmod(interval_time.duration)
|
1061
1095
|
seed = dtstart + (@interval * div)
|
1062
1096
|
case @direction
|
1063
1097
|
when :reverse ; seed += @interval while (seed <= target)
|
data/lib/when_exe/inspect.rb
CHANGED
@@ -11,29 +11,30 @@ module When
|
|
11
11
|
#
|
12
12
|
# オブジェクトの内容を Hash 化
|
13
13
|
#
|
14
|
-
# @param [String, Integer] options {When::TM::TemporalPosition#
|
14
|
+
# @param [String, Integer] options {When::TM::TemporalPosition#_to_h}に渡す
|
15
15
|
# @param [Hash] options 下記のとおり
|
16
|
+
# @option options [Numeric] :precision 指定があれば「イベント名(イベント時刻)」出力の時刻を指定の精度に丸める
|
16
17
|
# @option options [Boolean] :camel true ならシンボルを camel case にする
|
17
18
|
# @option options [String] :locale 文字列化の locale(指定なしは M17nオブジェクトに変換)
|
18
19
|
# @option options [Boolean] :simple true ならIRI の先頭部分を簡約表現にする
|
19
20
|
# @option options [Boolean] :residue true なら Residue をそのまま出力
|
20
|
-
# @option options [Object] :その他 各クラス#
|
21
|
+
# @option options [Object] :その他 各クラス#_to_h を参照
|
21
22
|
#
|
22
23
|
# @return [Hash] (Whenモジュール内のクラスは文字列 or M17n化)
|
23
24
|
#
|
24
|
-
def
|
25
|
-
_m17n_form(
|
25
|
+
def to_h(options={})
|
26
|
+
_m17n_form(_to_h(options), options.kind_of?(Hash) ? options : {})
|
26
27
|
end
|
27
28
|
|
28
29
|
#
|
29
30
|
# オブジェクトの内容を JSON 化
|
30
31
|
#
|
31
|
-
# @param [Object] options #
|
32
|
+
# @param [Object] options #to_h を参照
|
32
33
|
#
|
33
|
-
# @return [String]
|
34
|
+
# @return [String] to_h 結果を JSON文字列化したもの
|
34
35
|
#
|
35
36
|
def _to_json(options={})
|
36
|
-
JSON.dump(
|
37
|
+
JSON.dump(to_h(options))
|
37
38
|
end
|
38
39
|
|
39
40
|
#
|
@@ -47,14 +48,14 @@ module When
|
|
47
48
|
#
|
48
49
|
# 時間位置オブジェクトの内容を Hash 化
|
49
50
|
#
|
50
|
-
# @param [Object] options #
|
51
|
+
# @param [Object] options #to_h を参照
|
51
52
|
#
|
52
53
|
# @return [Hash]
|
53
54
|
# 各クラスの HashProperty に列挙した属性のうち値が false/nil でないものを
|
54
55
|
# 属性 => 値
|
55
56
|
# とする Hash
|
56
57
|
#
|
57
|
-
def
|
58
|
+
def _to_h(options={})
|
58
59
|
hash = {}
|
59
60
|
self.class::HashProperty.each do |property|
|
60
61
|
method, skip = property
|
@@ -69,19 +70,20 @@ module When
|
|
69
70
|
#
|
70
71
|
# @param [Object] element 変換元
|
71
72
|
# @param [Hash] options 下記の通り
|
72
|
-
# @option options [
|
73
|
-
# @option options [
|
74
|
-
# @option options [
|
75
|
-
# @option options [Boolean] :
|
73
|
+
# @option options [Numeric] :precision 指定があれば「イベント名(イベント時刻)」出力の時刻を指定の精度に丸める
|
74
|
+
# @option options [Boolean] :camel true ならシンボルを camel case にする
|
75
|
+
# @option options [String] :locale 文字列化の locale(指定なしは M17nオブジェクトに変換)
|
76
|
+
# @option options [Boolean] :simple true ならIRI の先頭部分を簡約表現にする
|
77
|
+
# @option options [Boolean] :residue true なら Residue をそのまま出力
|
76
78
|
#
|
77
79
|
# @return [Hash, Array] 変換結果
|
78
80
|
#
|
79
81
|
# @note element.events のある日付は _event_form で変換する
|
80
82
|
#
|
81
83
|
def _m17n_form(element, options={})
|
82
|
-
result = element.respond_to?(:_event_form) ? element._event_form(self)
|
83
|
-
element.respond_to?(:_to_hash_value) ? element._to_hash_value(options)
|
84
|
-
element.respond_to?(:label) && element.label ? element.label
|
84
|
+
result = element.respond_to?(:_event_form) ? element._event_form(self, options[:precision]) :
|
85
|
+
element.respond_to?(:_to_hash_value) ? element._to_hash_value(options) :
|
86
|
+
element.respond_to?(:label) && element.label ? element.label :
|
85
87
|
case element
|
86
88
|
when Hash ; Hash[*(element.keys.inject([]) { |s, k|
|
87
89
|
s + [_m17n_form(k, options), _m17n_form(element[k], options)]
|
@@ -121,7 +123,7 @@ module When
|
|
121
123
|
end
|
122
124
|
|
123
125
|
#
|
124
|
-
#
|
126
|
+
# to_h のための要素生成
|
125
127
|
# @private
|
126
128
|
def _to_hash_value(options={})
|
127
129
|
options[:residue] ? self : to_m17n
|
@@ -130,7 +132,7 @@ module When
|
|
130
132
|
|
131
133
|
class Pair
|
132
134
|
#
|
133
|
-
#
|
135
|
+
# to_h のための要素生成
|
134
136
|
# @private
|
135
137
|
def _to_hash_value(options={})
|
136
138
|
to_s
|
@@ -319,6 +321,7 @@ module When
|
|
319
321
|
begin
|
320
322
|
date = it.next
|
321
323
|
end while date.to_i == dates[-1].to_i
|
324
|
+
date = date.to_cal_date unless date.instance_of?(TM::CalDate)
|
322
325
|
dates << date
|
323
326
|
end
|
324
327
|
end
|
@@ -326,6 +329,11 @@ module When
|
|
326
329
|
else
|
327
330
|
begun = self.floor(MONTH,DAY) + When::TM::PeriodDuration.new([0, first, 0])
|
328
331
|
ended = begun + When::TM::PeriodDuration.new([0, length, 0])
|
332
|
+
loop do
|
333
|
+
last = ended.prev
|
334
|
+
break unless last.cal_date[MONTH-1] == ended.cal_date[MONTH-1]
|
335
|
+
ended = last
|
336
|
+
end
|
329
337
|
if block_given?
|
330
338
|
(begun...ended).map do |date|
|
331
339
|
yield(date)
|
@@ -535,7 +543,7 @@ module When
|
|
535
543
|
# - :dynamical dynamical_time / 秒
|
536
544
|
# - :universal universal_time / 秒
|
537
545
|
#
|
538
|
-
def
|
546
|
+
def _to_h(options={})
|
539
547
|
hash = super.update({
|
540
548
|
:sdn => to_i,
|
541
549
|
:calendar => calendar_name,
|
@@ -596,9 +604,7 @@ module When
|
|
596
604
|
|
597
605
|
def _to_uri(date)
|
598
606
|
uri = date.gsub(/\./, '-').gsub(/%/, '@')
|
599
|
-
unless @calendar_era_name || @frame == When.Calendar('Gregorian')
|
600
|
-
uri += '^^' + @frame.iri.gsub(/\?/, '%3F').gsub('.', '@').split(/\//)[-1]
|
601
|
-
end
|
607
|
+
uri += '^^' + @frame.iri.split(/\//)[-1] unless @calendar_era_name || @frame == When.Calendar('Gregorian')
|
602
608
|
uri
|
603
609
|
end
|
604
610
|
private :_to_uri
|
@@ -772,7 +778,9 @@ module When
|
|
772
778
|
#
|
773
779
|
def to_m17n(precision=@precision)
|
774
780
|
time = m17n('T' + _time_to_s(precision))
|
775
|
-
|
781
|
+
if @frame
|
782
|
+
time += @frame.zone unless Clock.is_local_time_set? && @frame.equal?(Clock.local_time)
|
783
|
+
end
|
776
784
|
return time
|
777
785
|
end
|
778
786
|
|
@@ -784,7 +792,9 @@ module When
|
|
784
792
|
#
|
785
793
|
def to_s(precision=@precision)
|
786
794
|
time = 'T' + _time_to_s(precision)
|
787
|
-
|
795
|
+
if @frame
|
796
|
+
time += @frame.zone unless Clock.is_local_time_set? && @frame.equal?(Clock.local_time)
|
797
|
+
end
|
788
798
|
return time
|
789
799
|
end
|
790
800
|
|
@@ -846,9 +856,12 @@ module When
|
|
846
856
|
|
847
857
|
# 秒
|
848
858
|
digits = [precision - @clk_time.length + 1, STRING-SECOND].min
|
849
|
-
if digits
|
850
|
-
|
851
|
-
|
859
|
+
if digits == 0
|
860
|
+
format += "%02d"
|
861
|
+
elsif digits > 0
|
862
|
+
factor = 10**digits
|
863
|
+
terms[-1] = ((@clk_time[-1] + 1E-6) * factor).floor.to_f / factor # 切り捨て(10で割る丸めガードあり)
|
864
|
+
format += "%02.#{digits}f"
|
852
865
|
end
|
853
866
|
|
854
867
|
# 結果
|
@@ -857,7 +870,7 @@ module When
|
|
857
870
|
end
|
858
871
|
|
859
872
|
#
|
860
|
-
#
|
873
|
+
# to_h のための要素生成
|
861
874
|
# @private
|
862
875
|
def _to_hash_value(options={})
|
863
876
|
clk_time.map {|e| _m17n_form(e, options) }
|
@@ -923,7 +936,7 @@ module When
|
|
923
936
|
# - :clk_time to_clock_time の結果 ( 日, 時, 分, 秒 )
|
924
937
|
# - :notes Hash (の Array (の Array)) - _notes(options)
|
925
938
|
#
|
926
|
-
def
|
939
|
+
def _to_h(options={})
|
927
940
|
super.update({:cal_date=>@cal_date})
|
928
941
|
end
|
929
942
|
|
@@ -1090,32 +1103,37 @@ module When
|
|
1090
1103
|
# 多言語対応文字列化 - When.exe Standard Representation により多言語対応文字列化する
|
1091
1104
|
#
|
1092
1105
|
# @param [Integer] precision どの桁まで多言語対応文字列化するか、分解能で指定する
|
1106
|
+
# @param [false] round 常に切り捨てる(DateAndTimeとの互換性のためのダミーの引数)
|
1093
1107
|
#
|
1094
1108
|
# @return [When::BasicTypes::M17n]
|
1095
1109
|
#
|
1096
|
-
def to_m17n(precision=@precision)
|
1097
|
-
|
1098
|
-
date
|
1099
|
-
return m17n(
|
1100
|
-
|
1110
|
+
def to_m17n(precision=@precision, round=false)
|
1111
|
+
date = m17n(_date_to_s(precision))
|
1112
|
+
return date unless @calendar_era
|
1113
|
+
return _parent_labels.inject(m17n(@calendar_era_name[0])) {|era_name, parent|
|
1114
|
+
era_name.prefix(m17n(parent) + '::')
|
1115
|
+
} + date
|
1101
1116
|
end
|
1102
1117
|
|
1103
1118
|
# 文字列化 - When.exe Standard Representation により文字列化する
|
1104
1119
|
#
|
1105
1120
|
# @param [Integer] precision どの桁まで多言語対応文字列化するか、分解能で指定する
|
1121
|
+
# @param [false] round 常に切り捨てる(DateAndTimeとの互換性のためのダミーの引数)
|
1106
1122
|
#
|
1107
1123
|
# @return [String]
|
1108
1124
|
#
|
1109
|
-
def to_s(precision=@precision)
|
1110
|
-
era, = @calendar_era_name
|
1125
|
+
def to_s(precision=@precision, round=false)
|
1111
1126
|
date = _date_to_s(precision)
|
1112
|
-
return date unless
|
1113
|
-
return
|
1127
|
+
return date unless @calendar_era
|
1128
|
+
return _parent_labels.inject(@calendar_era_name[0].to_s) {|era_name, parent|
|
1129
|
+
parent.to_s + '::' + era_name
|
1130
|
+
} + date
|
1114
1131
|
end
|
1115
1132
|
|
1116
1133
|
# event を 文字列化 - 日時で与えられた event を文字列化する
|
1117
1134
|
#
|
1118
1135
|
# @param [When::TM::TemporalPosition] other 時系の歩度を比較する基準(nilは比較しない)
|
1136
|
+
# @param [Numeric] round_precision イベント名(イベント)出力の場合の時刻の丸め位置(nilなら丸めない)
|
1119
1137
|
#
|
1120
1138
|
# @return [String]
|
1121
1139
|
#
|
@@ -1124,15 +1142,36 @@ module When
|
|
1124
1142
|
# 日時の精度が日より細かい - イベント名(イベント時刻)
|
1125
1143
|
# 日時の精度が日 - イベント名(当日までの経過日数)
|
1126
1144
|
#
|
1127
|
-
def _event_form(other=nil)
|
1145
|
+
def _event_form(other=nil, round_precision=nil)
|
1128
1146
|
return to_m17n unless events
|
1129
|
-
return events[0] + '(' +
|
1147
|
+
return events[0] + '(' + _clk_time_for_inspect(round_precision).to_s(round_precision || precision)[/[:*=0-9]+/] + ')' if precision > When::DAY
|
1130
1148
|
return events[0] unless other
|
1131
1149
|
other = JulianDate.dynamical_time(other.dynamical_time,
|
1132
1150
|
{:time_standard=>time_standard}) unless time_standard.rate_of_clock == other.time_standard.rate_of_clock
|
1133
1151
|
events[0] + '(' + (other.to_i - to_i).to_s + ')'
|
1134
1152
|
end
|
1135
1153
|
|
1154
|
+
private
|
1155
|
+
|
1156
|
+
# 日付の年号に曖昧性がある場合の親年号の label の Array
|
1157
|
+
#
|
1158
|
+
# @return [Array<String>]
|
1159
|
+
#
|
1160
|
+
def _parent_labels
|
1161
|
+
return [] unless (area = When::TM::CalendarEra[nil]) &&
|
1162
|
+
(period = area[nil])
|
1163
|
+
list = []
|
1164
|
+
era = @calendar_era
|
1165
|
+
while (labels = period[era.label.to_s]) &&
|
1166
|
+
(epoch = labels[era.epoch_year]) &&
|
1167
|
+
(epoch.size > 1) &&
|
1168
|
+
(parent = era.parent).respond_to?(:epoch_year)
|
1169
|
+
list << parent.label
|
1170
|
+
era = parent
|
1171
|
+
end
|
1172
|
+
list
|
1173
|
+
end
|
1174
|
+
|
1136
1175
|
# 日付の年号以外の部分を文字列化する
|
1137
1176
|
#
|
1138
1177
|
# @param [Integer] precision どの桁まで多言語対応文字列化するか、分解能で指定する
|
@@ -1144,23 +1183,23 @@ module When
|
|
1144
1183
|
precision = [precision, 1 - @cal_date.length].max
|
1145
1184
|
precision = [precision, DAY].min
|
1146
1185
|
terms = []
|
1147
|
-
|
1186
|
+
ext_dg = [(@extra_year_digits||1).to_i, 0].max
|
1148
1187
|
|
1149
1188
|
# 年
|
1150
1189
|
year_by_epoch = @cal_date[0]
|
1151
|
-
if
|
1190
|
+
if @calendar_era_name
|
1152
1191
|
era, epoch, reverse = @calendar_era_name
|
1153
1192
|
year_in_term = reverse ? -year_by_epoch : year_by_epoch
|
1154
1193
|
year_by_calendar = epoch + year_by_epoch if epoch
|
1155
1194
|
terms << year_in_term
|
1156
|
-
format
|
1195
|
+
format = (0..99) === (year_in_term * 1) ? "%02d." : "%04d."
|
1157
1196
|
if year_by_calendar && year_by_calendar != year_in_term
|
1158
1197
|
terms << (year_by_calendar * 1)
|
1159
1198
|
format += "(%04d)"
|
1160
1199
|
end
|
1161
1200
|
else
|
1162
1201
|
terms << year_by_epoch
|
1163
|
-
format
|
1202
|
+
format = (0..9999) === (year_by_epoch * 1) ? "%04d." : "%+0#{5+ext_dg}d."
|
1164
1203
|
end
|
1165
1204
|
|
1166
1205
|
# 月日
|
@@ -1196,22 +1235,35 @@ module When
|
|
1196
1235
|
# 多言語対応文字列化 - When.exe Standard Representation により多言語対応文字列化する
|
1197
1236
|
#
|
1198
1237
|
# @param [Integer] precision どの桁まで多言語対応文字列化するか、分解能で指定する
|
1238
|
+
# @param [true, false] round 指定の桁までで丸める(true)か, 切り捨てる(false)か
|
1239
|
+
# @note 丸めるのは precision が When::DAY よりも高精度の場合のみである
|
1199
1240
|
#
|
1200
1241
|
# @return [When::BasicTypes::M17n]
|
1201
1242
|
#
|
1202
|
-
def to_m17n(precision=@precision)
|
1203
|
-
super +
|
1243
|
+
def to_m17n(precision=@precision, round=false)
|
1244
|
+
super + _clk_time_for_inspect(round ? precision : nil).to_m17n(precision)
|
1204
1245
|
end
|
1205
1246
|
|
1206
1247
|
# 文字列化 -When.exe Standard Representation により文字列化する
|
1207
1248
|
#
|
1208
1249
|
# @param [Integer] precision どの桁まで多言語対応文字列化するか、分解能で指定する
|
1250
|
+
# @param [true, false] round 指定の桁までで丸める(true)か, 切り捨てる(false)か
|
1251
|
+
# @note 丸めるのは precision が When::DAY よりも高精度の場合のみである
|
1209
1252
|
#
|
1210
1253
|
# @return [String]
|
1211
1254
|
#
|
1212
|
-
def to_s(precision=@precision)
|
1213
|
-
super +
|
1255
|
+
def to_s(precision=@precision, round=false)
|
1256
|
+
super + _clk_time_for_inspect(round ? precision : nil).to_s(precision)
|
1257
|
+
end
|
1258
|
+
|
1259
|
+
# 出力に使用する clk_time の作成
|
1260
|
+
def _clk_time_for_inspect(precision)
|
1261
|
+
return @clk_time unless precision && precision > When::DAY
|
1262
|
+
base = self + When::TM::Duration.new(@clk_time.frame._round_value(precision))
|
1263
|
+
base.clk_time.clk_time[When::HOUR] = @clk_time.clk_time[When::HOUR] + 1 unless self.to_i == base.to_i
|
1264
|
+
return base.clk_time
|
1214
1265
|
end
|
1266
|
+
private :_clk_time_for_inspect
|
1215
1267
|
|
1216
1268
|
# 時
|
1217
1269
|
#
|