when_exe 0.4.1 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +36 -33
  3. data/bin/locales.rb +1 -1
  4. data/bin/make_ttl.rb.config +1 -1
  5. data/lib/when_exe.rb +27 -16
  6. data/lib/when_exe/basictypes.rb +772 -771
  7. data/lib/when_exe/calendartypes.rb +1485 -1453
  8. data/lib/when_exe/coordinates.rb +5 -0
  9. data/lib/when_exe/core/compatibility.rb +1 -1
  10. data/lib/when_exe/core/duration.rb +147 -116
  11. data/lib/when_exe/core/extension.rb +499 -497
  12. data/lib/when_exe/ephemeris.rb +1952 -1951
  13. data/lib/when_exe/ephemeris/eclipse.rb +5 -4
  14. data/lib/when_exe/ephemeris/notes.rb +457 -421
  15. data/lib/when_exe/ephemeris/planets.rb +585 -585
  16. data/lib/when_exe/ephemeris/sun.rb +214 -214
  17. data/lib/when_exe/google_api.rb +153 -0
  18. data/lib/when_exe/icalendar.rb +1640 -1632
  19. data/lib/when_exe/inspect.rb +42 -20
  20. data/lib/when_exe/linkeddata.rb +28 -7
  21. data/lib/when_exe/locales/autoload.rb +2 -1
  22. data/lib/when_exe/locales/locale.rb +35 -15
  23. data/lib/when_exe/locales/zh.rb +77 -0
  24. data/lib/when_exe/mini_application.rb +3 -1
  25. data/lib/when_exe/{googlecalendar.rb → obsolete/googlecalendar.rb} +144 -144
  26. data/lib/when_exe/parts/enumerator.rb +498 -486
  27. data/lib/when_exe/parts/geometric_complex.rb +397 -397
  28. data/lib/when_exe/parts/timezone.rb +246 -241
  29. data/lib/when_exe/region/armenian.rb +55 -56
  30. data/lib/when_exe/region/babylonian.rb +406 -405
  31. data/lib/when_exe/region/bahai.rb +107 -106
  32. data/lib/when_exe/region/balinese.rb +624 -622
  33. data/lib/when_exe/region/chinese.rb +1071 -1026
  34. data/lib/when_exe/region/chinese/epochs.rb +28 -28
  35. data/lib/when_exe/region/chinese/notes.rb +219 -0
  36. data/lib/when_exe/region/chinese/twins.rb +803 -803
  37. data/lib/when_exe/region/christian.rb +21 -15
  38. data/lib/when_exe/region/coptic.rb +107 -106
  39. data/lib/when_exe/region/discordian.rb +218 -218
  40. data/lib/when_exe/region/east_asian.rb +1 -1
  41. data/lib/when_exe/region/french.rb +126 -56
  42. data/lib/when_exe/region/geologicalage.rb +639 -639
  43. data/lib/when_exe/region/goddess.rb +60 -58
  44. data/lib/when_exe/region/hanke_henry.rb +2 -2
  45. data/lib/when_exe/region/indian.rb +1225 -1222
  46. data/lib/when_exe/region/international_fixed.rb +96 -97
  47. data/lib/when_exe/region/iranian.rb +206 -203
  48. data/lib/when_exe/region/islamic.rb +102 -102
  49. data/lib/when_exe/region/japanese.rb +126 -71
  50. data/lib/when_exe/region/japanese/epochs.rb +426 -426
  51. data/lib/when_exe/region/japanese/notes.rb +101 -81
  52. data/lib/when_exe/region/japanese/residues.rb +1345 -1311
  53. data/lib/when_exe/region/japanese/twins.rb +225 -225
  54. data/lib/when_exe/region/japanese/weeks.rb +112 -112
  55. data/lib/when_exe/region/javanese.rb +230 -230
  56. data/lib/when_exe/region/jewish.rb +130 -131
  57. data/lib/when_exe/region/m17n.rb +114 -114
  58. data/lib/when_exe/region/martian.rb +258 -258
  59. data/lib/when_exe/region/mayan.rb +11 -8
  60. data/lib/when_exe/region/pax.rb +4 -5
  61. data/lib/when_exe/region/pope.rb +1 -1
  62. data/lib/when_exe/region/positivist.rb +100 -100
  63. data/lib/when_exe/region/residue.rb +162 -162
  64. data/lib/when_exe/region/roman.rb +333 -333
  65. data/lib/when_exe/region/{soviet.rb → russian.rb} +221 -209
  66. data/lib/when_exe/region/shire.rb +222 -223
  67. data/lib/when_exe/region/symmetry.rb +50 -50
  68. data/lib/when_exe/region/thai.rb +336 -336
  69. data/lib/when_exe/region/tibetan.rb +315 -316
  70. data/lib/when_exe/region/tranquility.rb +207 -208
  71. data/lib/when_exe/region/vanishing_leprechaun.rb +3 -1
  72. data/lib/when_exe/region/vietnamese.rb +449 -440
  73. data/lib/when_exe/region/weekdate.rb +80 -80
  74. data/lib/when_exe/region/world.rb +170 -171
  75. data/lib/when_exe/region/world_season.rb +89 -89
  76. data/lib/when_exe/region/yerm.rb +3 -3
  77. data/lib/when_exe/region/zoroastrian.rb +205 -205
  78. data/lib/when_exe/timestandard.rb +708 -707
  79. data/lib/when_exe/tmduration.rb +338 -338
  80. data/lib/when_exe/tmobjects.rb +1356 -1356
  81. data/lib/when_exe/tmposition.rb +66 -31
  82. data/lib/when_exe/version.rb +16 -2
  83. data/test/examples/Residue.m17n +83 -83
  84. data/test/examples/Terms.m17n +2 -2
  85. data/test/test.rb +2 -2
  86. data/test/test/google_api.rb +65 -0
  87. data/test/test/linkeddata.rb +1 -1
  88. data/test/test/{googlecalendar.rb → obsolete/googlecalendar.rb} +194 -194
  89. data/test/test/region/indian.rb +90 -85
  90. data/test/test/region/m17n.rb +7 -7
  91. data/test/test/region/mayan.rb +195 -195
  92. data/test/test/region/residue.rb +153 -153
  93. data/test/test/tmposition.rb +11 -1
  94. data/when_exe.gemspec +2 -2
  95. metadata +95 -8
  96. data/test/test.rb.config +0 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 21ef2902a6f6e66f6b217b300ec63d0cfe4b3ec1
4
- data.tar.gz: e132d01708f7eaac9e2246faeec19b5843551422
3
+ metadata.gz: b40bf07a801ef6ae19fa3821c5768cda89f95e7e
4
+ data.tar.gz: acafb3787334e8a37dca4d7429489b6d390ed17a
5
5
  SHA512:
6
- metadata.gz: 1622bb678b6adfce5e1c54a91889ede8bb675fa3add66a01eba031910bbc3f11e45c2cbb5c4b24ac46bd22a9d3984d30f621f6e5c1e67d5430ca7d7cd4b142c3
7
- data.tar.gz: 09f2ceda494e0e731593468051147ec22845827847a0f35f75ab9ca8b3969a6ea3154d8b5becc01ff80e302a30649b29a424cd34b86d804a2646a3b807f0dd36
6
+ metadata.gz: c4be4641f8831f194acab492a26170ebe4f54fb00f5c98dd1dfc5982f88ea3bea077a6ce5778f5691f02a3b8d95e9538826191ebcd88235490d967a3a6efda44
7
+ data.tar.gz: e4d27604acb85c99db321ec99bfc04b456f99656439aecfcd9534e54ae6fb1e6ab844673a2b10d8369a3b0f18968bb9ffc6faa9be1136ffa202d360b559c462f
data/README.md CHANGED
@@ -3,7 +3,7 @@ when_exe - A multicultural and multilingualized calendar library
3
3
 
4
4
  [![Gem Version](https://badge.fury.io/rb/when_exe.svg)](http://badge.fury.io/rb/when_exe)
5
5
 
6
- [when_exe](http://rubygems.org/gems/when_exe) is a multicultural and multilingualized calendar library based on [ISO 8601](http://en.wikipedia.org/wiki/ISO_8601), [ISO 19108](http://www.iso.org/iso/home/store/catalogue_tc/catalogue_detail.htm?csnumber=26013), [RFC 5545(iCalendar)](http://tools.ietf.org/html/rfc5545) and [RFC6350](http://tools.ietf.org/html/rfc6350). JSON-LD format for TemporalPosition and TemporalReferenceSystem are available.
6
+ [when_exe](http://rubygems.org/gems/when_exe) is a multicultural and multilingualized calendar library based on [ISO 8601](http://en.wikipedia.org/wiki/ISO_8601), [ISO 19108](http://www.iso.org/iso/home/store/catalogue_tc/catalogue_detail.htm?csnumber=26013), [RFC 5545(iCalendar)](http://tools.ietf.org/html/rfc5545) and [RFC6350](http://tools.ietf.org/html/rfc6350). [JSON-LD](http://www.w3.org/TR/json-ld/) formats for TemporalPosition and TemporalReferenceSystem are available.
7
7
 
8
8
  [<img alt='Architecture' title='display this figure at actual size' src='https://raw.githubusercontent.com/suchowan/when_exe/f7bb8b51259f0c1653c6c37b3ce20bd2a6ab7914/architecture.png' width='637' height='408'/>](https://raw.githubusercontent.com/suchowan/when_exe/f7bb8b51259f0c1653c6c37b3ce20bd2a6ab7914/architecture.png)
9
9
 
@@ -295,39 +295,42 @@ Example Usage
295
295
  p When.when?('TZID=America/New_York:1997-10-26T02:30') #=> 1997-10-26T02:30-05:00
296
296
  p When.when?('TZID=America/New_York:1997-10-26T03:30') #=> 1997-10-26T03:30-05:00
297
297
 
298
+ #
298
299
  # Google Calendar ------------------------------
299
- # https://github.com/suchowan/gcalapi is required for this section's operations.
300
- # Please install gcalapi before operation.
301
- # Please replace xxxxxxxx and ******** to valid id/password pair and access Google Calendar.
300
+ # https://rubygems.org/gems/google-api-client is required for this section's operations.
301
+ # Please install google-api-client and add authorization file 'google-api.yaml' before operation.
302
302
 
303
- service = GoogleCalendar::Service.new('xxxxxxxx@gmail.com', '********')
304
- feed = "http://www.google.com/calendar/feeds/%s__%s%%40holiday.calendar.google.com/public/full" %
305
- ['japanese', 'ja']
306
- gcal = GoogleCalendar::Calendar::new(service, feed)
307
- gcal.enum_for({'start-min'=>'2014-01-01', 'start-max'=>'2015-01-01',
308
- 'orderby'=>'starttime', 'sortorder'=>'a'
309
- }).each do |range|
310
- puts '%s - %s' % [range, range.events[0].summary] #=>
311
- # 2014-01-01T00:00:00.00+09:00...2014-01-02T00:00:00.00+09:00 - 元日
312
- # 2014-01-02T00:00:00.00+09:00...2014-01-03T00:00:00.00+09:00 - 銀行休業日
313
- # 2014-01-03T00:00:00.00+09:00...2014-01-04T00:00:00.00+09:00 - 銀行休業日
314
- # 2014-01-13T00:00:00.00+09:00...2014-01-14T00:00:00.00+09:00 - 成人の日
315
- # 2014-02-11T00:00:00.00+09:00...2014-02-12T00:00:00.00+09:00 - 建国記念の日
316
- # 2014-03-21T00:00:00.00+09:00...2014-03-22T00:00:00.00+09:00 - 春分の日
317
- # 2014-04-29T00:00:00.00+09:00...2014-04-30T00:00:00.00+09:00 - 昭和の日
318
- # 2014-05-03T00:00:00.00+09:00...2014-05-04T00:00:00.00+09:00 - 憲法記念日
319
- # 2014-05-04T00:00:00.00+09:00...2014-05-05T00:00:00.00+09:00 - みどりの日
320
- # 2014-05-05T00:00:00.00+09:00...2014-05-06T00:00:00.00+09:00 - こどもの日
321
- # 2014-05-06T00:00:00.00+09:00...2014-05-07T00:00:00.00+09:00 - みどりの日 振替休日
322
- # 2014-07-21T00:00:00.00+09:00...2014-07-22T00:00:00.00+09:00 - 海の日
323
- # 2014-09-15T00:00:00.00+09:00...2014-09-16T00:00:00.00+09:00 - 敬老の日
324
- # 2014-09-23T00:00:00.00+09:00...2014-09-24T00:00:00.00+09:00 - 秋分の日
325
- # 2014-10-13T00:00:00.00+09:00...2014-10-14T00:00:00.00+09:00 - 体育の日
326
- # 2014-11-03T00:00:00.00+09:00...2014-11-04T00:00:00.00+09:00 - 文化の日
327
- # 2014-11-23T00:00:00.00+09:00...2014-11-24T00:00:00.00+09:00 - 勤労感謝の日
328
- # 2014-11-24T00:00:00.00+09:00...2014-11-25T00:00:00.00+09:00 - 勤労感謝の日 振替休日
329
- # 2014-12-23T00:00:00.00+09:00...2014-12-24T00:00:00.00+09:00 - 天皇誕生日
330
- # 2014-12-25T00:00:00.00+09:00...2014-12-26T00:00:00.00+09:00 - クリスマス
331
- # 2014-12-31T00:00:00.00+09:00...2015-01-01T00:00:00.00+09:00 - 大晦日
303
+ require 'google/api_client'
304
+ require "yaml"
305
+ oauth_yaml = YAML.load_file('google-api.yaml')
306
+ client = Google::APIClient.new(:application_name => "when_exe",
307
+ :application_version => When::VERSION)
308
+ client.authorization.client_id = oauth_yaml["client_id"]
309
+ client.authorization.client_secret = oauth_yaml["client_secret"]
310
+ client.authorization.scope = oauth_yaml["scope"]
311
+ client.authorization.refresh_token = oauth_yaml["refresh_token"]
312
+ client.authorization.access_token = oauth_yaml["access_token"]
313
+ service = client.discovered_api('calendar', 'v3')
314
+ calendar = When::GoogleAPI::Calendar.list(client, service,
315
+ 'en.japanese#holiday@group.v.calendar.google.com')
316
+ calendar.enum_for(When.when?('20150101/1231')).each do |date|
317
+ p [date, date.events[0].summary] #=>
318
+ # [2015-01-01, "New Year's Day"]
319
+ # [2015-01-12, "Coming of Age Day"]
320
+ # [2015-02-11, "National Foundation Day"]
321
+ # [2015-03-21, "Spring Equinox"]
322
+ # [2015-04-29, "Shōwa Day"]
323
+ # [2015-05-03, "Constitution Memorial Day"]
324
+ # [2015-05-04, "Greenery Day"]
325
+ # [2015-05-05, "Children's Day"]
326
+ # [2015-05-06, "Constitution Memorial Day observed"]
327
+ # [2015-07-20, "Sea Day"]
328
+ # [2015-09-21, "Respect for the Aged Day"]
329
+ # [2015-09-22, "Bridge Public holiday"]
330
+ # [2015-09-23, "Autumn Equinox"]
331
+ # [2015-10-12, "Sports Day"]
332
+ # [2015-11-03, "Culture Day"]
333
+ # [2015-11-23, "Labor Thanksgiving Day"]
334
+ # [2015-12-23, "Emperor's Birthday"]
332
335
  end
333
336
 
data/bin/locales.rb CHANGED
@@ -14,7 +14,7 @@ require 'net/https'
14
14
  HEADER = <<HEADER
15
15
  # -*- coding: utf-8 -*-
16
16
  =begin
17
- Copyright (C) 2012-2014 Takashi SUGA
17
+ Copyright (C) 2012-2015 Takashi SUGA
18
18
 
19
19
  You may use and/or modify this file according to the license described in the LICENSE.txt file included in this archive.
20
20
  =end
@@ -1,4 +1,4 @@
1
- {"begin" : "595^^Japanese",
1
+ {"begin" : "593^^Japanese",
2
2
  "end" : "1872^^Japanese",
3
3
  "file" : "japanese.ttl",
4
4
  "resource" : [
data/lib/when_exe.rb CHANGED
@@ -18,11 +18,6 @@ begin
18
18
  autoload :TZInfo, 'tzinfo'
19
19
  rescue LoadError, NoMethodError
20
20
  end
21
- begin
22
- gem 'gcalapi'
23
- autoload :GoogleCalendar, 'when_exe/googlecalendar'
24
- rescue LoadError, NoMethodError
25
- end
26
21
 
27
22
  autoload :URI, 'uri'
28
23
  autoload :OpenURI, 'open-uri'
@@ -60,14 +55,16 @@ module When
60
55
  # @option options [When::Coordinates::Spatial] :location デフォルトの空間位置
61
56
  # @option options [When::TM::IntervalLength] :until V::Event::Enumerator の until
62
57
  # @option options [Hash{String=>String}] :alias Locale の読替パターン ({ 読替前のlocale=>読替後のlocale })
63
- # @option options [String] :namespace_format 名前空間定義の省略時に名前空間生成に用いる書式
58
+ # @option options [Hash{String=>String}] :namespace_format 名前空間定義の省略時に名前空間生成に用いる書式
64
59
  # @option options [Hash{String=>String}] :unification 漢字の包摂パターン ({ 包摂前の文字列=>包摂後の文字列 })
60
+ # @option options [Numeric] :wikipedia_interval Wikipedia の連続的な参照を抑制するための遅延時間/秒
65
61
  # @option options [Array<String>] :order CalendarEra の検索順序 ([ IRI of When::TM::CalendarEra ])
66
62
  # @option options [Hash{String=>Array, String}] :format strftime で用いる記号の定義 ({ 記号=>[ 書式,項目名 ] or 記号列 })
67
63
  # @option options [Array<Array>] :leap_seconds 閏秒の挿入記録 ([ [JD, TAI-UTC, (MJD, OFFSET)] ])
68
64
  # @option options [String] :base_uri Base URI for When_exe Resources (Default When::SourceURI)
69
65
  # @option options [Hash<String=>String>] :additional_namespaces User defined namespaces (Default {})
70
66
  # @option options [String] :root_dir Root Directory for When_exe Resources Cash data (Default When::RootDir)
67
+ # @option options [Boolean] :leave_const If true, leave Constants of When module defined
71
68
  # @option options [Boolean] :direct '_' で終わるメソッドをキャッシュせずに毎回計算するか否か
72
69
  # @option options [Hash{Symbol=>boolean}] :escape 毎回 method_missing を発生させるメソッドを true にする
73
70
  # @option options [false, nil] :escape to_str, to_ary, to_hash のみ毎回 method_missing を発生させる
@@ -158,7 +155,6 @@ module When
158
155
  #
159
156
  RootDir = ENV["WHEN_EXE_ROOT_DIR"] || File.dirname(__FILE__).sub(/\/[^\/]*\z/,'')
160
157
 
161
- require 'when_exe/version'
162
158
  require 'when_exe/locales/locale'
163
159
  require 'when_exe/locales/autoload'
164
160
  require 'when_exe/parts/enumerator'
@@ -170,6 +166,7 @@ module When
170
166
  require 'when_exe/ephemeris'
171
167
  require 'when_exe/coordinates'
172
168
  require 'when_exe/icalendar'
169
+ require 'when_exe/google_api'
173
170
  require 'when_exe/tmobjects'
174
171
  require 'when_exe/timestandard'
175
172
  require 'when_exe/tmposition'
@@ -179,6 +176,7 @@ module When
179
176
  require 'when_exe/region/m17n'
180
177
  require 'when_exe/region/residue'
181
178
  require 'when_exe/inspect'
179
+ require 'when_exe/version'
182
180
  require 'when_exe/linkeddata'
183
181
 
184
182
  #
@@ -232,14 +230,19 @@ module When
232
230
 
233
231
  class BasicTypes::M17n
234
232
  autoload :Japanese, 'when_exe/region/japanese'
233
+ autoload :JapaneseHoliday, 'when_exe/region/japanese'
235
234
  autoload :Chinese, 'when_exe/region/chinese'
235
+ autoload :ChineseLuniSolar, 'when_exe/region/chinese/notes'
236
236
  autoload :Yi, 'when_exe/region/chinese'
237
237
  autoload :Tibetan, 'when_exe/region/tibetan'
238
+ autoload :Vietnamese, 'when_exe/region/vietnamese'
238
239
  autoload :Thai, 'when_exe/region/thai'
239
240
  autoload :Balinese, 'when_exe/region/balinese'
240
241
  autoload :Javanese, 'when_exe/region/javanese'
241
242
  autoload :Indian, 'when_exe/region/indian'
243
+ autoload :Zoroastrian, 'when_exe/region/zoroastrian'
242
244
  autoload :Iranian, 'when_exe/region/iranian'
245
+ autoload :Bahai, 'when_exe/region/bahai'
243
246
  autoload :Islamic, 'when_exe/region/islamic'
244
247
  autoload :Jewish, 'when_exe/region/jewish'
245
248
  autoload :AncientOrient, 'when_exe/region/babylonian'
@@ -247,6 +250,7 @@ module When
247
250
  autoload :Roman, 'when_exe/region/roman'
248
251
  autoload :Coptic, 'when_exe/region/coptic'
249
252
  autoload :French, 'when_exe/region/french'
253
+ autoload :Discordian, 'when_exe/region/discordian'
250
254
  autoload :World, 'when_exe/region/world'
251
255
  autoload :Positivist, 'when_exe/region/positivist'
252
256
  autoload :InternationalFixed, 'when_exe/region/international_fixed'
@@ -320,6 +324,9 @@ module When
320
324
  autoload :Roman, 'when_exe/region/roman'
321
325
  autoload :Gregorian, 'when_exe/region/christian'
322
326
  autoload :FrenchRepublican, 'when_exe/region/french'
327
+ autoload :FrenchRepublicanRomme, 'when_exe/region/french'
328
+ autoload :FrenchRepublicanContinuous, 'when_exe/region/french'
329
+ autoload :FrenchRepublicanTropical,'when_exe/region/french'
323
330
  autoload :World, 'when_exe/region/world'
324
331
  autoload :LongCount, 'when_exe/region/mayan'
325
332
  autoload :Positivist, 'when_exe/region/positivist'
@@ -360,6 +367,8 @@ module When
360
367
  autoload :CommonWithRokuyo, 'when_exe/region/japanese/weeks'
361
368
  autoload :RokuyoWeek, 'when_exe/region/japanese/weeks'
362
369
  autoload :Yis, 'when_exe/region/chinese'
370
+ autoload :ChineseLuniSolar, 'when_exe/region/chinese/notes'
371
+ autoload :ChineseSolar, 'when_exe/region/chinese/notes'
363
372
  autoload :Balinese, 'when_exe/region/balinese'
364
373
  autoload :Javanese, 'when_exe/region/javanese'
365
374
  autoload :Tibetan, 'when_exe/region/tibetan'
@@ -367,10 +376,10 @@ module When
367
376
  autoload :Roman, 'when_exe/region/roman'
368
377
  autoload :Mayan, 'when_exe/region/mayan'
369
378
  autoload :DiscordianWeek, 'when_exe/region/discordian'
370
- autoload :CommonWithSovietFiveDay, 'when_exe/region/soviet'
371
- autoload :SovietFiveDayWeek, 'when_exe/region/soviet'
372
- autoload :CommonWithSovietSixDay, 'when_exe/region/soviet'
373
- autoload :SovietSixDayWeek, 'when_exe/region/soviet'
379
+ autoload :CommonWithSovietFiveDay, 'when_exe/region/russian'
380
+ autoload :SovietFiveDayWeek, 'when_exe/region/russian'
381
+ autoload :CommonWithSovietSixDay, 'when_exe/region/russian'
382
+ autoload :SovietSixDayWeek, 'when_exe/region/russian'
374
383
  # autoload :Yerm, 'when_exe/region/yerm'
375
384
  autoload :WorldWeek, 'when_exe/region/world'
376
385
  autoload :PositivistWeek, 'when_exe/region/positivist'
@@ -385,12 +394,14 @@ module When
385
394
  end
386
395
 
387
396
  module Coordinates
397
+ autoload :Chinese, 'when_exe/region/chinese'
388
398
  autoload :Tibetan, 'when_exe/region/tibetan'
389
399
  autoload :Yi, 'when_exe/region/chinese'
390
400
  autoload :Javanese, 'when_exe/region/javanese'
391
401
  autoload :Indian, 'when_exe/region/indian'
392
402
  autoload :Iranian, 'when_exe/region/iranian'
393
403
  autoload :Bahai, 'when_exe/region/bahai'
404
+ autoload :Russian, 'when_exe/region/russian'
394
405
  autoload :Roman, 'when_exe/region/roman'
395
406
  autoload :Mayan, 'when_exe/region/mayan'
396
407
 
@@ -443,13 +454,13 @@ module When
443
454
  autoload :Jewish, 'when_exe/region/jewish'
444
455
  autoload :AncientOrient, 'when_exe/region/babylonian'
445
456
  autoload :Roman, 'when_exe/region/roman'
446
- autoload :Julian, 'when_exe/region/roman'
457
+ autoload :Julians, 'when_exe/region/roman'
447
458
  autoload :Pope, 'when_exe/region/pope'
448
459
  autoload :Byzantine, 'when_exe/region/christian'
449
460
  autoload :LongCount, 'when_exe/region/mayan'
450
461
 
451
462
  # Defualt search path for Epochs and Eras
452
- DefaultEpochs = ['Common', 'ModernJapanese',
463
+ DefaultEpochs = ['Common', 'ModernJapanese', 'Gregorian', 'Julian',
453
464
  'Hijra', 'Jewish', 'Iranian',
454
465
  'Roman', 'Byzantine', 'AncientOrient', 'LongCount',
455
466
  'BalineseLuniSolar', 'JavaneseLunar',
@@ -515,9 +526,9 @@ module When
515
526
  when TM::TemporalPosition, Parts::GeometricComplex ; specification
516
527
  when TM::Position ; specification.any_other
517
528
  when Array ; begin options = TM::TemporalPosition._options(options) ; specification.map {|e| when?(e, options)} end
518
- when /\Atoday(\^{1,2}(.+))?\z/i ; today($2 ? {:frame=>$2}.update(options) : options)
519
- when /\Anow(\^{1,2}(.+))?\z/i ; now( $2 ? {:frame=>$2}.update(options) : options)
520
- when /(JDN|MJD|SDN|CEP)(\z|\^)/i; TM::JulianDate.parse(specification, options)
529
+ when /\Atoday((\^|%5E){1,2}(.+))?\z/i ; today($3 ? {:frame=>$3}.update(options) : options)
530
+ when /\Anow((\^|%5E){1,2}(.+))?\z/i ; now( $3 ? {:frame=>$3}.update(options) : options)
531
+ when /(JDN|MJD|SDN|CEP)(\z|\^|%5E)/i ; TM::JulianDate.parse(specification, options)
521
532
  when /[\n\r]+/ ; when?(specification.split(/[\n\r]+/), options)
522
533
  when String ; TM::TemporalPosition._instance(EncodingConversion.to_internal_encoding(specification), options)
523
534
  when Numeric ; TM::JulianDate.new(+specification, TM::TemporalPosition._options(options))
@@ -1,771 +1,772 @@
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
- # ISO 19108 以外の ISO に規定のある基本的なデータ型
11
- # およびその subclass
12
- module BasicTypes
13
-
14
- #
15
- # ISO 8601 Date and Time Representation
16
- #
17
- # see {xml schema}[link:http://www.w3.org/2001/XMLSchema-datatypes#date_time]
18
- #
19
- class DateTime < String
20
-
21
- class << self
22
-
23
- # When.exe Standard Representation 形式の表現を分解してArray化する
24
- #
25
- # @param [String] date_time 日時を表現する When.exe Standard Representation 形式の文字列
26
- # @param [Hash] options 以下の通り
27
- # @option options [String, Array<String, Integer>] :era_name デフォルトの年号(Integerは0年に対応する通年)
28
- # @option options [Array<Numeric>] :abbr 上位省略形式で使用する上位部分
29
- # @option options [Integer] :extra_year_digits ISO8601拡大表記のための年の構成要素拡大桁数(省略時 1桁)
30
- # @option options [Integer] :ordinal_date_digits ISO8601拡大表記の年内通日の桁数(省略時 3桁)
31
- #
32
- # @return [Array] format, date, time, clock, era
33
- #
34
- # format (Symbol, nil)
35
- # nil 通常形式
36
- # :century 世紀指定形式 ('CC', '+CCCC', '-CCCC')
37
- # :day 年間通算日形式 ('YYDDD'など)
38
- # :week 暦週形式 ('YYWNN'など)
39
- #
40
- # date (Array<Numeric>) 日付部分
41
- #
42
- # time (Array<Numeric>) 時刻部分
43
- #
44
- # clock (String) 時間帯
45
- #
46
- # era (String, Array<String, Integer>) 年号(Integerは0年に対応する通年)
47
- #
48
- def _to_array(date_time, options={})
49
- raise TypeError, "Argument is not ISO 8601 String" unless date_time.kind_of?(String)
50
- if options[:abbr].kind_of?(When::TimeValue)
51
- options[:abbr] = ((options[:frame]||When::Gregorian) ^ options[:abbr]).cal_date
52
- end
53
- date_time = date_time.gsub(/_([\d])/, '\1')
54
- begin
55
- return _to_array_basic(date_time, options)
56
- rescue ArgumentError
57
- return _to_array_extended(date_time, options)
58
- end
59
- end
60
-
61
- private
62
-
63
- # ISO 8601 基本形式の表現を分解して配列化する
64
- def _to_array_basic(date_time, options={})
65
-
66
- case date_time
67
- # basic date & time format (ISO 8601)
68
- when /\A([-+W\d]+)(?:(T([.,\d]+)?)([A-Z]+(\?.+)?|[-+]\d+)?)?\z/
69
- d, t, time, clock = $~[1..4]
70
- format, date = Date._to_array_basic_ISO8601(d, options)
71
-
72
- # basic date & time format (JIS X0301)
73
- when /\A([.\d]+)(?:(T([.,\d]+)?)([A-Z]+(\?.+)?|[-+]\d+)?)?\z/
74
- raise ArgumentError, "Wrong date format" unless options[:era_name]
75
- d, t, time, clock = $~[1..4]
76
- format, date = Date._to_array_basic_X0301(d, options)
77
- era = options[:era_name]
78
-
79
- # basic time format (ISO 8601)
80
- when /\A(T(-{0,2}[.,\d]+)?)([A-Z]+(\?.+)?|[-+]\d+)?\z/
81
- t, time, clock = $~[1..3]
82
-
83
- # not supported
84
- else
85
- raise ArgumentError, "Wrong date format: #{date_time}"
86
- end
87
-
88
- return [format, date, Time._to_array_basic(time, t, options),
89
- Time._to_string_clock(clock), era]
90
- end
91
-
92
- # ISO 8601 拡張形式の表現を分解して配列化する
93
- def _to_array_extended(date_time, options={})
94
-
95
- case date_time
96
- # extended date & time format (ISO 8601)
97
- when /\A(([-+*&%@!>=<?\dW.\(\)]|\{.+?\})+)(?:(T([:*=.,\d]+)?)([A-Z]+(\?.+)?|[-+][:\d]+)?)?\z/
98
- d, v, t, time, clock = $~[1..5]
99
- d, r = _split_residue(d, options[:abbr]) if d =~ /\{/
100
- if d =~ /[\(\)]/
101
- d = When::CalendarTypes::Yerm.parse(d, options[:abbr])
102
- options[:frame] ||= 'Yerm'
103
- end
104
- format, date = Date._to_array_extended_ISO8601(d, options)
105
-
106
- # extended date & time format (JIS X0301)
107
- when /\A((.+::)?(\[[^\]]+\]|[^-+\d{]+))(([-+*&%@!>=<?\dW.\(\)]|\{.+?\})+)?(?:(T([:*=.,\d]+)?)([A-Z]+(\?.+)?|[-+][:\d]+)?)?\z/
108
- era, parent, child, d, v, t, time, clock = $~[1..8]
109
- d, r = _split_residue(d, options[:abbr]) if d =~ /\{/
110
- format, date, era = Date._to_array_extended_X0301(d, era, options)
111
- era ||= options[:era_name] if d =~ /\./
112
-
113
- # extended time format (ISO 8601)
114
- when /\A(T(-{0,2}[:*=.,\d]+)?)([A-Z]+(\?.+)?|[-+][:\d]+)?\z/
115
- t, time, clock = $~[1..3]
116
-
117
- # not supported
118
- else
119
- raise ArgumentError, "Wrong date format: #{date_time}"
120
- end
121
-
122
- return [format, date, Time._to_array_extended(time, t, options),
123
- Time._to_string_clock(clock), era, r]
124
- end
125
-
126
- # 剰余類の指定を置き換える
127
- def _split_residue(d, abbr)
128
- abbr, = abbr
129
- residue = {}
130
- count = 0
131
- sign, d = d =~ /^-/ ? ['-', d[1..-1]] : ['', d]
132
- [sign + d.gsub(/[-+*&%@!>=<?.]|\{.+?\}/) {|s|
133
- if s =~ /\{/
134
- residue[count] = s[1..-2]
135
- count == 0 ? (abbr || 1) : ''
136
- else
137
- count += 1
138
- s
139
- end
140
- }, residue]
141
- end
142
- end
143
- end
144
-
145
- #
146
- # ISO 8601 Date Representation
147
- #
148
- # see {xml schema}[link:http://www.w3.org/2001/XMLSchema-datatypes#date]
149
- #
150
- class Date < DateTime
151
-
152
- # @private
153
- Extra_Year_Digits = Hash.new {|hash, key|
154
- ex = (key || 1).to_i
155
- hash[key] =
156
- if ex > 0
157
- [
158
- /\A(\d{2})\z/,
159
- /\A([-+]\d{#{4+ex}})(\d{2})(\d{2})\z/,
160
- /\A([-+]\d{#{4+ex}})-(\d{2})\z/,
161
- /\A([-+]\d{#{4+ex}})\z/,
162
- /\A([-+]\d{#{4+ex}})W(\d{2})(\d{1})?\z/,
163
- /\A([+]\d{#{2+ex}})\z/,
164
- /\A([-]\d{#{2+ex}})\z/,
165
- /\A([-+]\d{#{4+ex}})(\d{3})\z/
166
- ]
167
- elsif ex == 0
168
- [/\A(\d{2})\z/] + [/\A(\d{4})\z/] * 6
169
- else
170
- [/\A(\d{4})\z/] * 7
171
- end
172
- }
173
-
174
- # @private
175
- Ordinal_Date_Digits = Hash.new {|hash, key|
176
- hash[key] = /\A(\d{#{(key || 3).to_i}})\z/
177
- }
178
-
179
- class << self
180
- # ISO 8601 基本形式の表現を分解して配列化する
181
- def _to_array_basic_ISO8601(date, options={})
182
- by, bm, bd = options[:abbr]
183
- extra_reg = Extra_Year_Digits[options[:extra_year_digits]]
184
- case date
185
- when nil ; return nil
186
- when /\A(\d{4})(\d{2})(\d{2})\z/ ; return nil, [$1.to_i, $2.to_i, $3.to_i] # 5.2.1.1
187
- when /\A(\d{4})-(\d{2})\z/ ; return nil, [$1.to_i, $2.to_i] # 5.2.1.2
188
- when /\A(\d{4})\z/ ; return nil, [$1.to_i] # 5.2.1.2
189
- when extra_reg[0] ; return :century,[$1.to_i * 100] # 5.2.1.2
190
- when /\A(\d{4})(\d{3})\z/ ; return :day, [$1.to_i, $2.to_i] # 5.2.2.1
191
- when /\A(\d{4})W(\d{2})(\d{1})?\z/ ; return :week, [$1.to_i, $2.to_i, _int($3)] # 5.2.3.1-2
192
- when extra_reg[1] ; return nil, [$1.to_i, $2.to_i, $3.to_i] # 5.2.1.4 a)
193
- when extra_reg[2] ; return nil, [$1.to_i, $2.to_i] # 5.2.1.4 b)
194
- when extra_reg[3] ; return nil, [$1.to_i] # 5.2.1.4 c)
195
- when extra_reg[4] ; return :week, [$1.to_i, $2.to_i, _int($3)] # 5.2.3.4 a-b)
196
- when extra_reg[5] ; return :century,[$1.to_i * 100] # 5.2.1.4 d)
197
- when extra_reg[6] ; return :century,[$1.to_i * 100] unless by # 5.2.1.4 d)
198
- when extra_reg[7] ; return :day, [$1.to_i, $2.to_i] # 5.2.2.3 a)
199
- else ; raise ArgumentError, "Wrong date format" unless by
200
- end
201
-
202
- by = by.to_i
203
- case date
204
- when /\A(\d{2})(\d{2})(\d{2})\z/ ; return nil, [_century($1,by), $2.to_i, $3.to_i] # 5.2.1.3 a)
205
- when /\A-(\d{2})(\d{2})?\z/ ; return nil, [_century($1,by), _int($2)] # 5.2.1.3 b-c)
206
- when /\A--(\d{2})(\d{2})?\z/ ; return nil, [by, $1.to_i, _int($2)] # 5.2.1.3 d-e)
207
- when /\A(\d{2})(\d{3})\z/ ; return :day, [_century($1,by), $2.to_i] # 5.2.2.2 a)
208
- when /\A-(\d{3})\z/ ; return :day, [by, $1.to_i] # 5.2.2.2 b)
209
- when /\A(\d{2})W(\d{2})(\d{1})?\z/ ; return :week, [_century($1,by), $2.to_i, _int($3)] # 5.2.3.3 a-b)
210
- when /\A-(\d{1})W(\d{2})(\d{1})?\z/ ; return :week, [_decade($1,by), $2.to_i, _int($3)] # 5.2.3.3 c-d)
211
- when /\A-W(\d{2})(\d{1})?\z/ ; return :week, [by, $1.to_i, _int($2)] # 5.2.3.3 e-f)
212
- else ; raise ArgumentError, "Wrong date format" unless bm
213
- end
214
-
215
- bm = bm.to_i
216
- case date
217
- when /\A---(\d{2})\z/ ; return nil, [by, bm, $1.to_i] # 5.2.1.3 f)
218
- when /\A-W-(\d{1})\z/ ; return :week, [by, bm, $1.to_i] # 5.2.3.3 g)
219
- when /\A----\z/ ; return nil, [by, bm, bd.to_i] if bd # extension
220
- end
221
-
222
- raise ArgumentError, "Wrong date format: #{date}"
223
- end
224
-
225
- # JIS X0301 基本形式の表現を分解して配列化する
226
- def _to_array_basic_X0301(date, options={})
227
- raise ArgumentError, "Wrong date format" unless date =~ /\./
228
- date.scan(/\d+\./) do |part|
229
- raise ArgumentError, "Wrong date format" unless part.length == 3
230
- end
231
- _to_array_basic_ISO8601(date.gsub(/\./, ''), {:abbr=>options[:abbr]||1})
232
- end
233
-
234
- # ISO 8601 拡張形式の表現を分解して配列化する
235
- def _to_array_extended_ISO8601(date, options={})
236
- return nil unless date
237
- abbr = Array(options[:abbr]).dup
238
- unless date =~ /\A([-+]?\d+#{abbr[0] ? '|-' : ''})([-*=.])?(.*)/
239
- raise ArgumentError, "Wrong date format: #{date}"
240
- end
241
- date = $3
242
- dd = [Coordinates::Pair._en_pair(_completion($1, abbr.shift), $2)]
243
- while date =~ /\A(\d+#{abbr[0] ? '|-' : ''})([-+*&%@!>=<?.])(.+)/
244
- date = $3
245
- dd << Coordinates::Pair._en_pair(_completion($1, abbr.shift), $2)
246
- end
247
- case date
248
- when /\AW(\d+#{abbr[0] ? '|-' : ''})([-+*&%@!>=<?.])?(\d+)?([-*=?%@])?\z/
249
- dd << Coordinates::Pair._en_pair(_completion($1, abbr.shift), $2)
250
- dd << Coordinates::Pair._en_pair($3, $4)
251
- return :week, dd
252
- when Ordinal_Date_Digits[options[:ordinal_date_digits]]
253
- dd << $1.to_i
254
- return :day, dd
255
- when /\A(\d+#{abbr[0] ? '|-' : ''})([-+*&%@!>=<?.])?\z/
256
- dd << Coordinates::Pair._en_pair(_completion($1, abbr.shift), $2)
257
- return nil, dd
258
- when ''
259
- return nil, dd
260
- else
261
- raise ArgumentError, "Wrong date format: #{date}"
262
- end
263
- end
264
-
265
- # JIS X0301 拡張形式の表現を分解して配列化する
266
- def _to_array_extended_X0301(date, era, options={})
267
- if (date =~ /\A([-+\d]+)\(([-+\d]+)\)(.*)\z/)
268
- year = $2
269
- date = $1 + $3
270
- end
271
- format, date = _to_array_extended_ISO8601(date, options)
272
- if (year)
273
- yy = year.to_i
274
- ee = date[0] * 1
275
- era = [era, yy-ee, yy+ee]
276
- end
277
- return format, date, era
278
- end
279
-
280
- private
281
-
282
- def _completion(digits, base)
283
- case digits
284
- when nil ; return nil
285
- when /\A\d{5}/ ; raise ArgumentError, "Wrong date format: #{digits}" if base
286
- else ; return digits.to_i unless base
287
- end
288
-
289
- base = base.to_i
290
- case digits
291
- when '-' ; return base
292
- when /\A-?(\d{1})\z/ ; return _decade( $1, base)
293
- when /\A-?(\d{2})\z/ ; return _century($1, base)
294
- else ; return digits.to_i
295
- end
296
- end
297
-
298
- def _century(year, base)
299
- quotient, remainder = base.divmod(100)
300
- year = year.to_i
301
- quotient += 1 if year < remainder
302
- return quotient * 100 + year
303
- end
304
-
305
- def _decade(year, base)
306
- quotient, remainder = base.divmod(10)
307
- year = year.to_i
308
- quotient += 1 if year < remainder
309
- return quotient * 10 + year
310
- end
311
-
312
- def _int(digits)
313
- return digits ? digits.to_i : nil
314
- end
315
- end
316
- end
317
-
318
- #
319
- # ISO 8601 Time Representation
320
- #
321
- # see {xml schema}[link:http://www.w3.org/2001/XMLSchema-datatypes#time]
322
- #
323
- class Time < DateTime
324
-
325
- class << self
326
- # 基本形式の表現を分解して配列化する
327
- def _to_array_basic(time, t, options={})
328
- return nil unless t
329
- return [0] unless time
330
- time.sub!(/,/, '.')
331
- unless (time =~ /\A(\d{2}(?:\.\d+)?|-)(\d{2}(?:\.\d+)?|-)?(\d{2}(\.\d+)?)?\z/)
332
- raise ArgumentError, "Wrong time format: #{time}"
333
- end
334
- indices = options[:frame] ? When.Calendar(options[:frame]).indices : Coordinates::DefaultDateIndices
335
- abbr = Array(options[:abbr]).dup
336
- abbr[0..indices.length] = []
337
- return [0, Coordinates::Pair._en_number($1=='-' ? abbr[0] : $1, nil),
338
- Coordinates::Pair._en_number($2=='-' ? abbr[1] : $2, nil),
339
- Coordinates::Pair._en_number($3, nil)]
340
- end
341
-
342
- # 拡張形式の表現を分解して配列化する
343
- def _to_array_extended(time, t, options={})
344
- return nil unless t
345
- return [0] unless time
346
- indices = options[:frame] ? When.Calendar(options[:frame]).indices : Coordinates::DefaultDateIndices
347
- abbr = Array(options[:abbr]).dup
348
- abbr[0..indices.length] = []
349
- time.sub!(/,/, '.')
350
- if time =~ /\A([:*=])(.+)/
351
- time = $2
352
- tt = [Coordinates::Pair._en_pair(0, $1)]
353
- else
354
- tt = [0]
355
- end
356
- while time =~ /\A(\d{2}(?:\.\d+)?|-)([:*=])(.+)/
357
- time = $3
358
- tt << Coordinates::Pair._en_pair($1=='-' ? abbr.shift : $1, $2)
359
- end
360
- case time
361
- when /\A(\d{2}(\.\d+)?)\z/
362
- tt << Coordinates::Pair._en_number($1, nil)
363
- when ''
364
- else
365
- raise ArgumentError, "Wrong time format: #{time}"
366
- end
367
- return tt
368
- end
369
-
370
- # 時間帯の表現を正規化する
371
- def _to_string_clock(clock)
372
- return nil unless clock
373
- return clock if (clock =~ /\A[A-Z]+(\?.+)?\z/)
374
- raise ArgumentError, "Wrong clock format: #{clock}" unless clock =~ /\A([-+])(\d{2})(?::?(\d{2}))?(?::?(\d{2}))?\z/
375
- sgn, h, m, s = $~[1..4]
376
- zone = sgn + h + ':' + (m||'00')
377
- zone += s if s
378
- return zone
379
- end
380
- end
381
- end
382
-
383
- # コード
384
- #
385
- # 当該コードを定義している辞書, シソーラスまたは機関への参照を
386
- # オプショナルな codeSpace 属性に保持することができる文字列
387
- #
388
- # see {http://schemas.opengis.net/gml/3.1.1/base/basicTypes.xsd#CodeType gml schema}
389
- #
390
- class Code < String
391
-
392
- # an optional codeSpace
393
- #
394
- # @return [String] anyURI (Optional)
395
- attr_accessor :code_space
396
- alias :codeSpace :code_space
397
- private :code_space=
398
-
399
- # オブジェクトの生成
400
- #
401
- # @param [String] code Text token
402
- # @param [String] namespace code を定義している authority の URI
403
- #
404
- def initialize(code, namespace=nil)
405
- @code_space = namespace
406
- self[0..-1] = code
407
- end
408
- end
409
-
410
- #
411
- # == 多言語対応文字列
412
- #
413
- # 本ライブラリで用いる諸々の用語を多言語対応で曖昧性なく管理するため
414
- # Code の subclass として定義する
415
- #
416
- # == 内部変数
417
- # === self[ 0..-1 ] : String
418
- # インスタンスを代表する文字列
419
- # 通常の String として振舞う場合は、この文字列として振舞う
420
- #
421
- # === @locale : Hash
422
- # インスタンスがさす言葉の諸言語での表現を文字列として保持する
423
- # locale指定('lang_country.encoding') => その locale での文字列
424
- # locale指定の要素に省略がある場合、残った共通の要素によって文字列を特定する
425
- # Ex. @locale = {'en'=>'March', 'ja'=>'三月'} ならば、locale が
426
- # 'en_US', 'en_GB' のいずれでもlocale での文字列は 'March'
427
- #
428
- # === @namespace : Hash
429
- # インスタンスがさす言葉の意味を特定するための authority の URI を保持する
430
- # locale指定('lang_country.encoding') => その locale での authority の URI
431
- # locale指定の要素に省略がある場合、残った共通の要素によってURIを特定する
432
- # Ex. @locale = {'en'=>'en:March', 'ja'=>'ja:3%E6%9C%88'} ならば、locale が
433
- # 'en_US', 'en_GB' のいずれでもlocale での authority の URIは 'en:March'
434
- # 当該用語が標準管理機関で管理されていない場合、wikipedia の当該項目の URI を用いる
435
- #
436
- # === @code_space : String
437
- # 代表的な authority の URI
438
- # @namespace[''] である
439
- #
440
- # see {When::Locale}, {When::Parts::Resource}
441
- #
442
- class M17n < Code
443
- include When::Locale
444
- include Parts::Resource
445
-
446
- # @private
447
- HashProperty = [:label, :names, :link, :access_key, :code_space]
448
-
449
- # @private
450
- LabelTypes = {
451
- 'Residue' => ['Coordinates', '%s', '_co:%s%s' ],
452
- 'Week' => ['CalendarNote', '%sWeek', '_n:%sWeek%s' ],
453
- 'Notes' => ['CalendarNote', '%s', '_n:%s/Notes%s'],
454
- nil => ['BasicTypes::M17n', '%s', '_m:%s%s' ]
455
- }
456
-
457
- class << self
458
-
459
- #
460
- # resource の取得
461
- #
462
- # @param [When::Parts::Resource, String] source
463
- #
464
- # @return [When::Parts::Resource]
465
- #
466
- # @private
467
- def _label(source)
468
- case source
469
- when Parts::Resource, nil ; return source
470
- when Parts::Resource::IRIHeader ; return Parts::Resource._instance(source)
471
- end
472
- iri = Parts::Resource._abbreviation_to_iri(source, LabelTypes)
473
- iri ? Parts::Resource._instance(iri) : nil
474
- end
475
-
476
- #
477
- # label の取得
478
- #
479
- # @param [When::Parts::Resource, String] source
480
- #
481
- # @return [When::BasicTypes::M17n, String]
482
- #
483
- def label(source)
484
- resource = _label(source)
485
- case resource
486
- when nil ; return source
487
- when M17n ; return resource
488
- when Parts::Resource ; return resource.label
489
- else ; return resource
490
- end
491
- end
492
-
493
- #
494
- # label の Array の取得
495
- #
496
- # @param [When::Parts::Resource, Array] source
497
- #
498
- # @return [Array]
499
- #
500
- def labels(source)
501
- array =
502
- if source.kind_of?(Array)
503
- source
504
- else
505
- resource = _label(source)
506
- return nil unless resource
507
- resource.child
508
- end
509
- case array[0]
510
- when M17n ; return array
511
- when Parts::Resource ; return array.map {|v| v.label}
512
- else ; return array
513
- end
514
- end
515
- end
516
-
517
- #
518
- # 代表名
519
- #
520
- # @return [String]
521
- #
522
- attr_reader :label
523
-
524
- #
525
- # 名前が意味するもの自体のオブジェクト
526
- #
527
- # @return [When::BasicTypes::Object]
528
- #
529
- alias :what :parent
530
-
531
- #
532
- # When::BasicTypes::M17n に変換する - 何もしないで自身を返す
533
- #
534
- # @return [When::BasicTypes::M17n]
535
- #
536
- def to_m17n
537
- self
538
- end
539
-
540
- #
541
- # 内部エンコーディング文字列化
542
- #
543
- def to_internal_encoding
544
- _copy({:label => When::EncodingConversion.to_internal_encoding(to_s),
545
- :names => Hash[*(names.keys.map {|name| [name, When::EncodingConversion.to_internal_encoding(names[name])]}).flatten],
546
- :link => link,
547
- :access_key => access_key,
548
- :code_space => code_space
549
- })
550
- end
551
-
552
- #
553
- # 外部エンコーディング文字列化
554
- #
555
- def to_external_encoding
556
- _copy({:label => When::EncodingConversion.to_external_encoding(to_s),
557
- :names => Hash[*(names.keys.map {|name| [name, When::EncodingConversion.to_external_encoding(names[name])]}).flatten],
558
- :link => link,
559
- :access_key => access_key,
560
- :code_space => code_space
561
- })
562
- end
563
-
564
- # オブジェクトの生成
565
- #
566
- # @overload initialize(names, namespace={}, locale=[])
567
- # @param [Array<String>] names
568
- #
569
- # [String] '*locale:label=prefix:link'
570
- # * - 存在すれば、label をインスタンスを代表する文字列とする
571
- # locale - label に対応する locale指定(なければ、locale 引数の指定を用いる)
572
- # label - locale 指定に対応する label
573
- # prefix:link - その locale での authority の URI
574
- # prefix: - namespace 引数の指定により URI に展開する
575
- # link - なければ labelをURI encodeして用いる
576
- #
577
- # @param [Hash] namespace { prefix=>uri }
578
- #
579
- # lables, locale 引数の prefix の展開に用いる
580
- #
581
- # @param [Array<String>] locale
582
- #
583
- # [String] '*locale=prefix:link'
584
- # * - 存在すれば、label をインスタンスを代表する文字列とする
585
- # locale - locale指定
586
- # prefix:link - authority の URI
587
- # prefix: - namespace 引数の指定により URI に展開する
588
- #
589
- # @example
590
- # M17n.new(['3月', 'fr:Mars=http://fr.wikipedia.org/wiki/Mars_(mois)', 'March'],
591
- # {'en_wikipedia'=>'http://en.wikipedia.org/wiki/',
592
- # 'ja_wikipedia'=>'http://ja.wikipedia.org/wiki/'},
593
- # ['=ja_wikipedia:', '*en=en_wikipedia:']) を行うと、生成された M17n では、
594
- # @names = {'' =>'3月', 'fr'=>'Mars', 'en'=>'March'}
595
- # @namespace = {'' =>'http://ja.wikipedia.org/wiki/3%E6%9C%88',
596
- # 'fr'=>'http://fr.wikipedia.org/wiki/Mars_(mois)',
597
- # 'en'=>'http://en.wikipedia.org/wiki/March'}
598
- # となり、通常の String として振舞う場合は 'March' として振舞う
599
- #
600
- def initialize(*args)
601
- rest, options = _attributes(args)
602
- _sequence
603
-
604
- return _pool[@label.to_s] ?
605
- _copy_all(_pool[@label.to_s]) : # 階層になった Resource の代表ラベルのための生成
606
- _copy(options) if @label # M17n#to_h の出力と書式互換の入力による生成
607
-
608
- case rest[0]
609
- when When::Parts::Resource::ContentLine
610
- content, namespace = rest
611
- namespace ||= {}
612
- names = []
613
- locale = []
614
- begin
615
- loc = content.attribute['language'].object
616
- locale << [nil, loc, namespace[loc]]
617
- name = content.object
618
- ref = content.attribute['reference'] || content.attribute['url']
619
- name += '=' + (/\ANUL\z/i =~ ref.object ? '' : ref.object) if ref
620
- names << name
621
- end while (content = content.same_altid)
622
- @names ||= names.reverse
623
- @namespace ||= namespace if namespace.kind_of?(Hash)
624
- @locale ||= locale.reverse
625
- when nil ;
626
- else
627
- names, namespace, locale = rest
628
- @names = names if names
629
- @namespace ||= When::Locale._namespace(namespace) if namespace
630
- @locale ||= When::Locale._locale(locale) if locale
631
- end
632
- @namespace ||= {}
633
- @locale ||= []
634
-
635
- @code_space = @namespace['']
636
- self[0..-1] = @label = _names(@names, @namespace, @locale)
637
- end
638
- end
639
-
640
- #
641
- # Abstract class for instance having permanent life with IRI
642
- #
643
- # see {When::Parts::Resource}
644
- # see {http://schemas.opengis.net/gml/3.1.1/base/basicTypes.xsd#ObjectType gml schema}
645
- #
646
- class Object
647
-
648
- include Parts::Resource
649
-
650
- # 名前
651
- #
652
- # @return [String, When::BasicTypes::M17n]
653
- #
654
- attr_reader :label
655
-
656
- private
657
-
658
- # オブジェクトの初期化
659
- def initialize(*args)
660
- @_lock_ = Mutex.new if When.multi_thread
661
- _normalize(*_attributes(args))
662
- _sequence
663
- end
664
- end
665
- end
666
-
667
- #
668
- # RS::Identifier を提供する
669
- #
670
- module RS
671
-
672
- # 参照系の識別子
673
- #
674
- # see {http://schemas.opengis.net/gml/3.1.1/base/referenceSystems.xsd#IdentifierType gml schema}
675
- #
676
- class Identifier
677
-
678
- # The code or name for this Identifier
679
- #
680
- # @return [When::BasicTypes::Code]
681
- #
682
- attr_reader :name
683
-
684
- # Identifier of the version of the associated codeSpace or code
685
- #
686
- # @return [Array<String>]
687
- #
688
- attr_reader :version
689
-
690
- # Remarks about this code or alias
691
- #
692
- # @return [Array<String>] String は URI/IRI文字列の場合あり
693
- #
694
- attr_reader :remarks
695
-
696
- # オブジェクトの生成
697
- #
698
- # @param [When::BasicTypes::Code] name
699
- # @param [Array<String>] version
700
- # @param [Array<String>] remarks String は URI/IRI文字列の場合あり
701
- #
702
- def initialize(name, version=nil, remarks=nil)
703
- @name = name
704
- @version = version
705
- @remarks = remarks
706
- end
707
-
708
- # その他のメソッド
709
- #
710
- # @note When::RS::Identifier で定義されていないメソッドは
711
- # 処理を @name (type: When::BasicTypes::Code) に委譲する
712
- #
713
- def method_missing(name, *args, &block)
714
- self.class.module_eval %Q{
715
- def #{name}(*args, &block)
716
- @name.send("#{name}", *args, &block)
717
- end
718
- } unless When::Parts::MethodCash.escape(name)
719
- @name.send(name, *args, &block)
720
- end
721
- end
722
- end
723
-
724
- #
725
- # EX::Extent を提供する
726
- #
727
- module EX
728
-
729
- # 参照系の時間的および空間的な使用範囲を記述する
730
- #
731
- # 本ライブラリでは、時間的使用範囲を記述ためにのみ使用している
732
- #
733
- # see {http://schemas.opengis.net/gml/3.1.1/base/referenceSystems.xsd#ExtentType gml schema}
734
- #
735
- class Extent
736
-
737
- # time periods
738
- #
739
- # 時間的使用範囲の上限と下限を示す
740
- #
741
- # @return [When::TM::Period]
742
- #
743
- attr_reader :temporal_extent
744
- alias :temporalExtent :temporal_extent
745
-
746
- # オブジェクトの生成
747
- #
748
- # @param [When::TM::Period] extent
749
- #
750
- def initialize(extent)
751
- @temporal_extent = extent
752
- end
753
-
754
- # その他のメソッド
755
- #
756
- # @note When::EX::Extent で定義されていないメソッドは
757
- # 処理を @temporal_extent (type: When::TM::Period) に委譲する
758
- #
759
- def method_missing(name, *args, &block)
760
- self.class.module_eval %Q{
761
- def #{name}(*args, &block)
762
- list = args.map {|arg| arg.kind_of?(self.class) ? arg.temporal_extent : arg}
763
- @temporal_extent.send("#{name}", *list, &block)
764
- end
765
- } unless When::Parts::MethodCash.escape(name)
766
- list = args.map {|arg| arg.kind_of?(self.class) ? arg.temporal_extent : arg}
767
- @temporal_extent.send(name, *list, &block)
768
- end
769
- end
770
- end
771
- end
1
+ # -*- coding: utf-8 -*-
2
+ =begin
3
+ Copyright (C) 2011-2015 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
+ # ISO 19108 以外の ISO に規定のある基本的なデータ型
11
+ # およびその subclass
12
+ module BasicTypes
13
+
14
+ #
15
+ # ISO 8601 Date and Time Representation
16
+ #
17
+ # see {xml schema}[link:http://www.w3.org/2001/XMLSchema-datatypes#date_time]
18
+ #
19
+ class DateTime < String
20
+
21
+ class << self
22
+
23
+ # When.exe Standard Representation 形式の表現を分解してArray化する
24
+ #
25
+ # @param [String] date_time 日時を表現する When.exe Standard Representation 形式の文字列
26
+ # @param [Hash] options 以下の通り
27
+ # @option options [String, Array<String, Integer>] :era_name デフォルトの年号(Integerは0年に対応する通年)
28
+ # @option options [Array<Numeric>] :abbr 上位省略形式で使用する上位部分
29
+ # @option options [Integer] :extra_year_digits ISO8601拡大表記のための年の構成要素拡大桁数(省略時 1桁)
30
+ # @option options [Integer] :ordinal_date_digits ISO8601拡大表記の年内通日の桁数(省略時 3桁)
31
+ #
32
+ # @return [Array] format, date, time, clock, era
33
+ #
34
+ # format (Symbol, nil)
35
+ # nil 通常形式
36
+ # :century 世紀指定形式 ('CC', '+CCCC', '-CCCC')
37
+ # :day 年間通算日形式 ('YYDDD'など)
38
+ # :week 暦週形式 ('YYWNN'など)
39
+ #
40
+ # date (Array<Numeric>) 日付部分
41
+ #
42
+ # time (Array<Numeric>) 時刻部分
43
+ #
44
+ # clock (String) 時間帯
45
+ #
46
+ # era (String, Array<String, Integer>) 年号(Integerは0年に対応する通年)
47
+ #
48
+ def _to_array(date_time, options={})
49
+ raise TypeError, "Argument is not ISO 8601 String" unless date_time.kind_of?(String)
50
+ if options[:abbr].kind_of?(When::TimeValue)
51
+ options[:abbr] = ((options[:frame]||When::Gregorian) ^ options[:abbr]).cal_date
52
+ end
53
+ date_time = date_time.gsub(/[_\s]+([\d])/, '\1')
54
+ begin
55
+ return _to_array_basic(date_time, options)
56
+ rescue ArgumentError
57
+ return _to_array_extended(date_time, options)
58
+ end
59
+ end
60
+
61
+ private
62
+
63
+ # ISO 8601 基本形式の表現を分解して配列化する
64
+ def _to_array_basic(date_time, options={})
65
+
66
+ case date_time
67
+ # basic date & time format (ISO 8601)
68
+ when /\A([-+W\d]+)(?:(T([.,\d]+)?)([A-Z]+(\?.+)?|[-+]\d+)?)?\z/
69
+ d, t, time, clock = $~[1..4]
70
+ format, date = Date._to_array_basic_ISO8601(d, options)
71
+
72
+ # basic date & time format (JIS X0301)
73
+ when /\A([.\d]+)(?:(T([.,\d]+)?)([A-Z]+(\?.+)?|[-+]\d+)?)?\z/
74
+ raise ArgumentError, "Wrong date format" unless options[:era_name]
75
+ d, t, time, clock = $~[1..4]
76
+ format, date = Date._to_array_basic_X0301(d, options)
77
+ era = options[:era_name]
78
+
79
+ # basic time format (ISO 8601)
80
+ when /\A(T(-{0,2}[.,\d]+)?)([A-Z]+(\?.+)?|[-+]\d+)?\z/
81
+ t, time, clock = $~[1..3]
82
+
83
+ # not supported
84
+ else
85
+ raise ArgumentError, "Wrong date format: #{date_time}"
86
+ end
87
+
88
+ return [format, date, Time._to_array_basic(time, t, options),
89
+ Time._to_string_clock(clock), era]
90
+ end
91
+
92
+ # ISO 8601 拡張形式の表現を分解して配列化する
93
+ def _to_array_extended(date_time, options={})
94
+
95
+ case date_time
96
+ # extended date & time format (ISO 8601)
97
+ when /\A(([-+*&%@!>=<?\dW.\(\)]|\{.+?\})+)(?:(T([:*=.,\d]+)?)([A-Z]+(\?.+)?|[-+][:\d]+)?)?\z/
98
+ d, v, t, time, clock = $~[1..5]
99
+ d, r = _split_residue(d, options[:abbr]) if d =~ /\{/
100
+ if d =~ /[\(\)]/
101
+ d = When::CalendarTypes::Yerm.parse(d, options[:abbr])
102
+ options[:frame] ||= 'Yerm'
103
+ end
104
+ format, date = Date._to_array_extended_ISO8601(d, options)
105
+
106
+ # extended date & time format (JIS X0301)
107
+ when /\A((.+::)?(\[[^\]]+\]|[^-+\d{]+))(([-+*&%@!>=<?\dW.\(\)]|\{.+?\})+)?(?:(T([:*=.,\d]+)?)([A-Z]+(\?.+)?|[-+][:\d]+)?)?\z/
108
+ era, parent, child, d, v, t, time, clock = $~[1..8]
109
+ d0 = d
110
+ d, r = _split_residue(d, options[:abbr]) if d =~ /\{/
111
+ format, date, era = Date._to_array_extended_X0301(d, era, options)
112
+ era ||= options[:era_name] if d =~ /\./
113
+
114
+ # extended time format (ISO 8601)
115
+ when /\A(T(-{0,2}[:*=.,\d]+)?)([A-Z]+(\?.+)?|[-+][:\d]+)?\z/
116
+ t, time, clock = $~[1..3]
117
+
118
+ # not supported
119
+ else
120
+ raise ArgumentError, "Wrong date format: #{date_time}"
121
+ end
122
+
123
+ return [format, date, Time._to_array_extended(time, t, options),
124
+ Time._to_string_clock(clock), era, r]
125
+ end
126
+
127
+ # 剰余類の指定を置き換える
128
+ def _split_residue(d, abbr)
129
+ abbr, = abbr
130
+ residue = {}
131
+ count = 0
132
+ sign, d = d =~ /^-/ ? ['-', d[1..-1]] : ['', d]
133
+ [sign + d.gsub(/[-+*&%@!>=<?.]|(\d)?\{(.+?)\}/) {|s|
134
+ if $2
135
+ residue[count] = $2
136
+ count == 0 ? ($1 || abbr || 1) : $1
137
+ else
138
+ count += 1
139
+ s
140
+ end
141
+ }, residue]
142
+ end
143
+ end
144
+ end
145
+
146
+ #
147
+ # ISO 8601 Date Representation
148
+ #
149
+ # see {xml schema}[link:http://www.w3.org/2001/XMLSchema-datatypes#date]
150
+ #
151
+ class Date < DateTime
152
+
153
+ # @private
154
+ Extra_Year_Digits = Hash.new {|hash, key|
155
+ ex = (key || 1).to_i
156
+ hash[key] =
157
+ if ex > 0
158
+ [
159
+ /\A(\d{2})\z/,
160
+ /\A([-+]\d{#{4+ex}})(\d{2})(\d{2})\z/,
161
+ /\A([-+]\d{#{4+ex}})-(\d{2})\z/,
162
+ /\A([-+]\d{#{4+ex}})\z/,
163
+ /\A([-+]\d{#{4+ex}})W(\d{2})(\d{1})?\z/,
164
+ /\A([+]\d{#{2+ex}})\z/,
165
+ /\A([-]\d{#{2+ex}})\z/,
166
+ /\A([-+]\d{#{4+ex}})(\d{3})\z/
167
+ ]
168
+ elsif ex == 0
169
+ [/\A(\d{2})\z/] + [/\A(\d{4})\z/] * 6
170
+ else
171
+ [/\A(\d{4})\z/] * 7
172
+ end
173
+ }
174
+
175
+ # @private
176
+ Ordinal_Date_Digits = Hash.new {|hash, key|
177
+ hash[key] = /\A(\d{#{(key || 3).to_i}})\z/
178
+ }
179
+
180
+ class << self
181
+ # ISO 8601 基本形式の表現を分解して配列化する
182
+ def _to_array_basic_ISO8601(date, options={})
183
+ by, bm, bd = options[:abbr]
184
+ extra_reg = Extra_Year_Digits[options[:extra_year_digits]]
185
+ case date
186
+ when nil ; return nil
187
+ when /\A(\d{4})(\d{2})(\d{2})\z/ ; return nil, [$1.to_i, $2.to_i, $3.to_i] # 5.2.1.1
188
+ when /\A(\d{4})-(\d{2})\z/ ; return nil, [$1.to_i, $2.to_i] # 5.2.1.2
189
+ when /\A(\d{4})\z/ ; return nil, [$1.to_i] # 5.2.1.2
190
+ when extra_reg[0] ; return :century,[$1.to_i * 100] # 5.2.1.2
191
+ when /\A(\d{4})(\d{3})\z/ ; return :day, [$1.to_i, $2.to_i] # 5.2.2.1
192
+ when /\A(\d{4})W(\d{2})(\d{1})?\z/ ; return :week, [$1.to_i, $2.to_i, _int($3)] # 5.2.3.1-2
193
+ when extra_reg[1] ; return nil, [$1.to_i, $2.to_i, $3.to_i] # 5.2.1.4 a)
194
+ when extra_reg[2] ; return nil, [$1.to_i, $2.to_i] # 5.2.1.4 b)
195
+ when extra_reg[3] ; return nil, [$1.to_i] # 5.2.1.4 c)
196
+ when extra_reg[4] ; return :week, [$1.to_i, $2.to_i, _int($3)] # 5.2.3.4 a-b)
197
+ when extra_reg[5] ; return :century,[$1.to_i * 100] # 5.2.1.4 d)
198
+ when extra_reg[6] ; return :century,[$1.to_i * 100] unless by # 5.2.1.4 d)
199
+ when extra_reg[7] ; return :day, [$1.to_i, $2.to_i] # 5.2.2.3 a)
200
+ else ; raise ArgumentError, "Wrong date format" unless by
201
+ end
202
+
203
+ by = by.to_i
204
+ case date
205
+ when /\A(\d{2})(\d{2})(\d{2})\z/ ; return nil, [_century($1,by), $2.to_i, $3.to_i] # 5.2.1.3 a)
206
+ when /\A-(\d{2})(\d{2})?\z/ ; return nil, [_century($1,by), _int($2)] # 5.2.1.3 b-c)
207
+ when /\A--(\d{2})(\d{2})?\z/ ; return nil, [by, $1.to_i, _int($2)] # 5.2.1.3 d-e)
208
+ when /\A(\d{2})(\d{3})\z/ ; return :day, [_century($1,by), $2.to_i] # 5.2.2.2 a)
209
+ when /\A-(\d{3})\z/ ; return :day, [by, $1.to_i] # 5.2.2.2 b)
210
+ when /\A(\d{2})W(\d{2})(\d{1})?\z/ ; return :week, [_century($1,by), $2.to_i, _int($3)] # 5.2.3.3 a-b)
211
+ when /\A-(\d{1})W(\d{2})(\d{1})?\z/ ; return :week, [_decade($1,by), $2.to_i, _int($3)] # 5.2.3.3 c-d)
212
+ when /\A-W(\d{2})(\d{1})?\z/ ; return :week, [by, $1.to_i, _int($2)] # 5.2.3.3 e-f)
213
+ else ; raise ArgumentError, "Wrong date format" unless bm
214
+ end
215
+
216
+ bm = bm.to_i
217
+ case date
218
+ when /\A---(\d{2})\z/ ; return nil, [by, bm, $1.to_i] # 5.2.1.3 f)
219
+ when /\A-W-(\d{1})\z/ ; return :week, [by, bm, $1.to_i] # 5.2.3.3 g)
220
+ when /\A----\z/ ; return nil, [by, bm, bd.to_i] if bd # extension
221
+ end
222
+
223
+ raise ArgumentError, "Wrong date format: #{date}"
224
+ end
225
+
226
+ # JIS X0301 基本形式の表現を分解して配列化する
227
+ def _to_array_basic_X0301(date, options={})
228
+ raise ArgumentError, "Wrong date format" unless date =~ /\./
229
+ date.scan(/\d+\./) do |part|
230
+ raise ArgumentError, "Wrong date format" unless part.length == 3
231
+ end
232
+ _to_array_basic_ISO8601(date.gsub(/\./, ''), {:abbr=>options[:abbr]||1})
233
+ end
234
+
235
+ # ISO 8601 拡張形式の表現を分解して配列化する
236
+ def _to_array_extended_ISO8601(date, options={})
237
+ return nil unless date
238
+ abbr = Array(options[:abbr]).dup
239
+ unless date =~ /\A([-+]?\d+#{abbr[0] ? '|-' : ''})([-*=.])?(.*)/
240
+ raise ArgumentError, "Wrong date format: #{date}"
241
+ end
242
+ date = $3
243
+ dd = [Coordinates::Pair._en_pair(_completion($1, abbr.shift), $2)]
244
+ while date =~ /\A(\d+#{abbr[0] ? '|-' : ''})([-+*&%@!>=<?.])(.+)/
245
+ date = $3
246
+ dd << Coordinates::Pair._en_pair(_completion($1, abbr.shift), $2)
247
+ end
248
+ case date
249
+ when /\AW(\d+#{abbr[0] ? '|-' : ''})([-+*&%@!>=<?.])?(\d+)?([-*=?%@])?\z/
250
+ dd << Coordinates::Pair._en_pair(_completion($1, abbr.shift), $2)
251
+ dd << Coordinates::Pair._en_pair($3, $4)
252
+ return :week, dd
253
+ when Ordinal_Date_Digits[options[:ordinal_date_digits]]
254
+ dd << $1.to_i
255
+ return :day, dd
256
+ when /\A(\d+#{abbr[0] ? '|-' : ''})([-+*&%@!>=<?.])?\z/
257
+ dd << Coordinates::Pair._en_pair(_completion($1, abbr.shift), $2)
258
+ return nil, dd
259
+ when ''
260
+ return nil, dd
261
+ else
262
+ raise ArgumentError, "Wrong date format: #{date}"
263
+ end
264
+ end
265
+
266
+ # JIS X0301 拡張形式の表現を分解して配列化する
267
+ def _to_array_extended_X0301(date, era, options={})
268
+ if (date =~ /\A([-+\d]+)\(([-+\d]+)\)(.*)\z/)
269
+ year = $2
270
+ date = $1 + $3
271
+ end
272
+ format, date = _to_array_extended_ISO8601(date, options)
273
+ if (year)
274
+ yy = year.to_i
275
+ ee = date[0] * 1
276
+ era = [era, yy-ee, yy+ee]
277
+ end
278
+ return format, date, era
279
+ end
280
+
281
+ private
282
+
283
+ def _completion(digits, base)
284
+ case digits
285
+ when nil ; return nil
286
+ when /\A\d{5}/ ; raise ArgumentError, "Wrong date format: #{digits}" if base
287
+ else ; return digits.to_i unless base
288
+ end
289
+
290
+ base = base.to_i
291
+ case digits
292
+ when '-' ; return base
293
+ when /\A-?(\d{1})\z/ ; return _decade( $1, base)
294
+ when /\A-?(\d{2})\z/ ; return _century($1, base)
295
+ else ; return digits.to_i
296
+ end
297
+ end
298
+
299
+ def _century(year, base)
300
+ quotient, remainder = base.divmod(100)
301
+ year = year.to_i
302
+ quotient += 1 if year < remainder
303
+ return quotient * 100 + year
304
+ end
305
+
306
+ def _decade(year, base)
307
+ quotient, remainder = base.divmod(10)
308
+ year = year.to_i
309
+ quotient += 1 if year < remainder
310
+ return quotient * 10 + year
311
+ end
312
+
313
+ def _int(digits)
314
+ return digits ? digits.to_i : nil
315
+ end
316
+ end
317
+ end
318
+
319
+ #
320
+ # ISO 8601 Time Representation
321
+ #
322
+ # see {xml schema}[link:http://www.w3.org/2001/XMLSchema-datatypes#time]
323
+ #
324
+ class Time < DateTime
325
+
326
+ class << self
327
+ # 基本形式の表現を分解して配列化する
328
+ def _to_array_basic(time, t, options={})
329
+ return nil unless t
330
+ return [0] unless time
331
+ time.sub!(/,/, '.')
332
+ unless (time =~ /\A(\d{2}(?:\.\d+)?|-)(\d{2}(?:\.\d+)?|-)?(\d{2}(\.\d+)?)?\z/)
333
+ raise ArgumentError, "Wrong time format: #{time}"
334
+ end
335
+ indices = options[:frame] ? When.Calendar(options[:frame]).indices : Coordinates::DefaultDateIndices
336
+ abbr = Array(options[:abbr]).dup
337
+ abbr[0..indices.length] = []
338
+ return [0, Coordinates::Pair._en_number($1=='-' ? abbr[0] : $1, nil),
339
+ Coordinates::Pair._en_number($2=='-' ? abbr[1] : $2, nil),
340
+ Coordinates::Pair._en_number($3, nil)]
341
+ end
342
+
343
+ # 拡張形式の表現を分解して配列化する
344
+ def _to_array_extended(time, t, options={})
345
+ return nil unless t
346
+ return [0] unless time
347
+ indices = options[:frame] ? When.Calendar(options[:frame]).indices : Coordinates::DefaultDateIndices
348
+ abbr = Array(options[:abbr]).dup
349
+ abbr[0..indices.length] = []
350
+ time.sub!(/,/, '.')
351
+ if time =~ /\A([:*=])(.+)/
352
+ time = $2
353
+ tt = [Coordinates::Pair._en_pair(0, $1)]
354
+ else
355
+ tt = [0]
356
+ end
357
+ while time =~ /\A(\d{2}(?:\.\d+)?|-)([:*=])(.+)/
358
+ time = $3
359
+ tt << Coordinates::Pair._en_pair($1=='-' ? abbr.shift : $1, $2)
360
+ end
361
+ case time
362
+ when /\A(\d{2}(\.\d+)?)\z/
363
+ tt << Coordinates::Pair._en_number($1, nil)
364
+ when ''
365
+ else
366
+ raise ArgumentError, "Wrong time format: #{time}"
367
+ end
368
+ return tt
369
+ end
370
+
371
+ # 時間帯の表現を正規化する
372
+ def _to_string_clock(clock)
373
+ return nil unless clock
374
+ return clock if (clock =~ /\A[A-Z]+(\?.+)?\z/)
375
+ raise ArgumentError, "Wrong clock format: #{clock}" unless clock =~ /\A([-+])(\d{2})(?::?(\d{2}))?(?::?(\d{2}))?\z/
376
+ sgn, h, m, s = $~[1..4]
377
+ zone = sgn + h + ':' + (m||'00')
378
+ zone += s if s
379
+ return zone
380
+ end
381
+ end
382
+ end
383
+
384
+ # コード
385
+ #
386
+ # 当該コードを定義している辞書, シソーラスまたは機関への参照を
387
+ # オプショナルな codeSpace 属性に保持することができる文字列
388
+ #
389
+ # see {http://schemas.opengis.net/gml/3.1.1/base/basicTypes.xsd#CodeType gml schema}
390
+ #
391
+ class Code < String
392
+
393
+ # an optional codeSpace
394
+ #
395
+ # @return [String] anyURI (Optional)
396
+ attr_accessor :code_space
397
+ alias :codeSpace :code_space
398
+ private :code_space=
399
+
400
+ # オブジェクトの生成
401
+ #
402
+ # @param [String] code Text token
403
+ # @param [String] namespace code を定義している authority の URI
404
+ #
405
+ def initialize(code, namespace=nil)
406
+ @code_space = namespace
407
+ self[0..-1] = code
408
+ end
409
+ end
410
+
411
+ #
412
+ # == 多言語対応文字列
413
+ #
414
+ # 本ライブラリで用いる諸々の用語を多言語対応で曖昧性なく管理するため
415
+ # Code の subclass として定義する
416
+ #
417
+ # == 内部変数
418
+ # === self[ 0..-1 ] : String
419
+ # インスタンスを代表する文字列
420
+ # 通常の String として振舞う場合は、この文字列として振舞う
421
+ #
422
+ # === @locale : Hash
423
+ # インスタンスがさす言葉の諸言語での表現を文字列として保持する
424
+ # locale指定('lang_country.encoding') => その locale での文字列
425
+ # locale指定の要素に省略がある場合、残った共通の要素によって文字列を特定する
426
+ # Ex. @locale = {'en'=>'March', 'ja'=>'三月'} ならば、locale
427
+ # 'en_US', 'en_GB' のいずれでもlocale での文字列は 'March'
428
+ #
429
+ # === @namespace : Hash
430
+ # インスタンスがさす言葉の意味を特定するための authority の URI を保持する
431
+ # locale指定('lang_country.encoding') => その locale での authority の URI
432
+ # locale指定の要素に省略がある場合、残った共通の要素によってURIを特定する
433
+ # Ex. @locale = {'en'=>'en:March', 'ja'=>'ja:3%E6%9C%88'} ならば、locale
434
+ # 'en_US', 'en_GB' のいずれでもlocale での authority の URI 'en:March'
435
+ # 当該用語が標準管理機関で管理されていない場合、wikipedia の当該項目の URI を用いる
436
+ #
437
+ # === @code_space : String
438
+ # 代表的な authority の URI
439
+ # @namespace[''] である
440
+ #
441
+ # see {When::Locale}, {When::Parts::Resource}
442
+ #
443
+ class M17n < Code
444
+ include When::Locale
445
+ include Parts::Resource
446
+
447
+ # @private
448
+ HashProperty = [:label, :names, :link, :access_key, :code_space]
449
+
450
+ # @private
451
+ LabelTypes = {
452
+ 'Residue' => ['Coordinates', '%s', '_co:%s%s' ],
453
+ 'Week' => ['CalendarNote', '%sWeek', '_n:%sWeek%s' ],
454
+ 'Notes' => ['CalendarNote', '%s', '_n:%s/Notes%s'],
455
+ nil => ['BasicTypes::M17n', '%s', '_m:%s%s' ]
456
+ }
457
+
458
+ class << self
459
+
460
+ #
461
+ # resource の取得
462
+ #
463
+ # @param [When::Parts::Resource, String] source
464
+ #
465
+ # @return [When::Parts::Resource]
466
+ #
467
+ # @private
468
+ def _label(source)
469
+ case source
470
+ when Parts::Resource, nil ; return source
471
+ when Parts::Resource::IRIHeader ; return Parts::Resource._instance(source)
472
+ end
473
+ iri = Parts::Resource._abbreviation_to_iri(source, LabelTypes)
474
+ iri ? Parts::Resource._instance(iri) : nil
475
+ end
476
+
477
+ #
478
+ # label の取得
479
+ #
480
+ # @param [When::Parts::Resource, String] source
481
+ #
482
+ # @return [When::BasicTypes::M17n, String]
483
+ #
484
+ def label(source)
485
+ resource = _label(source)
486
+ case resource
487
+ when nil ; return source
488
+ when M17n ; return resource
489
+ when Parts::Resource ; return resource.label
490
+ else ; return resource
491
+ end
492
+ end
493
+
494
+ #
495
+ # label の Array の取得
496
+ #
497
+ # @param [When::Parts::Resource, Array] source
498
+ #
499
+ # @return [Array]
500
+ #
501
+ def labels(source)
502
+ array =
503
+ if source.kind_of?(Array)
504
+ source
505
+ else
506
+ resource = _label(source)
507
+ return nil unless resource
508
+ resource.child
509
+ end
510
+ case array[0]
511
+ when M17n ; return array
512
+ when Parts::Resource ; return array.map {|v| v.label}
513
+ else ; return array
514
+ end
515
+ end
516
+ end
517
+
518
+ #
519
+ # 代表名
520
+ #
521
+ # @return [String]
522
+ #
523
+ attr_reader :label
524
+
525
+ #
526
+ # 名前が意味するもの自体のオブジェクト
527
+ #
528
+ # @return [When::BasicTypes::Object]
529
+ #
530
+ alias :what :parent
531
+
532
+ #
533
+ # When::BasicTypes::M17n に変換する - 何もしないで自身を返す
534
+ #
535
+ # @return [When::BasicTypes::M17n]
536
+ #
537
+ def to_m17n
538
+ self
539
+ end
540
+
541
+ #
542
+ # 内部エンコーディング文字列化
543
+ #
544
+ def to_internal_encoding
545
+ _copy({:label => When::EncodingConversion.to_internal_encoding(to_s),
546
+ :names => Hash[*(names.keys.map {|name| [name, When::EncodingConversion.to_internal_encoding(names[name])]}).flatten],
547
+ :link => link,
548
+ :access_key => access_key,
549
+ :code_space => code_space
550
+ })
551
+ end
552
+
553
+ #
554
+ # 外部エンコーディング文字列化
555
+ #
556
+ def to_external_encoding
557
+ _copy({:label => When::EncodingConversion.to_external_encoding(to_s),
558
+ :names => Hash[*(names.keys.map {|name| [name, When::EncodingConversion.to_external_encoding(names[name])]}).flatten],
559
+ :link => link,
560
+ :access_key => access_key,
561
+ :code_space => code_space
562
+ })
563
+ end
564
+
565
+ # オブジェクトの生成
566
+ #
567
+ # @overload initialize(names, namespace={}, locale=[])
568
+ # @param [Array<String>] names
569
+ #
570
+ # [String] '*locale:label=prefix:link'
571
+ # * - 存在すれば、label をインスタンスを代表する文字列とする
572
+ # locale - label に対応する locale指定(なければ、locale 引数の指定を用いる)
573
+ # label - locale 指定に対応する label
574
+ # prefix:link - その locale での authority の URI
575
+ # prefix: - namespace 引数の指定により URI に展開する
576
+ # link - なければ labelをURI encodeして用いる
577
+ #
578
+ # @param [Hash] namespace { prefix=>uri }
579
+ #
580
+ # lables, locale 引数の prefix の展開に用いる
581
+ #
582
+ # @param [Array<String>] locale
583
+ #
584
+ # [String] '*locale=prefix:link'
585
+ # * - 存在すれば、label をインスタンスを代表する文字列とする
586
+ # locale - locale指定
587
+ # prefix:link - authority URI
588
+ # prefix: - namespace 引数の指定により URI に展開する
589
+ #
590
+ # @example
591
+ # M17n.new(['3月', 'fr:Mars=http://fr.wikipedia.org/wiki/Mars_(mois)', 'March'],
592
+ # {'en_wikipedia'=>'http://en.wikipedia.org/wiki/',
593
+ # 'ja_wikipedia'=>'http://ja.wikipedia.org/wiki/'},
594
+ # ['=ja_wikipedia:', '*en=en_wikipedia:']) を行うと、生成された M17n では、
595
+ # @names = {'' =>'3', 'fr'=>'Mars', 'en'=>'March'}
596
+ # @namespace = {'' =>'http://ja.wikipedia.org/wiki/3%E6%9C%88',
597
+ # 'fr'=>'http://fr.wikipedia.org/wiki/Mars_(mois)',
598
+ # 'en'=>'http://en.wikipedia.org/wiki/March'}
599
+ # となり、通常の String として振舞う場合は 'March' として振舞う
600
+ #
601
+ def initialize(*args)
602
+ rest, options = _attributes(args)
603
+ _sequence
604
+
605
+ return _pool[@label.to_s] ?
606
+ _copy_all(_pool[@label.to_s]) : # 階層になった Resource の代表ラベルのための生成
607
+ _copy(options) if @label # M17n#to_h の出力と書式互換の入力による生成
608
+
609
+ case rest[0]
610
+ when When::Parts::Resource::ContentLine
611
+ content, namespace = rest
612
+ namespace ||= {}
613
+ names = []
614
+ locale = []
615
+ begin
616
+ loc = content.attribute['language'].object
617
+ locale << [nil, loc, namespace[loc]]
618
+ name = content.object
619
+ ref = content.attribute['reference'] || content.attribute['url']
620
+ name += '=' + (/\ANUL\z/i =~ ref.object ? '' : ref.object) if ref
621
+ names << name
622
+ end while (content = content.same_altid)
623
+ @names ||= names.reverse
624
+ @namespace ||= namespace if namespace.kind_of?(Hash)
625
+ @locale ||= locale.reverse
626
+ when nil ;
627
+ else
628
+ names, namespace, locale = rest
629
+ @names = names if names
630
+ @namespace ||= When::Locale._namespace(namespace) if namespace
631
+ @locale ||= When::Locale._locale(locale) if locale
632
+ end
633
+ @namespace ||= {}
634
+ @locale ||= []
635
+
636
+ @code_space = @namespace['']
637
+ self[0..-1] = @label = _names(@names, @namespace, @locale)
638
+ end
639
+ end
640
+
641
+ #
642
+ # Abstract class for instance having permanent life with IRI
643
+ #
644
+ # see {When::Parts::Resource}
645
+ # see {http://schemas.opengis.net/gml/3.1.1/base/basicTypes.xsd#ObjectType gml schema}
646
+ #
647
+ class Object
648
+
649
+ include Parts::Resource
650
+
651
+ # 名前
652
+ #
653
+ # @return [String, When::BasicTypes::M17n]
654
+ #
655
+ attr_reader :label
656
+
657
+ private
658
+
659
+ # オブジェクトの初期化
660
+ def initialize(*args)
661
+ @_lock_ = Mutex.new if When.multi_thread
662
+ _normalize(*_attributes(args))
663
+ _sequence
664
+ end
665
+ end
666
+ end
667
+
668
+ #
669
+ # RS::Identifier を提供する
670
+ #
671
+ module RS
672
+
673
+ # 参照系の識別子
674
+ #
675
+ # see {http://schemas.opengis.net/gml/3.1.1/base/referenceSystems.xsd#IdentifierType gml schema}
676
+ #
677
+ class Identifier
678
+
679
+ # The code or name for this Identifier
680
+ #
681
+ # @return [When::BasicTypes::Code]
682
+ #
683
+ attr_reader :name
684
+
685
+ # Identifier of the version of the associated codeSpace or code
686
+ #
687
+ # @return [Array<String>]
688
+ #
689
+ attr_reader :version
690
+
691
+ # Remarks about this code or alias
692
+ #
693
+ # @return [Array<String>] String は URI/IRI文字列の場合あり
694
+ #
695
+ attr_reader :remarks
696
+
697
+ # オブジェクトの生成
698
+ #
699
+ # @param [When::BasicTypes::Code] name
700
+ # @param [Array<String>] version
701
+ # @param [Array<String>] remarks String は URI/IRI文字列の場合あり
702
+ #
703
+ def initialize(name, version=nil, remarks=nil)
704
+ @name = name
705
+ @version = version
706
+ @remarks = remarks
707
+ end
708
+
709
+ # その他のメソッド
710
+ #
711
+ # @note When::RS::Identifier で定義されていないメソッドは
712
+ # 処理を @name (type: When::BasicTypes::Code) に委譲する
713
+ #
714
+ def method_missing(name, *args, &block)
715
+ self.class.module_eval %Q{
716
+ def #{name}(*args, &block)
717
+ @name.send("#{name}", *args, &block)
718
+ end
719
+ } unless When::Parts::MethodCash.escape(name)
720
+ @name.send(name, *args, &block)
721
+ end
722
+ end
723
+ end
724
+
725
+ #
726
+ # EX::Extent を提供する
727
+ #
728
+ module EX
729
+
730
+ # 参照系の時間的および空間的な使用範囲を記述する
731
+ #
732
+ # 本ライブラリでは、時間的使用範囲を記述ためにのみ使用している
733
+ #
734
+ # see {http://schemas.opengis.net/gml/3.1.1/base/referenceSystems.xsd#ExtentType gml schema}
735
+ #
736
+ class Extent
737
+
738
+ # time periods
739
+ #
740
+ # 時間的使用範囲の上限と下限を示す
741
+ #
742
+ # @return [When::TM::Period]
743
+ #
744
+ attr_reader :temporal_extent
745
+ alias :temporalExtent :temporal_extent
746
+
747
+ # オブジェクトの生成
748
+ #
749
+ # @param [When::TM::Period] extent
750
+ #
751
+ def initialize(extent)
752
+ @temporal_extent = extent
753
+ end
754
+
755
+ # その他のメソッド
756
+ #
757
+ # @note When::EX::Extent で定義されていないメソッドは
758
+ # 処理を @temporal_extent (type: When::TM::Period) に委譲する
759
+ #
760
+ def method_missing(name, *args, &block)
761
+ self.class.module_eval %Q{
762
+ def #{name}(*args, &block)
763
+ list = args.map {|arg| arg.kind_of?(self.class) ? arg.temporal_extent : arg}
764
+ @temporal_extent.send("#{name}", *list, &block)
765
+ end
766
+ } unless When::Parts::MethodCash.escape(name)
767
+ list = args.map {|arg| arg.kind_of?(self.class) ? arg.temporal_extent : arg}
768
+ @temporal_extent.send(name, *list, &block)
769
+ end
770
+ end
771
+ end
772
+ end