when_exe 0.4.4 → 0.4.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/lib/when_exe.rb +89 -3
  3. data/lib/when_exe/basictypes.rb +37 -7
  4. data/lib/when_exe/calendarnote.rb +18 -13
  5. data/lib/when_exe/calendartypes.rb +3 -9
  6. data/lib/when_exe/coordinates.rb +23 -373
  7. data/lib/when_exe/ephemeris.rb +7 -7
  8. data/lib/when_exe/ephemeris/notes.rb +0 -14
  9. data/lib/when_exe/events.rb +1851 -0
  10. data/lib/when_exe/icalendar.rb +121 -4
  11. data/lib/when_exe/linkeddata.rb +29 -18
  12. data/lib/when_exe/locales/akt.rb +63 -0
  13. data/lib/when_exe/locales/locale.rb +60 -11
  14. data/lib/when_exe/mini_application.rb +14 -8
  15. data/lib/when_exe/namespace.rb +42 -0
  16. data/lib/when_exe/parts/enumerator.rb +13 -2
  17. data/lib/when_exe/parts/geometric_complex.rb +51 -1
  18. data/lib/when_exe/parts/method_cash.rb +15 -10
  19. data/lib/when_exe/parts/resource.rb +47 -29
  20. data/lib/when_exe/region/chinese.rb +4 -3
  21. data/lib/when_exe/region/chinese/calendars.rb +4 -4
  22. data/lib/when_exe/region/chinese/epochs.rb +6 -6
  23. data/lib/when_exe/region/chinese/notes.rb +3 -3
  24. data/lib/when_exe/region/chinese/twins.rb +6 -6
  25. data/lib/when_exe/region/islamic.rb +1 -1
  26. data/lib/when_exe/region/japanese.rb +4 -4
  27. data/lib/when_exe/region/japanese/eclipses.rb +2 -2
  28. data/lib/when_exe/region/japanese/location.rb +93 -0
  29. data/lib/when_exe/region/japanese/notes.rb +29 -11
  30. data/lib/when_exe/region/japanese/residues.rb +1 -1
  31. data/lib/when_exe/region/japanese/twins.rb +18 -6
  32. data/lib/when_exe/region/location.rb +40 -0
  33. data/lib/when_exe/region/martian.rb +1 -1
  34. data/lib/when_exe/region/ryukyu.rb +1 -1
  35. data/lib/when_exe/spatial.rb +611 -0
  36. data/lib/when_exe/timestandard.rb +3 -3
  37. data/lib/when_exe/tmobjects.rb +32 -0
  38. data/lib/when_exe/tmposition.rb +211 -1318
  39. data/lib/when_exe/tmptypes.rb +1265 -0
  40. data/lib/when_exe/tmreference.rb +35 -0
  41. data/lib/when_exe/version.rb +3 -3
  42. data/test/events/example-datasets +7 -0
  43. data/test/events/history-dataset.csv +22 -0
  44. data/test/events/japanese-holiday-index.csv +28 -0
  45. data/test/events/japanese-holiday.csv +77 -0
  46. data/test/events/japanese-holiday.ttl +778 -0
  47. data/test/events/make_events_ttl.rb +18 -0
  48. data/test/events/mori_wikichoshi.csv +14 -0
  49. data/test/events/ndl_koyomi.csv +220 -0
  50. data/test/events/ndl_koyomi_index.csv +44 -0
  51. data/test/events/primeminister-dataset.csv +19 -0
  52. data/test/events/shogun-dataset.csv +22 -0
  53. data/test/events/test-history-dataset-edge-sparql.csv +26 -0
  54. data/test/events/test-history-dataset-edge.csv +27 -0
  55. data/test/events/test-history-dataset-sparql.csv +22 -0
  56. data/test/events/test-history-dataset.csv +23 -0
  57. data/test/events/test-history-events-edge.ttl +89 -0
  58. data/test/events/test-history-events.csv +6 -0
  59. data/test/examples/Terms.m17n +1 -1
  60. data/test/test.rb +6 -0
  61. data/test/test/coordinates.rb +2 -2
  62. data/test/test/events.rb +32 -0
  63. data/test/test/region/japanese.rb +20 -0
  64. data/test/test/region/m17n.rb +2 -2
  65. data/test/test/region/mayan.rb +6 -6
  66. data/test/test/tmposition.rb +63 -1
  67. metadata +26 -2
@@ -528,6 +528,17 @@ module When::V
528
528
  'resources', 'rdate']]
529
529
  # Classes = [V::Root, V::Alarm]
530
530
 
531
+ RegisteredNotes = {
532
+ 'term' => 'SolarTerms',
533
+ 'phase' => 'LunarPhases',
534
+ 'easter' => 'Christian',
535
+ 'christmas' => 'Christian'
536
+ }
537
+
538
+ RegisteredNoteMethods = /\A(#{RegisteredNotes.keys.sort.reverse.join('|')})/
539
+
540
+ DayOfWeek = %w(SU MO TU WE TH FR SA)
541
+
531
542
  class << self
532
543
  include When::Parts::Resource::Pool
533
544
 
@@ -565,6 +576,101 @@ module When::V
565
576
  def default_until
566
577
  @default_until ||= 1000*When::TM::Duration::YEAR
567
578
  end
579
+
580
+ # ISO8601へ埋め込まれた指定に対応する iterator を生成する
581
+ #
582
+ # @param [When::TM::TemporalPosition] base イベントの始点
583
+ # @param [When::TM::Duration] duration イベントの期間
584
+ # @param [Hash] delayed_options 遅延適用するオブジェクト変換オプション
585
+ #
586
+ # @return [When::Parts::Enumerator]
587
+ #
588
+ def iterator_for_ISO8601(base, duration, delayed_options)
589
+ duration.to_s =~ /\A-?P(\d+)([YM])\z/
590
+ event_options = {'rrule'=>
591
+ case $2
592
+ when 'Y' ; {'FREQ'=>'YEARLY', 'INTERVAL'=>$1.to_i}
593
+ when 'M' ; {'FREQ'=>'MONTHLY', 'INTERVAL'=>$1.to_i}
594
+ else ; duration ? {'FREQ'=>duration.set_repeat(false).abs} : {'FREQ'=>'YEARLY'}
595
+ end
596
+ }
597
+ residue_options = delayed_options[:residue]
598
+ if residue_options
599
+ event_options['rrule'].update(_byyear(residue_options)) if residue_options[0]
600
+ event_options['rrule'].update(_byday(residue_options )) if residue_options[2]
601
+ delayed_options.delete(:residue)
602
+ end
603
+ if base.precision == When::MONTH && event_options['rrule']['FREQ'] == 'YEARLY'
604
+ event_options['rrule'].update({'BYMONTH'=>base[When::MONTH]})
605
+ base = base.floor if event_options['rrule']['BYMONTHDAY']
606
+ end
607
+ case base
608
+ when When::TM::TemporalPosition ; event_options.update({'dtstart' =>base})
609
+ else ; event_options.update({'dtstart' =>base.first,
610
+ 'duration' =>base.last-base.first})
611
+ end
612
+ event_options['duration'] = delayed_options.delete(:duration) if delayed_options[:duration]
613
+ behavior_options = {'1st'=>delayed_options.delete(:first) || "don't care"}
614
+ behavior_options[:delayed] = delayed_options unless delayed_options.empty?
615
+ behavior_options[:direction] = :reverse if duration && duration.sign < 0
616
+ return new(event_options).enum_for(event_options['dtstart'], behavior_options)
617
+ end
618
+
619
+ private
620
+
621
+ # オブジェクト変換オプションの遅延適用のBYYEAR要素
622
+ #
623
+ def _byyear(options)
624
+ {'BYYEAR'=>_to_ical_hash(When.Residue(options.delete(0)), 'year', 4)}
625
+ end
626
+
627
+ # オブジェクト変換オプションの遅延適用のBYDAY要素
628
+ #
629
+ def _byday(options)
630
+ operation = options.delete(2)
631
+ return {'BYDAY'=>_to_ical_hash(operation, 'day', 11)} if operation.kind_of?(When::Coordinates::Residue)
632
+
633
+ residues = []
634
+ result = {}
635
+ byday = {}
636
+
637
+ # イベント、日付
638
+ operation.split('&').each do |element|
639
+ element.strip!
640
+ case element
641
+ when RegisteredNoteMethods ; byday.update({nil=>element})
642
+ when /\A(.+?)#(.+)\z/ ; byday.update({$1=>$2})
643
+ when /\A[-+,\d]+\z/ ; result['BYMONTHDAY'] = element
644
+ else ; residues << element
645
+ end
646
+ end
647
+
648
+ # 剰余類
649
+ unless residues.empty?
650
+ residue = residues.join('&')
651
+ if residue =~ /\A[-+]?\d*(MO|TU|WE|TH|FR|SA|SU)\z/
652
+ result['BYWEEKDAY'] = residue
653
+ else
654
+ resource = When.Residue(residue)
655
+ if resource
656
+ byday.update(_to_ical_hash(resource, 'day', 11))
657
+ else
658
+ result['BYWEEKDAY'] = residue
659
+ end
660
+ end
661
+ end
662
+
663
+ result['BYDAY'] = byday unless byday.empty?
664
+ return result
665
+ end
666
+
667
+ # 剰余のハッシュ化
668
+ def _to_ical_hash(residue, unit, offset)
669
+ operation = ''
670
+ operation << "#{residue.carry < 0 ? residue.carry : residue.carry+1}*" if residue.shifted
671
+ operation << "#{(residue.remainder-offset+residue.units[unit]) % residue.divisor}"
672
+ {residue.divisor=>operation}
673
+ end
568
674
  end
569
675
 
570
676
  # SUMMARY Property
@@ -1065,6 +1171,7 @@ module When::V
1065
1171
  @options = When::Parts::Enumerator._options(args)
1066
1172
  @exdate = @options.delete(:exdate)
1067
1173
  @exevent = @options.delete(:exevent)
1174
+ @delayed = @options.delete(:delayed)
1068
1175
  @parent, @rule, @dtstart, @duration, *rest = args
1069
1176
  @dtstart = When.when?(@dtstart)
1070
1177
  @rule = self.class._decode_rule(@rule, @dtstart) if (@rule.kind_of?(String))
@@ -1267,7 +1374,7 @@ module When::V
1267
1374
  position = rule[(by_part == 'BYYEAR') ? 'YEARPOS' : 'DAYPOS'][ref]
1268
1375
  start = rule[(by_part == 'BYYEAR') ? 'YEARST' : 'DAYST' ][ref]
1269
1376
  rule[by_part][ref] = ((ref.to_i==0) ? Logic::Enumerator :
1270
- Logic::Residue).new(by_part, list, position, ref, start)
1377
+ Logic::Residue).new(by_part, list, position, ref, start, dtstart)
1271
1378
  end
1272
1379
  end
1273
1380
  end
@@ -1457,7 +1564,7 @@ module When::V
1457
1564
  end
1458
1565
 
1459
1566
  # @private
1460
- def initialize(by_part, list, position, ref, start)
1567
+ def initialize(by_part, list, position, ref, start, dtstart)
1461
1568
  @by_part = by_part
1462
1569
  divisor = When::Coordinates::Pair._en_number(ref)
1463
1570
  @list = list.split(/,/).map {|w|
@@ -1519,9 +1626,19 @@ module When::V
1519
1626
  end
1520
1627
 
1521
1628
  # @private
1522
- def initialize(by_part, list, position, ref, start)
1629
+ def initialize(by_part, list, position, ref, start, dtstart)
1523
1630
  @by_part = by_part
1524
- @ref = When.Resource(ref, '_n:')
1631
+ @ref =
1632
+ if ref
1633
+ When.Resource(ref, '_n:')
1634
+ else
1635
+ method = list[/\A[^-+\d]+/]
1636
+ if dtstart.frame.note.respond_to?(method)
1637
+ dtstart.frame.note
1638
+ else
1639
+ When.Resource(When::V::Event::RegisteredNotes[method], '_n:')
1640
+ end
1641
+ end
1525
1642
  @start = start
1526
1643
  @list = list.split(/,/).map {|w|
1527
1644
  raise ArgumentError, "The #{by_part} rule format error" unless w =~ /\A(([-+]?\d+)\*)?(.+?)([-+]\d+)?\z/
@@ -40,12 +40,19 @@ module When
40
40
  'latitude' => "Coordinates/Spatial#latitude-instance_method",
41
41
  'altitide' => "Coordinates/Spatial#latitude-instance_method",
42
42
  'event' => "CalendarNote#event-instance_method",
43
+ 'note' => "CalendarNote/NoteElement",
44
+ 'id' => "Events/Event#id-instance_method",
45
+ 'group' => "Events/Event#group-instance_method",
46
+ 'start' => "Events/Range#start-instance_method",
47
+ 'until' => "Events/Range#until-instance_method",
48
+ 'west' => "Coordinates/Spatial/Range#west-instance_method",
49
+ 'east' => "Coordinates/Spatial/Range#east-instance_method",
50
+ 'south' => "Coordinates/Spatial/Range#south-instance_method",
51
+ 'north' => "Coordinates/Spatial/Range#north-instance_method",
52
+ 'bottom' => "Coordinates/Spatial/Range#bottom-instance_method",
53
+ 'top' => "Coordinates/Spatial/Range#top-instance_method"
43
54
  }
44
55
 
45
- XSD = 'http://www.w3.org/2001/XMLSchema'
46
- RDFS = 'http://www.w3.org/2000/01/rdf-schema#'
47
- RDF = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'
48
-
49
56
  #
50
57
  # @private
51
58
  #
@@ -85,8 +92,9 @@ module When
85
92
  def schema(iri=nil)
86
93
  ts = base_uri.sub(/When\/$/, 'ts#')
87
94
  hash =
88
- {'@context'=>{'ts' => ts},
89
- '@graph' => Schema.keys.map {|id| {'@id'=>'ts:'+id, 'ts:reference'=>{'@id'=>DocRoot + Schema[id]}}}
95
+ {'@context'=>{'rdf'=>When::Namespace::RDF, 'ts' => ts},
96
+ '@graph' => Schema.keys.map {|id| {'@id'=>'ts:'+id, 'rdf:type'=>{'@id'=>'rdf:Property'},
97
+ 'ts:reference'=>{'@id'=>DocRoot + Schema[id]}}}
90
98
  }
91
99
  bless(hash, iri || ts[0..-2])
92
100
  end
@@ -117,7 +125,7 @@ module When
117
125
  JSON.generate(jsonld_hash)
118
126
  else
119
127
  array = JSON::LD::API.toRdf(jsonld_hash)
120
- graph = ::RDF::Graph.new << array
128
+ graph = RDF::Graph.new << array
121
129
  args = [writer]
122
130
  args << {:prefixes=>prefixes} if prefixes
123
131
  graph.dump(*args)
@@ -162,13 +170,13 @@ module When
162
170
  def namespace_prefixes(*resources)
163
171
  base = base_uri.sub(/When\/$/, '')
164
172
  resources.inject({
165
- 'xsd' => [XSD],
166
- 'rdf' => [RDF],
167
- 'rdfs' => [RDFS],
168
- 'owl' => ['http://www.w3.org/2002/07/owl#'],
169
- 'dc' => ['http://purl.org/dc/elements/1.1/'],
170
- 'dcq' => ['http://purl.org/dc/terms/'],
171
- 'dct' => ['http://purl.org/dc/dcmitype/'],
173
+ 'xsd' => [When::Namespace::XSD ],
174
+ 'rdf' => [When::Namespace::RDF ],
175
+ 'rdfs' => [When::Namespace::RDFS],
176
+ 'owl' => [When::Namespace::OWL ],
177
+ 'dc' => [When::Namespace::DC ],
178
+ 'dcq' => [When::Namespace::DCQ ],
179
+ 'dct' => [When::Namespace::DCT ],
172
180
  # 'tp' => [base + 'tp/'],
173
181
  'ts' => [base + 'ts#']
174
182
  }) {|namespace, resource|
@@ -315,6 +323,8 @@ module When
315
323
  hash[key] = value if /^@/ =~ key.to_s
316
324
  end
317
325
  hash[RDF + 'type'] = {'@id'=>base + 'ts/' + self.class.to_s.gsub(/::/, '/')}
326
+ hash[RDFS + 'subPropertyOf'] = {'@id'=>base + 'ts#note'} if kind_of?(When::CalendarNote::NoteElement) ||
327
+ kind_of?(When::Parts::Resource) && /\/notes\// =~ iri && !leaf?
318
328
  if options[:context]
319
329
  options[:prefixes] ||= When::Parts::Resource.namespace_prefixes
320
330
  context = hash['@context'] || {}
@@ -371,9 +381,10 @@ module When
371
381
  def compact_namespace_to_prefix(source, prefixes, context=nil)
372
382
  return source unless prefixes
373
383
  prefixes.each_pair do |key, value|
374
- Array(value).each do |prefix|
375
- start = source.index(prefix)
376
- body = source[prefix.length..-1]
384
+ Array(value).each do |namespace|
385
+ namespace = namespace.sub(/([a-z0-9])\z/i, '\1#')
386
+ start = source.index(namespace)
387
+ body = source[namespace.length..-1]
377
388
  return key + ':' + body if start == 0 && body !~ /[:#\/]/
378
389
  end
379
390
  end
@@ -459,7 +470,7 @@ module When
459
470
  #
460
471
  def to_uri_linkeddata(*args)
461
472
  date, frame = _to_uri(to_s(*args)).split('^^', 2)
462
- frame += '_' if frame =~ /\d\z/
473
+ frame += '_' if /\d\z/ =~ frame
463
474
  date = "#{frame}(#{date})" if frame
464
475
  When::Parts::Resource.base_uri.sub(/When\/$/, 'tp/') + date
465
476
  end
@@ -147,6 +147,35 @@ module When
147
147
  # @private
148
148
  IAST_K_keys = transliteration_keys(IAST_K)
149
149
 
150
+ # @private
151
+ NumAlter1 = [['〇','零'], [/[壱壹]/,'一'], [/[弐貳]/,'二'], [/[弎参參]/,'三'], ['肆','四'],
152
+ ['伍','五'], ['陸','六'], ['柒','七'], ['捌','八'], ['玖','九'], ['拾','十'],
153
+ ['廿', '二十'], [/[卅丗]/, '三十'], ['卌', '四十'],
154
+ ['佰', '百'], ['仟', '千'], ['萬', '万'], ['秭', '𥝱']]
155
+
156
+ # @private
157
+ NumAlter2 = [['零〇','0'], ['一壱壹','1'], ['二弐貳','2'], ['三弎参參','3'], ['四肆','4'],
158
+ ['五伍','5'], ['六陸','6'], ['七柒','7'], ['八捌','8'], ['九玖','9']]
159
+
160
+ # @private
161
+ Numbers = %w(零 一 二 三 四 五 六 七 八 九 十 百 千 万 億 兆 京 垓 𥝱
162
+ 穣 溝 澗 正 載 極 恒河沙 阿僧祇 那由他 不可思議 無量大数)
163
+
164
+ # @private
165
+ NumRExp1 = /#{Numbers[10..12].reverse.map {|num| "(?:(.*)#{num})"}.join('?')}?(.*)/
166
+
167
+ # public
168
+ NumRExp3 = /([#{Numbers[0..12].join('')}廿卅丗卌]+)/
169
+
170
+ # @private
171
+ NumRExp4 = /#{Numbers[13..-1].reverse.map {|num| "(?:(.*)#{num})"}.join('?')}?(.*)/
172
+
173
+ # @private
174
+ NumMap = Hash[*(Numbers[0..9].zip((0..9).to_a)).flatten]
175
+
176
+ # @private
177
+ DigitMap = [1,1,1,0]
178
+
150
179
  #
151
180
  # Convert AKT string to katakana scripts
152
181
  #
@@ -173,5 +202,39 @@ module When
173
202
  gsub(/([rm])y/, '\1uy'),
174
203
  locale)
175
204
  end
205
+
206
+ #
207
+ # Convert kanji scripts to numeric
208
+ #
209
+ def self.k2a_digits(figures, force_alter=false)
210
+ if force_alter
211
+ figures = figures.dup
212
+ NumAlter1.each {|alter| figures.gsub!(*alter)}
213
+ end
214
+ sum = 0
215
+ NumRExp4 =~ figures
216
+ $~.to_a[1..-1].each do |wide_match|
217
+ if NumRExp1 =~ wide_match
218
+ $~.to_a[1..-1].each_with_index do |match,digit|
219
+ sum *= 10
220
+ sum += (NumMap[match] || DigitMap[digit]) if match
221
+ end
222
+ else
223
+ sum *= 10000
224
+ end
225
+ end
226
+ sum
227
+ end
228
+
229
+ #
230
+ # Convert zenkaku figures to numeric
231
+ #
232
+ def self.z2h_digits(figures, force_alter=false)
233
+ if force_alter
234
+ figures = figures.dup
235
+ NumAlter2.each {|alter| figures.tr!(*alter)}
236
+ end
237
+ figures.tr('0123456789', '0123456789').to_i
238
+ end
176
239
  end
177
240
  end
@@ -63,6 +63,10 @@ module When
63
63
  # @private
64
64
  Link = /<li class="interlanguage-link interwiki-(.+?)"><a href="\/\/(.+?)\.wikipedia\.org\/wiki\/(.+?)" title="(.+?) – /
65
65
 
66
+ # NUL for Escape
67
+ # @private
68
+ NUL = 0.chr
69
+
66
70
  class << self
67
71
 
68
72
  # Wikipedia の連続的な参照を抑制するための遅延時間/秒
@@ -134,6 +138,29 @@ module When
134
138
  source
135
139
  end
136
140
 
141
+ # 暦要素を含む文字列を Hash に分解する
142
+ #
143
+ # @param [String] date_time 暦要素を含む文字列
144
+ # @param [String or Hash] format 分解する書式
145
+ # @param [String] locale 言語指定
146
+ #
147
+ # @return [Hash] 暦要素を分解格納した Hash
148
+ #
149
+ def _to_date_time_hash(date_time, format, locale=nil)
150
+ if locale
151
+ format = format.kind_of?(String) ?
152
+ translate(format, locale) :
153
+ _hash_value(format, locale)
154
+ unless locale == 'en'
155
+ regexp, hash = _trans_table(locale)
156
+ date_time = date_time.gsub(regexp) {|match| hash[match]}
157
+ end
158
+ end
159
+ ::DateTime._strptime(date_time, format)
160
+ rescue NameError
161
+ raise "Please require standard library 'Date' or 'DateTime'"
162
+ end
163
+
137
164
  # 包摂リストに登録されている文字を包摂する
138
165
  #
139
166
  # @param [When::Locale] source 文字を包摂しようとする国際化文字列
@@ -243,20 +270,27 @@ module When
243
270
  }
244
271
  end
245
272
 
246
- # locale 指定を解析して Hash の値を取り出す
273
+ # locale 指定を解析して key の値を取り出す
247
274
  # @private
248
- def _hash_value(hash, locale, defaults=['', 'en'])
275
+ def _hash_key(hash, locale, defaults=['', 'en'])
249
276
  locale = locale.sub(/\..*/, '')
250
- return hash[locale] if hash[locale]
251
- return _hash_value(hash, _alias[locale], defaults) if _alias[locale]
252
- language = locale.sub(/-.*/, '')
253
- return hash[language] if hash[language]
277
+ return locale if hash.key?(locale)
278
+ return _hash_key(hash, _alias[locale], defaults) if _alias.key?(locale)
279
+ language = locale.sub(/[-_].*/, '')
280
+ return language if hash.key?(language)
254
281
  defaults.each do |default|
255
- return hash[default] if hash[default]
282
+ return default if hash.key?(default)
256
283
  end
257
284
  return nil
258
285
  end
259
286
 
287
+ # locale 指定を解析して Hash の値を取り出す
288
+ # @private
289
+ def _hash_value(hash, locale, defaults=['', 'en'])
290
+ key = _hash_key(hash, locale, defaults)
291
+ key ? hash[key] : nil
292
+ end
293
+
260
294
  # 漢字の包摂パターン
261
295
  # @private
262
296
  def _unification
@@ -269,7 +303,7 @@ module When
269
303
  access_key = access_key.split(/\//).map {|key| key =~ /\A[0-9]+\z/ ? key.to_i : key}
270
304
  locale = locale.sub(/\..*/, '')
271
305
  [locale, locale.sub(/-.*/, '')].each do |loc|
272
- symbol = ('Locale_' + loc.sub(/-/,'_')).to_sym
306
+ symbol = ('Locale_' + loc.gsub(/-/,'_')).to_sym
273
307
  return {locale=>access_key.inject(const_get(symbol)) {|hash, key| hash = hash[key]}} if const_defined?(symbol)
274
308
  end
275
309
  return nil
@@ -283,7 +317,7 @@ module When
283
317
  # @private
284
318
  def _dbpedia(source)
285
319
  return nil unless Ref =~ source
286
- return "http://#{$1=='en' ? '' : $1+'.'}dbpedia.org/resource/#{URI.decode($2)}"
320
+ return "http://#{$1=='en' ? '' : $1+'.'}dbpedia.org/resource/#{CGI.unescape($2)}"
287
321
  end
288
322
 
289
323
  private
@@ -309,7 +343,7 @@ module When
309
343
  # wikipedia の読み込み
310
344
  def _wikipedia_object(path, locale, file, query, interval, options)
311
345
  # 採取済みデータ
312
- title = URI.decode(file.gsub('_', ' '))
346
+ title = CGI.unescape(file.gsub('_', ' '))
313
347
  mode = "".respond_to?(:force_encoding) ? ':utf-8' : ''
314
348
  dir = When::Parts::Resource.root_dir + '/data/wikipedia/' + locale
315
349
  FileUtils.mkdir_p(dir) unless FileTest.exist?(dir)
@@ -391,6 +425,21 @@ module When
391
425
  object._pool['..'] += '?' + query if query
392
426
  object
393
427
  end
428
+
429
+ # 月名と週名の翻訳テーブル
430
+ def _trans_table(locale)
431
+ return @trans_table[locale] if @trans_table && @trans_table[locale]
432
+ hash = Hash[*(%w(_m:Calendar::Month::* _m:Calendar::Abbr_Month::*
433
+ _co:Common::Week::* _co:Common::Abbr_Day::*).inject([]) {|list, iri|
434
+ list.concat(When.Resource(iri).map {|resource|
435
+ label = resource.kind_of?(When::BasicTypes::M17n) ? resource : resource.label
436
+ [label.translate(locale), label.translate('en')]
437
+ })
438
+ }.sort_by {|pair| -(pair.first.length*100+pair.last.length)}).flatten]
439
+ regexp = /#{hash.keys.sort_by {|key| -key.length}.join('|')}/
440
+ @trans_table ||= {}
441
+ @trans_table[locale] = [regexp, hash]
442
+ end
394
443
  end
395
444
 
396
445
  # ローケール指定時の文字列
@@ -785,7 +834,7 @@ module When
785
834
  # encode URI from patterns %%(...) or %.(...) and replace space to '_'
786
835
  def _encode(source)
787
836
  source.gsub(' ','_').gsub(/%.<.+?>/) { |match|
788
- URI.encode(match[3..-2]).gsub('%', match[1..1])
837
+ CGI.escape(match[3..-2]).gsub('%', match[1..1])
789
838
  }
790
839
  end
791
840
  end