when_exe 0.2.100 → 0.3.1
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/irb.rc +5 -0
- data/bin/locales.rb +2 -2
- data/bin/when.rb +16 -0
- data/bin/when.rb.config +7 -0
- data/lib/when_exe.rb +616 -14
- data/lib/when_exe/basictypes.rb +615 -0
- data/lib/when_exe/calendartypes.rb +1700 -0
- data/lib/when_exe/coordinates.rb +1936 -0
- data/lib/when_exe/core/compatibility.rb +54 -0
- data/lib/when_exe/core/duration.rb +72 -72
- data/lib/when_exe/core/extension.rb +382 -0
- data/lib/when_exe/ephemeris.rb +1845 -0
- data/lib/when_exe/googlecalendar.rb +140 -0
- data/lib/when_exe/icalendar.rb +1587 -0
- data/lib/when_exe/inspect.rb +1237 -0
- data/lib/when_exe/locales/af.rb +90 -0
- data/lib/when_exe/locales/ar.rb +145 -0
- data/lib/when_exe/locales/az.rb +90 -0
- data/lib/when_exe/locales/bg.rb +90 -0
- data/lib/when_exe/locales/bn.rb +94 -0
- data/lib/when_exe/locales/bs.rb +121 -0
- data/lib/when_exe/locales/ca.rb +92 -0
- data/lib/when_exe/locales/cs.rb +107 -0
- data/lib/when_exe/locales/cy.rb +150 -0
- data/lib/when_exe/locales/da.rb +84 -0
- data/lib/when_exe/locales/de.rb +92 -0
- data/lib/when_exe/locales/de_AT.rb +92 -0
- data/lib/when_exe/locales/de_CH.rb +92 -0
- data/lib/when_exe/locales/el.rb +93 -0
- data/lib/when_exe/locales/en.rb +88 -0
- data/lib/when_exe/locales/en_AU.rb +88 -0
- data/lib/when_exe/locales/en_CA.rb +88 -0
- data/lib/when_exe/locales/en_GB.rb +88 -0
- data/lib/when_exe/locales/en_IN.rb +88 -0
- data/lib/when_exe/locales/en_NZ.rb +88 -0
- data/lib/when_exe/locales/eo.rb +89 -0
- data/lib/when_exe/locales/es.rb +84 -0
- data/lib/when_exe/locales/es_419.rb +84 -0
- data/lib/when_exe/locales/es_AR.rb +84 -0
- data/lib/when_exe/locales/es_CL.rb +84 -0
- data/lib/when_exe/locales/es_CO.rb +84 -0
- data/lib/when_exe/locales/es_MX.rb +84 -0
- data/lib/when_exe/locales/es_PE.rb +85 -0
- data/lib/when_exe/locales/es_VE.rb +84 -0
- data/lib/when_exe/locales/et.rb +94 -0
- data/lib/when_exe/locales/eu.rb +95 -0
- data/lib/when_exe/locales/fa.rb +80 -0
- data/lib/when_exe/locales/fi.rb +89 -0
- data/lib/when_exe/locales/fr.rb +88 -0
- data/lib/when_exe/locales/fr_CA.rb +88 -0
- data/lib/when_exe/locales/fr_CH.rb +88 -0
- data/lib/when_exe/locales/gl.rb +81 -0
- data/lib/when_exe/locales/he.rb +84 -0
- data/lib/when_exe/locales/hi.rb +80 -0
- data/lib/when_exe/locales/hi_IN.rb +84 -0
- data/lib/when_exe/locales/hr.rb +128 -0
- data/lib/when_exe/locales/hu.rb +84 -0
- data/lib/when_exe/locales/id.rb +89 -0
- data/lib/when_exe/locales/is.rb +89 -0
- data/lib/when_exe/locales/it.rb +87 -0
- data/lib/when_exe/locales/it_CH.rb +87 -0
- data/lib/when_exe/locales/ja.rb +78 -0
- data/lib/when_exe/locales/kn.rb +86 -0
- data/lib/when_exe/locales/ko.rb +78 -0
- data/lib/when_exe/locales/links.rb +2342 -0
- data/lib/when_exe/locales/lo.rb +123 -0
- data/lib/when_exe/locales/locales.rb +91 -0
- data/lib/when_exe/locales/lt.rb +111 -0
- data/lib/when_exe/locales/lv.rb +118 -0
- data/lib/when_exe/locales/mk.rb +93 -0
- data/lib/when_exe/locales/mn.rb +80 -0
- data/lib/when_exe/locales/nb.rb +81 -0
- data/lib/when_exe/locales/ne.rb +81 -0
- data/lib/when_exe/locales/nl.rb +92 -0
- data/lib/when_exe/locales/nn.rb +73 -0
- data/lib/when_exe/locales/or.rb +84 -0
- data/lib/when_exe/locales/pl.rb +128 -0
- data/lib/when_exe/locales/pt.rb +88 -0
- data/lib/when_exe/locales/pt_BR.rb +88 -0
- data/lib/when_exe/locales/rm.rb +143 -0
- data/lib/when_exe/locales/ro.rb +105 -0
- data/lib/when_exe/locales/ru.rb +128 -0
- data/lib/when_exe/locales/sk.rb +109 -0
- data/lib/when_exe/locales/sl.rb +122 -0
- data/lib/when_exe/locales/sr.rb +122 -0
- data/lib/when_exe/locales/sv.rb +83 -0
- data/lib/when_exe/locales/sw.rb +89 -0
- data/lib/when_exe/locales/th.rb +78 -0
- data/lib/when_exe/locales/tl.rb +99 -0
- data/lib/when_exe/locales/tr.rb +96 -0
- data/lib/when_exe/locales/uk.rb +128 -0
- data/lib/when_exe/locales/uz.rb +128 -0
- data/lib/when_exe/locales/vi.rb +94 -0
- data/lib/when_exe/locales/wo.rb +82 -0
- data/lib/when_exe/locales/zh_CN.rb +77 -0
- data/lib/when_exe/locales/zh_HK.rb +77 -0
- data/lib/when_exe/locales/zh_TW.rb +77 -0
- data/lib/when_exe/mini_application.rb +252 -0
- data/lib/when_exe/parts/enumerator.rb +472 -0
- data/lib/when_exe/parts/geometric_complex.rb +379 -0
- data/lib/when_exe/parts/locale.rb +513 -0
- data/lib/when_exe/parts/method_cash.rb +207 -0
- data/lib/when_exe/parts/resource.rb +806 -0
- data/lib/when_exe/parts/timezone.rb +182 -0
- data/lib/when_exe/region/bahai.rb +145 -0
- data/lib/when_exe/region/balinese.rb +627 -0
- data/lib/when_exe/region/chinese.rb +896 -0
- data/lib/when_exe/region/chinese_calendar.rb +919 -0
- data/lib/when_exe/region/chinese_epoch.rb +1245 -0
- data/lib/when_exe/region/christian.rb +644 -0
- data/lib/when_exe/region/far_east.rb +192 -0
- data/lib/when_exe/region/french.rb +66 -0
- data/lib/when_exe/region/geologicalage.rb +639 -0
- data/lib/when_exe/region/indian.rb +1066 -0
- data/lib/when_exe/region/iranian.rb +66 -0
- data/lib/when_exe/region/islamic.rb +105 -0
- data/lib/when_exe/region/japanese.rb +851 -0
- data/lib/when_exe/region/japanese_notes.rb +964 -0
- data/lib/when_exe/region/japanese_residues.rb +1149 -0
- data/lib/when_exe/region/javanese.rb +228 -0
- data/lib/when_exe/region/jewish.rb +127 -0
- data/lib/when_exe/region/korean.rb +267 -0
- data/lib/when_exe/region/m17n.rb +115 -0
- data/lib/when_exe/region/martian.rb +215 -0
- data/lib/when_exe/region/mayan.rb +122 -0
- data/lib/when_exe/region/moon.rb +333 -0
- data/lib/when_exe/region/nihon_shoki.rb +73 -0
- data/lib/when_exe/region/planets.rb +585 -0
- data/lib/when_exe/region/pope.rb +298 -0
- data/lib/when_exe/region/residue.rb +229 -0
- data/lib/when_exe/region/roman.rb +325 -0
- data/lib/when_exe/region/ryukyu.rb +98 -0
- data/lib/when_exe/region/shire.rb +254 -0
- data/lib/when_exe/region/sun.rb +210 -0
- data/lib/when_exe/region/thai.rb +227 -0
- data/lib/when_exe/region/tibetan.rb +233 -0
- data/lib/when_exe/region/v50.rb +111 -0
- data/lib/when_exe/region/vietnamese.rb +173 -0
- data/lib/when_exe/region/world.rb +197 -0
- data/lib/when_exe/timestandard.rb +547 -0
- data/lib/when_exe/tmduration.rb +330 -330
- data/lib/when_exe/tmobjects.rb +1295 -0
- data/lib/when_exe/tmposition.rb +1955 -0
- data/lib/when_exe/tmreference.rb +1547 -0
- data/lib/when_exe/version.rb +10 -3
- data/link_to_online_documents +4 -0
- data/test/examples/JapanHolidays.ics +456 -0
- data/test/examples/Millennium.ics +17 -0
- data/test/examples/NewYork.ics +61 -0
- data/test/examples/Residue.m17n +135 -0
- data/test/examples/Spatial.m17n +179 -0
- data/test/examples/Terms.m17n +39 -0
- data/test/examples/Test.ics +53 -0
- data/test/examples/USA-DST.ics +61 -0
- data/test/examples/geometric_complex.rb +41 -0
- data/test/examples/sample.xml +14 -0
- data/test/examples/today.rb +61 -0
- data/test/test.rb +54 -19
- data/test/test.rb.config +1 -0
- data/test/test/basictypes.rb +368 -0
- data/test/test/calendartypes.rb +57 -0
- data/test/test/coordinates.rb +380 -0
- data/test/test/ephemeris.rb +127 -0
- data/test/test/googlecalendar.rb +167 -0
- data/test/test/icalendar.rb +848 -0
- data/test/test/inspect.rb +115 -0
- data/test/test/parts.rb +480 -0
- data/test/test/region/chinese.rb +161 -0
- data/test/test/region/french.rb +33 -0
- data/test/test/region/geologicalage.rb +14 -0
- data/test/test/region/indian.rb +55 -0
- data/test/test/region/iran.rb +54 -0
- data/test/test/region/islamic.rb +18 -0
- data/test/test/region/japanese.rb +62 -0
- data/test/test/region/jewish.rb +61 -0
- data/test/test/region/m17n.rb +181 -0
- data/test/test/region/mayan.rb +78 -0
- data/test/test/region/moon.rb +14 -0
- data/test/test/region/planets.rb +14 -0
- data/test/test/region/residue.rb +123 -0
- data/test/test/region/sun.rb +14 -0
- data/test/test/region/thai.rb +94 -0
- data/test/test/region/tibetan.rb +30 -0
- data/test/test/tmobjects.rb +356 -57
- data/test/test/tmposition.rb +237 -0
- data/test/test/tmreference.rb +95 -0
- data/when_exe.gemspec +2 -2
- metadata +187 -7
- data/doc/COPYING +0 -31
- data/doc/COPYING.ja +0 -25
- data/doc/document_url +0 -1
@@ -0,0 +1,1547 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
=begin
|
3
|
+
Copyright (C) 2011-2013 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
|
+
#
|
9
|
+
# ISO 19108 Geographic information - Temporal schema
|
10
|
+
#
|
11
|
+
module When::TM
|
12
|
+
#
|
13
|
+
# (5.3) Temporal Reference System Package
|
14
|
+
#
|
15
|
+
|
16
|
+
# 時間参照系
|
17
|
+
#
|
18
|
+
# see {http://schemas.opengis.net/gml/3.1.1/base/temporalReferenceSystems.xsd#AbstractTimeReferenceSystemType gml schema}
|
19
|
+
#
|
20
|
+
class ReferenceSystem < When::TM::Object
|
21
|
+
|
22
|
+
# この時間参照系が使用する空間と時間の制限(実装は時間のみ)
|
23
|
+
#
|
24
|
+
# Limits of space and time within which the temporal reference system is use
|
25
|
+
#
|
26
|
+
# @return [When::EX::Extent]
|
27
|
+
#
|
28
|
+
# @note
|
29
|
+
# マルチスレッド動作時 CalendarEra の生成で Calendar の本属性が更新される
|
30
|
+
# 参照・更新処理は synchronize { ... } の ... の部分に書く必要がある
|
31
|
+
#
|
32
|
+
attr_accessor :domain_of_validity
|
33
|
+
alias :domainOfValidity :domain_of_validity
|
34
|
+
|
35
|
+
# この時間参照系と関連付けられた時間位置 (relation - Reference)
|
36
|
+
#
|
37
|
+
# The temporal position associated with the time reference system being described
|
38
|
+
#
|
39
|
+
# @return [Array<When::TM::(Temporal)Position>]
|
40
|
+
#
|
41
|
+
attr_reader :position
|
42
|
+
|
43
|
+
# この時間参照系が使用する時間の範囲
|
44
|
+
#
|
45
|
+
# Range of time within which the temporal reference system is use
|
46
|
+
#
|
47
|
+
# @return [When::Parts::GeomerticComplex]
|
48
|
+
#
|
49
|
+
# @note
|
50
|
+
# マルチスレッド動作時 CalendarEra の生成で Calendar の本属性が更新される
|
51
|
+
# 参照・更新処理は synchronize { ... } の ... の部分に書く必要がある
|
52
|
+
#
|
53
|
+
def domain
|
54
|
+
@domain ||= When::Parts::GeometricComplex.new([])
|
55
|
+
end
|
56
|
+
attr_writer :domain
|
57
|
+
|
58
|
+
# 時間参照系を識別する名称
|
59
|
+
#
|
60
|
+
# Name by which the temporal reference system is known
|
61
|
+
#
|
62
|
+
# @return [When::RS::Identifier]
|
63
|
+
#
|
64
|
+
def name
|
65
|
+
@name ||= When::RS::Identifier.new(label, @version, @remark)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# 順序時間参照系
|
70
|
+
#
|
71
|
+
# see {http://schemas.opengis.net/gml/3.1.1/base/temporalReferenceSystems.xsd#TimeOrdinalReferenceSystemType gml schema}
|
72
|
+
#
|
73
|
+
class OrdinalReferenceSystem < ReferenceSystem
|
74
|
+
|
75
|
+
# この順序時間参照系の最上位レベルを構成する順序年代 (relation - Structure)
|
76
|
+
#
|
77
|
+
# Ordinal eras that make up the highest level of this ordinal reference system
|
78
|
+
#
|
79
|
+
# @return [Array<When::TM::OrdinalEra>]
|
80
|
+
#
|
81
|
+
alias :component :child
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
# 暦
|
86
|
+
#
|
87
|
+
# see {http://schemas.opengis.net/gml/3.1.1/base/temporalReferenceSystems.xsd#TimeCalendarType gml schema}
|
88
|
+
#
|
89
|
+
class Calendar < ReferenceSystem
|
90
|
+
|
91
|
+
include When::Coordinates
|
92
|
+
include Temporal
|
93
|
+
|
94
|
+
# 初期化
|
95
|
+
#
|
96
|
+
# @return [void]
|
97
|
+
#
|
98
|
+
def self._setup_
|
99
|
+
@_lock_ = Mutex.new if When.multi_thread
|
100
|
+
@_lock_.lock if @_lock_
|
101
|
+
@_pool = {}
|
102
|
+
@_lock_.unlock if @_lock_
|
103
|
+
end
|
104
|
+
|
105
|
+
# この暦と関連付けられた暦年代 (relation - Basis)
|
106
|
+
#
|
107
|
+
# The calendar eras associated with the calendar being described
|
108
|
+
#
|
109
|
+
# @return [Array<When::TM::CalendarEra>]
|
110
|
+
#
|
111
|
+
# @note
|
112
|
+
# マルチスレッド動作時 CalendarEra の生成で 本属性が更新される
|
113
|
+
# 参照・更新処理は synchronize { ... } の ... の部分に書く必要がある
|
114
|
+
#
|
115
|
+
attr_reader :reference_frame
|
116
|
+
alias :referenceFrame :reference_frame
|
117
|
+
|
118
|
+
# 一暦日の中の時間位置を定めるために、この暦とともに使用する時計 (relation - Resolution)
|
119
|
+
#
|
120
|
+
# The clock that is used with this calendar to define
|
121
|
+
# temporal position within a calendar day
|
122
|
+
#
|
123
|
+
# @return [Array<When::TM::Clock>]
|
124
|
+
#
|
125
|
+
attr_reader :time_basis
|
126
|
+
alias :timeBasis :time_basis
|
127
|
+
|
128
|
+
# 時刻制 - additional attribute
|
129
|
+
#
|
130
|
+
# @return [When::TimeStandard, nil]
|
131
|
+
#
|
132
|
+
def time_standard
|
133
|
+
@time_basis ? @time_basis.time_standard : nil
|
134
|
+
end
|
135
|
+
|
136
|
+
# 時間の歩度
|
137
|
+
#
|
138
|
+
# @return [Numeric]
|
139
|
+
#
|
140
|
+
def rate_of_clock
|
141
|
+
@time_basis ? @time_basis.time_standard.rate_of_clock : 1.0
|
142
|
+
end
|
143
|
+
|
144
|
+
# 日付と時刻をユリウス日(When::TM::JulianDate)に変換する
|
145
|
+
#
|
146
|
+
# @param [When::TM::CalDate] cal_date
|
147
|
+
# @param [When::TM::ClockTime] time
|
148
|
+
#
|
149
|
+
# @return [When::TM::JulianDate]
|
150
|
+
#
|
151
|
+
def date_trans(cal_date, time=nil, options={})
|
152
|
+
time = cal_date.clk_time if ((time == nil) && cal_date.kind_of?(DateAndTime))
|
153
|
+
frac = (time) ? time.universal_time : 0.0
|
154
|
+
jdn = to_julian_date(cal_date.cal_date)
|
155
|
+
return JulianDate.universal_time((jdn - JulianDate::JD19700101) * Duration::DAY + frac, options)
|
156
|
+
end
|
157
|
+
alias :dateTrans :date_trans
|
158
|
+
|
159
|
+
# ユリウス日(When::TM::JulianDate)を日付に変換する
|
160
|
+
#
|
161
|
+
# @param [When::TM::JulianDate] jdt
|
162
|
+
# @param [Hash] options see {When::TM::TemporalPosition._instance}
|
163
|
+
#
|
164
|
+
# @return [When::TM::CalDate] if (options[:clock or :tz] == nil)
|
165
|
+
# @return [When::TM::CalDateAndTime] if (options[:clock or :tz] != nil)
|
166
|
+
#
|
167
|
+
def jul_trans(jdt, options={})
|
168
|
+
unless jdt.kind_of?(When::TimeValue)
|
169
|
+
options[:clock] ||= @time_basis unless rate_of_clock == 1.0
|
170
|
+
jdt = JulianDate.new(jdt, options)
|
171
|
+
end
|
172
|
+
cal_options = jdt._attr
|
173
|
+
cal_options.delete(:era_name)
|
174
|
+
cal_options.delete(:era)
|
175
|
+
unless rate_of_clock == jdt.rate_of_clock
|
176
|
+
cal_options.delete(:time_standard)
|
177
|
+
cal_options[:clock] = @time_basis || When.utc
|
178
|
+
jdt = JulianDate.dynamical_time(jdt.dynamical_time, {:time_standard=>time_standard})
|
179
|
+
end
|
180
|
+
cal_options.update(options)
|
181
|
+
cal_options[:frame] = self
|
182
|
+
cal_date = to_cal_date(jdt.to_i)
|
183
|
+
cal_date[0] -= cal_options[:era_name][1] if cal_options[:era_name]
|
184
|
+
clock = @time_basis || Clock.get_clock_option(cal_options) || jdt.clock
|
185
|
+
return CalDate.new(cal_date, cal_options) unless clock
|
186
|
+
clock = When.Clock(clock) if clock.kind_of?(String)
|
187
|
+
clock = clock._daylight(jdt) if clock._need_validate
|
188
|
+
frac = clock.universal_time
|
189
|
+
sdn, time = (jdt.universal_time - frac).divmod(Duration::DAY)
|
190
|
+
cal_options[:clock] = clock
|
191
|
+
return DateAndTime.new(to_cal_date(sdn.to_i + JulianDate::JD19700101), time+frac, cal_options)
|
192
|
+
end
|
193
|
+
alias :julTrans :jul_trans
|
194
|
+
alias :^ :jul_trans
|
195
|
+
|
196
|
+
# 日付をユリウス日(Numeric)に変換する
|
197
|
+
#
|
198
|
+
# @param [Numeric] cal_date
|
199
|
+
#
|
200
|
+
# @return [Integer] JulianDate
|
201
|
+
#
|
202
|
+
def to_julian_date(cal_date)
|
203
|
+
date = _decode(cal_date)
|
204
|
+
date[0] = +date[0]
|
205
|
+
return _coordinates_to_number(*date)
|
206
|
+
end
|
207
|
+
|
208
|
+
# ユリウス日(Numeric)を日付に変換する
|
209
|
+
#
|
210
|
+
# @param [Integer] jdn
|
211
|
+
#
|
212
|
+
# @return [Numeric]
|
213
|
+
#
|
214
|
+
def to_cal_date(jdn)
|
215
|
+
return _encode(_number_to_coordinates(jdn))
|
216
|
+
end
|
217
|
+
|
218
|
+
# 月初の通日
|
219
|
+
#
|
220
|
+
# @param [Integer] m 通月
|
221
|
+
#
|
222
|
+
# @return [Numeric] 月初の通日
|
223
|
+
#
|
224
|
+
def _new_month_(m)
|
225
|
+
date = @base.map {|d| d||0}
|
226
|
+
if @indices[-2].unit
|
227
|
+
date[-2] += m
|
228
|
+
_coordinates_to_number(*_decode(date))
|
229
|
+
else
|
230
|
+
d0 = _coordinates_to_number(*_decode(date))
|
231
|
+
date[-3] += (m * @mean_month / @mean_year).floor - 1
|
232
|
+
d1 = _coordinates_to_number(*_decode(date))
|
233
|
+
date[-2] += m - ((d1 - d0) / @mean_month + 0.5).floor
|
234
|
+
_coordinates_to_number(*_decode(date))
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
# 通日 - > [通月,月内日数,月の日数]
|
239
|
+
#
|
240
|
+
# @param [Integer] sdn 通日
|
241
|
+
#
|
242
|
+
# @return [Array<Numeric>] ( m, d, n )
|
243
|
+
# [ m - 通月]
|
244
|
+
# [ d - 月内の日数 (0 始まり)]
|
245
|
+
# [ n - 月の日数]
|
246
|
+
#
|
247
|
+
def _to_month_number_(sdn)
|
248
|
+
Residue.mod(sdn) {|m| _new_month(m)}
|
249
|
+
end
|
250
|
+
|
251
|
+
private
|
252
|
+
|
253
|
+
# オブジェクトの正規化
|
254
|
+
def _normalize(args=[], options={})
|
255
|
+
@time_basis = When.Calendar(@time_basis) if @time_basis.kind_of?(String)
|
256
|
+
@indices ||= DefaultDateIndex
|
257
|
+
_normalize_temporal
|
258
|
+
@reference_frame ||= []
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
# 時計
|
263
|
+
#
|
264
|
+
# see {http://schemas.opengis.net/gml/3.1.1/base/temporalReferenceSystems.xsd#TimeClockType gml schema}
|
265
|
+
#
|
266
|
+
class Clock < ReferenceSystem
|
267
|
+
|
268
|
+
include When::Coordinates
|
269
|
+
include Temporal
|
270
|
+
|
271
|
+
class << self
|
272
|
+
include When::Parts::Resource::Pool
|
273
|
+
|
274
|
+
# 地方時
|
275
|
+
#
|
276
|
+
# @return [When::TM::Clock, When::Parts::Timezone, When::V::Timezone]
|
277
|
+
#
|
278
|
+
# @note
|
279
|
+
# 本変数の write access はテスト用である。
|
280
|
+
# 本変数は、原則、ライブラリ立ち上げ時に _setup_ で初期化する。
|
281
|
+
# 以降、本変数に代入を行っても、すでに生成した When::TM::TemporalPosition には反映されない。
|
282
|
+
#
|
283
|
+
# @note
|
284
|
+
# マルチスレッド動作時 CalendarEra の生成で Calendar の本属性が更新される
|
285
|
+
# 参照・更新処理は Clock.synchronize { ... } の ... の部分に書く必要がある
|
286
|
+
#
|
287
|
+
attr_accessor :local_time
|
288
|
+
|
289
|
+
# When::TM::Clock Class のグローバルな設定を行う
|
290
|
+
#
|
291
|
+
# @param [When::TM::Clock, When::Parts::Timezone, When::V::Timezone] local 地方時を使用する場合、指定する
|
292
|
+
#
|
293
|
+
# @return [void]
|
294
|
+
#
|
295
|
+
def _setup_(local=nil)
|
296
|
+
@_lock_ = Mutex.new if When.multi_thread
|
297
|
+
@_lock_.lock if @_lock_
|
298
|
+
@_pool = {}
|
299
|
+
@local_time = local
|
300
|
+
@_lock_.unlock if @_lock_
|
301
|
+
end
|
302
|
+
|
303
|
+
# @private
|
304
|
+
def get_clock(options)
|
305
|
+
get_clock_option(options) || @local_time || When.utc
|
306
|
+
end
|
307
|
+
|
308
|
+
# @private
|
309
|
+
def get_clock_option(options)
|
310
|
+
clock = options.delete(:clock)
|
311
|
+
tz = options.delete(:tz)
|
312
|
+
tz ? (When::V::Timezone[tz] || When::Parts::Timezone[tz]) : clock
|
313
|
+
end
|
314
|
+
|
315
|
+
# @private
|
316
|
+
def to_hms(hms, extended=true)
|
317
|
+
case hms
|
318
|
+
when Numeric
|
319
|
+
sgn = (hms >= 0) ? '+' : '-'
|
320
|
+
hh, mm = hms.abs.divmod(3600)
|
321
|
+
mm, ss = mm.divmod(60)
|
322
|
+
ss, ff = ss.divmod(1)
|
323
|
+
ff = (ff == 0 || When::STRING <= When::SECOND) ? '' :
|
324
|
+
("%.#{When::STRING - When::SECOND}f" % ff)[1..-1]
|
325
|
+
ss = (ss == 0 && ff == '') ? '' : ("%02d" % ss)
|
326
|
+
mm = "%02d" % mm
|
327
|
+
hh = "%02d" % hh
|
328
|
+
when /^([-+])(\d{2})([:=*])?(\d{2})?([:=*])?(\d{2})?(\.\d+)?$/
|
329
|
+
sgn, hh, d1, mm, d2, ss, ff = $~[1..7]
|
330
|
+
ff ||= ''
|
331
|
+
ss ||= ''
|
332
|
+
mm ||= ''
|
333
|
+
else
|
334
|
+
return nil
|
335
|
+
end
|
336
|
+
|
337
|
+
if (extended)
|
338
|
+
d1 ||= (mm=='') ? '' : ':'
|
339
|
+
d2 ||= (ss=='') ? '' : ':'
|
340
|
+
else
|
341
|
+
d1 = ''
|
342
|
+
d2 = ''
|
343
|
+
end
|
344
|
+
sgn + hh + d1 + mm + d2 + ss + ff
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
348
|
+
# この時法の基点となる事象
|
349
|
+
#
|
350
|
+
# Event used as the datum for this clock
|
351
|
+
#
|
352
|
+
# @return [String]
|
353
|
+
#
|
354
|
+
# @note
|
355
|
+
# new の options 引数に :reference_event があれば設定される。
|
356
|
+
# ライブラリとしては本変数を参照していない。下記の振る舞いを String で説明するため用いてもよい。
|
357
|
+
#
|
358
|
+
# @note
|
359
|
+
# 日付の境界が午前0時でない場合、When::Coordinates::Temporal.border により、境界が指定される。
|
360
|
+
# border, behavior メソッドをオーバーライドすることで、日の出、日の入りなど event 時刻が一定
|
361
|
+
# しない場合にも対応する。
|
362
|
+
#
|
363
|
+
attr_reader :reference_event
|
364
|
+
alias :referenceEvent :reference_event
|
365
|
+
|
366
|
+
# この時法による参照事象の時刻
|
367
|
+
#
|
368
|
+
# Time of the reference event for this clock
|
369
|
+
#
|
370
|
+
# @return [When::TM::ClockTime]
|
371
|
+
#
|
372
|
+
attr_reader :reference_time
|
373
|
+
alias :referenceTime :reference_time
|
374
|
+
|
375
|
+
# UTCによる参照事象の時刻
|
376
|
+
#
|
377
|
+
# UTC time of the reference event
|
378
|
+
#
|
379
|
+
# @return [When::TM::ClockTime]
|
380
|
+
#
|
381
|
+
attr_reader :utc_reference
|
382
|
+
alias :utcReference :utc_reference
|
383
|
+
|
384
|
+
# 一暦日の中の時間位置を定めるために、この時計とともに使用する暦 (relation - Resolution)
|
385
|
+
#
|
386
|
+
# The calendar that is used with this clock to define
|
387
|
+
# temporal position within a calendar day
|
388
|
+
#
|
389
|
+
# @return [Array<When::TM::Calendar>]
|
390
|
+
#
|
391
|
+
attr_reader :date_basis
|
392
|
+
alias :dateBasis :date_basis
|
393
|
+
|
394
|
+
# 時刻制 - additional attribute
|
395
|
+
#
|
396
|
+
# @return [When::TimeStandard]
|
397
|
+
#
|
398
|
+
attr_reader :time_standard
|
399
|
+
|
400
|
+
# この時法を生成した時間帯プロパティ - additional attribute
|
401
|
+
#
|
402
|
+
# @return [When::V::TimezoneProperty]
|
403
|
+
#
|
404
|
+
# @note
|
405
|
+
# When::TM::TemporalPosition に対して加減算を行うと、時間帯が変わる可能性がある。
|
406
|
+
# 本変数により、時間帯決定ルール(When::V::TimezoneProperty#rrule)を参照する。
|
407
|
+
#
|
408
|
+
attr_accessor :tz_prop
|
409
|
+
alias :tzProp :tz_prop
|
410
|
+
|
411
|
+
# universal_timeとこの時法の最小単位との比 - additional attribute
|
412
|
+
#
|
413
|
+
# @return [Numeric]
|
414
|
+
#
|
415
|
+
attr_reader :second
|
416
|
+
|
417
|
+
# この時法のUTCとの差(ISO 8601 extended format) - additional attribute
|
418
|
+
#
|
419
|
+
# @return [String] (±hh:mm)
|
420
|
+
#
|
421
|
+
attr_reader :zone
|
422
|
+
alias :to_extended :zone
|
423
|
+
|
424
|
+
# 時間の歩度
|
425
|
+
#
|
426
|
+
# @return [Numeric]
|
427
|
+
#
|
428
|
+
def rate_of_clock
|
429
|
+
@time_standard.rate_of_clock
|
430
|
+
end
|
431
|
+
|
432
|
+
# 日の小数による参照事象の時刻
|
433
|
+
#
|
434
|
+
# Fraction time of the reference event
|
435
|
+
#
|
436
|
+
# @return [Numeric]
|
437
|
+
#
|
438
|
+
# T00:00:00Z からの参照事象の経過時間 / 128秒
|
439
|
+
#
|
440
|
+
def universal_time
|
441
|
+
return @utc_reference.universal_time
|
442
|
+
end
|
443
|
+
|
444
|
+
# この時法の時刻をUTC時刻に変換する
|
445
|
+
#
|
446
|
+
# @param [When::TM::ClockTime] u_time
|
447
|
+
#
|
448
|
+
# @return [When::TM::ClockTime]
|
449
|
+
#
|
450
|
+
def utc_trans(u_time)
|
451
|
+
return When.utc.to_clk_time(self.to_universal_time(u_time.clk_time))
|
452
|
+
end
|
453
|
+
alias :utcTrans :utc_trans
|
454
|
+
|
455
|
+
# UTC時刻をこの時法の時刻に変換する
|
456
|
+
#
|
457
|
+
# @param [When::TM::ClockTime] clk_time
|
458
|
+
#
|
459
|
+
# @return [When::TM::ClockTime]
|
460
|
+
#
|
461
|
+
def clk_trans(clk_time)
|
462
|
+
return self.to_clk_time(When.utc.to_universal_time(u_time.clk_time))
|
463
|
+
end
|
464
|
+
alias :clkTrans :clk_trans
|
465
|
+
|
466
|
+
# この時法の時刻を日の小数に変換する
|
467
|
+
#
|
468
|
+
# @param [Numeric] clk_time
|
469
|
+
#
|
470
|
+
# @return [Numeric]
|
471
|
+
#
|
472
|
+
def to_universal_time(clk_time)
|
473
|
+
return _coordinates_to_number(_decode(clk_time)) / @second
|
474
|
+
end
|
475
|
+
|
476
|
+
# 日の小数をこの時法の時刻に変換する
|
477
|
+
#
|
478
|
+
# @param [Numeric] fod
|
479
|
+
#
|
480
|
+
# @return [When::TM::ClockTime]
|
481
|
+
#
|
482
|
+
def to_clk_time(fod, options={})
|
483
|
+
options[:frame] = self
|
484
|
+
fod, second = fod.trunk, fod.branch / fod.second if fod.kind_of?(When::Coordinates::LeapSeconds)
|
485
|
+
clk_time = ClockTime.new(_encode(_number_to_coordinates(fod * @second)), options)
|
486
|
+
return clk_time if (second||0) == 0
|
487
|
+
clk_time.clk_time[-1] += second
|
488
|
+
return clk_time
|
489
|
+
end
|
490
|
+
|
491
|
+
# 時刻をNumeric(serial time)に変換する
|
492
|
+
#
|
493
|
+
# @param [Numeric] clk_time
|
494
|
+
#
|
495
|
+
# @return [Numeric] serial time
|
496
|
+
#
|
497
|
+
def _coordinates_to_number(clk_time)
|
498
|
+
u = 1
|
499
|
+
s = 0
|
500
|
+
(@base.length-1).downto(1) do |i|
|
501
|
+
s += u * (+clk_time[i] - @base[i]) if (clk_time[i])
|
502
|
+
u *= @unit[i]
|
503
|
+
end
|
504
|
+
return s + u * (+clk_time[0]) + @origin_of_LSC
|
505
|
+
end
|
506
|
+
|
507
|
+
# Numeric(serial time)を時刻に変換する
|
508
|
+
#
|
509
|
+
# @param [Numeric] serial_time
|
510
|
+
#
|
511
|
+
# @return [Numeric]
|
512
|
+
#
|
513
|
+
def _number_to_coordinates(serial_time)
|
514
|
+
time = [serial_time-@origin_of_LSC]
|
515
|
+
(@base.length-1).downto(1) do |i|
|
516
|
+
carry, time[0] = (+time[0]).divmod(@unit[i])
|
517
|
+
time[0] += @base[i]
|
518
|
+
time.unshift(carry)
|
519
|
+
end
|
520
|
+
return time
|
521
|
+
end
|
522
|
+
|
523
|
+
# When::TM::TemporalPosition の時間帯を変更して複製する
|
524
|
+
#
|
525
|
+
# @param [When::TM::CalDate, When::TM::DateAndTime, When::TM::JulianDate] date
|
526
|
+
# @param [Hash] options see {When::TM::TemporalPosition._instance}
|
527
|
+
#
|
528
|
+
# @return [When::TM::DateAndTime, When::TM::JulianDate]
|
529
|
+
#
|
530
|
+
def ^(date, options={})
|
531
|
+
date = Position.any_other(date, options)
|
532
|
+
my_options = (date.options||{}).merge(options)
|
533
|
+
frac = self.universal_time
|
534
|
+
sdn, time = (date.universal_time - frac).divmod(Duration::DAY)
|
535
|
+
my_options[:frame] ||= date.frame if date.kind_of?(CalDate)
|
536
|
+
my_options[:clock] = self
|
537
|
+
case date
|
538
|
+
when DateAndTime
|
539
|
+
return DateAndTime.new(my_options[:frame].to_cal_date(sdn + JulianDate::JD19700101), time+frac, my_options)
|
540
|
+
when CalDate
|
541
|
+
return CalDate.new(my_options[:frame].to_cal_date(date.to_i), my_options)
|
542
|
+
when JulianDate
|
543
|
+
my_options[:frame] = my_options.delete(:clock)
|
544
|
+
return JulianDate.universal_time(sdn * Duration::DAY, my_options)
|
545
|
+
else
|
546
|
+
raise TypeError, "Irregal (Temporal)Position"
|
547
|
+
end
|
548
|
+
end
|
549
|
+
|
550
|
+
# この時法の時間帯名
|
551
|
+
#
|
552
|
+
# @param [Symbol] format
|
553
|
+
# - :extended ISO 8601 extended format (default)
|
554
|
+
# - :basic ISO 8601 basic format
|
555
|
+
# - :hash 時間帯名の後ろにISO 8601 extended format を付加する
|
556
|
+
#
|
557
|
+
# @return [Array<String>]
|
558
|
+
#
|
559
|
+
# @note
|
560
|
+
# :extended または :basicが指定され、上記は時間帯名が定義されていない場合は、ISO 8601形式で返す
|
561
|
+
#
|
562
|
+
def tzname(format=:extended)
|
563
|
+
name = @tz_prop.tzname if @tz_prop.kind_of?(When::V::TimezoneProperty) && format != :hash
|
564
|
+
name ||= format == :basic ? to_basic : @zone
|
565
|
+
name = Array(name)
|
566
|
+
return name unless format == :hash
|
567
|
+
tzid = case @tz_prop
|
568
|
+
when When::V::TimezoneProperty ; @tz_prop['..'].property['tzid'].object
|
569
|
+
when When::Parts::Timezone ; @tz_prop.timezone.name
|
570
|
+
else ; ''
|
571
|
+
end
|
572
|
+
name[0] = tzid + name[0]
|
573
|
+
name
|
574
|
+
end
|
575
|
+
|
576
|
+
#
|
577
|
+
# _m17n_form のための要素生成
|
578
|
+
#
|
579
|
+
# @private
|
580
|
+
def _to_hash_value(options={})
|
581
|
+
tzname(:hash)[0]
|
582
|
+
end
|
583
|
+
|
584
|
+
# この時法のUTCとの差(ISO 8601 basic format)
|
585
|
+
#
|
586
|
+
# @return [String] (±hhmm)
|
587
|
+
#
|
588
|
+
def to_basic
|
589
|
+
return '' unless @zone
|
590
|
+
@zone.gsub(/:/, '')
|
591
|
+
end
|
592
|
+
|
593
|
+
# 夏時間の有無
|
594
|
+
# @private
|
595
|
+
def _need_validate
|
596
|
+
case @tz_prop
|
597
|
+
when nil ; false
|
598
|
+
when When::V::TimezoneProperty ; @tz_prop._pool['..']._need_validate
|
599
|
+
else ; @tz_prop._need_validate
|
600
|
+
end
|
601
|
+
end
|
602
|
+
|
603
|
+
# 夏時間
|
604
|
+
# @private
|
605
|
+
def _daylight(zdate=nil, &block)
|
606
|
+
case @tz_prop
|
607
|
+
when nil ; return self
|
608
|
+
when When::V::TimezoneProperty ; timezone = @tz_prop._pool['..']
|
609
|
+
else ; timezone = @tz_prop
|
610
|
+
end
|
611
|
+
return self unless timezone
|
612
|
+
return timezone._daylight(zdate, &block)
|
613
|
+
end
|
614
|
+
|
615
|
+
# この時法の夏時間-標準時間変化量
|
616
|
+
# @private
|
617
|
+
def _tz_difference
|
618
|
+
case @tz_prop
|
619
|
+
when nil ; 0
|
620
|
+
when When::V::TimezoneProperty ; @tz_prop._pool['..'].difference
|
621
|
+
else ; @tz_prop.difference
|
622
|
+
end
|
623
|
+
end
|
624
|
+
|
625
|
+
# 期間オブジェクトの桁数合わせ
|
626
|
+
# @private
|
627
|
+
def _arrange_length(period)
|
628
|
+
return period unless period.kind_of?(Array)
|
629
|
+
diff = @indices.length - period.length + 1
|
630
|
+
return period if (diff == 0)
|
631
|
+
return (diff > 0) ? period + Array.new(diff, 0) : period[0...diff]
|
632
|
+
end
|
633
|
+
|
634
|
+
# 時刻配列の分解能
|
635
|
+
# @private
|
636
|
+
def _precision(time, default=nil)
|
637
|
+
nil_index = time.index(nil) || time.length
|
638
|
+
precision = nil_index - 1 if (nil_index < @base.length || time[-1].kind_of?(Integer))
|
639
|
+
When::Coordinates::Index.precision(default || precision)
|
640
|
+
end
|
641
|
+
|
642
|
+
private
|
643
|
+
|
644
|
+
# オブジェクトの正規化
|
645
|
+
def _normalize(args=[], options={})
|
646
|
+
@indices ||= DefaultTimeIndex
|
647
|
+
|
648
|
+
# note
|
649
|
+
@note ||= 'JulianDayNotes'
|
650
|
+
|
651
|
+
_normalize_temporal
|
652
|
+
|
653
|
+
# second
|
654
|
+
@second = (@second||128).to_f
|
655
|
+
|
656
|
+
# zone
|
657
|
+
@zone = Clock.to_hms(@zone || @label || @reference_event)
|
658
|
+
|
659
|
+
# time_standard
|
660
|
+
@time_standard = When.Resource(@time_standard||'UniversalTime', '_t:') unless @time_standard.kind_of?(When::TimeStandard)
|
661
|
+
|
662
|
+
# utc_reference
|
663
|
+
@utc_reference ||= @zone ? ClockTime.new(@zone.to_s, {:frame=>When.utc}) : (Clock.local_time || When.utc)
|
664
|
+
|
665
|
+
# reference_time & origin_of_LSC
|
666
|
+
case @reference_time
|
667
|
+
when Array ; clk_time = @reference_time
|
668
|
+
when String ; clk_time = Pair._en_pair_date_time(@reference_time)
|
669
|
+
when ClockTime ; clk_time = @reference_time.clk_time
|
670
|
+
when nil ; clk_time = [0, 0]
|
671
|
+
else ; raise TypeError, "reference_time type mismatch"
|
672
|
+
end
|
673
|
+
@origin_of_LSC -= (to_universal_time(clk_time) - @utc_reference.universal_time) * @second
|
674
|
+
@reference_time = ClockTime.new(clk_time, {:frame=>self})
|
675
|
+
end
|
676
|
+
end
|
677
|
+
|
678
|
+
# 時間座標系
|
679
|
+
#
|
680
|
+
# see {http://schemas.opengis.net/gml/3.1.1/base/temporalReferenceSystems.xsd#TimeCoordinateSystemType gml schema}
|
681
|
+
#
|
682
|
+
class CoordinateSystem < ReferenceSystem
|
683
|
+
|
684
|
+
# グレゴリオ暦の日付及びその日のUTCの時刻で表現する、座標参照系の尺度の原点位置
|
685
|
+
#
|
686
|
+
# Position of the origin of the scale on which the temporal coordinate
|
687
|
+
# system is based expressed as a date in the Gregorian calendar and
|
688
|
+
# time of day in UTC
|
689
|
+
#
|
690
|
+
# @return [When::BasicTypes::DateTime]
|
691
|
+
#
|
692
|
+
attr_reader :origin
|
693
|
+
|
694
|
+
# この参照系の軸で時間の参照単位とする間隔
|
695
|
+
#
|
696
|
+
# Standard unit of time used to measure duration
|
697
|
+
# on the axis of the coordinate system
|
698
|
+
#
|
699
|
+
# @return [When::TM::Duration] (changed from String)
|
700
|
+
#
|
701
|
+
attr_reader :interval
|
702
|
+
|
703
|
+
# この時間参照系の座標値をグレゴリオ暦及びUTC時刻に変換する
|
704
|
+
#
|
705
|
+
# @param [When::TM::Coordinate] c_value
|
706
|
+
#
|
707
|
+
# @return [When::TM::DateAndTime] (When::TM::BasicTypes::DateTimeはまちがい)
|
708
|
+
#
|
709
|
+
def transform_coord(c_value)
|
710
|
+
When.Resource('_c:Gregorian').jul_trans(JulianDate.universal_time(c_value.universal_time, {:frame=>When.utc}))
|
711
|
+
end
|
712
|
+
alias :transformCoord :transform_coord
|
713
|
+
|
714
|
+
# グレゴリオ暦及びUTC時刻をこの時間参照系の座標値に変換する
|
715
|
+
#
|
716
|
+
# @param [When::TM::DateAndTime (BasicTypes::DateTimeはまちがい)] date_time
|
717
|
+
#
|
718
|
+
# @return [When::TM::Coordinate]
|
719
|
+
#
|
720
|
+
def transform_date_time(date_time)
|
721
|
+
Coordinate.universal_time(date_time.universal_time, {:frame=>self})
|
722
|
+
end
|
723
|
+
alias :transformDateTime :transform_date_time
|
724
|
+
|
725
|
+
private
|
726
|
+
|
727
|
+
# オブジェクトの正規化
|
728
|
+
def _normalize(args=[], options={})
|
729
|
+
@origin = When.when?(@origin, options)
|
730
|
+
@interval = When.Duration(@interval)
|
731
|
+
raise TypeError, "Interval should be IntervalLength" unless @interval.kind_of?(IntervalLength)
|
732
|
+
end
|
733
|
+
end
|
734
|
+
|
735
|
+
# 順序時間参照系
|
736
|
+
#
|
737
|
+
# see {http://schemas.opengis.net/gml/3.1.1/base/temporalReferenceSystems.xsd#TimeOrdinalEraType gml schema}
|
738
|
+
#
|
739
|
+
class OrdinalEra < When::TM::Object
|
740
|
+
|
741
|
+
include Separation
|
742
|
+
|
743
|
+
# この順序年代を識別する名称
|
744
|
+
#
|
745
|
+
# Name that identifies a specific ordinal era
|
746
|
+
#
|
747
|
+
# @return [String]
|
748
|
+
#
|
749
|
+
alias :name :label
|
750
|
+
|
751
|
+
# この順序年代をさらに分割する順序年代
|
752
|
+
#
|
753
|
+
# Ordinal eras that subdivide this ordinal era
|
754
|
+
#
|
755
|
+
# @return [Array<When::TM::OrdinalEra>]
|
756
|
+
#
|
757
|
+
alias :member :child
|
758
|
+
|
759
|
+
# この順序年代が属する順序時間参照系 (relation - Structure)
|
760
|
+
#
|
761
|
+
# Ordinal reference system that contains this ordinal era
|
762
|
+
#
|
763
|
+
# @return [When::TM::OrdinalReferenceSystem, nil]
|
764
|
+
#
|
765
|
+
def system
|
766
|
+
_pool['..'].kind_of?(String) ? _pool['..'] : nil
|
767
|
+
end
|
768
|
+
|
769
|
+
# この順序年代が属する上位順序年代 (relation - Composition)
|
770
|
+
#
|
771
|
+
# Ordinal era that contains this ordinal era
|
772
|
+
#
|
773
|
+
# @return [When::TM::OrdinalEra, nil]
|
774
|
+
#
|
775
|
+
def group
|
776
|
+
_pool['..'].kind_of?(String)? nil : _pool['..']
|
777
|
+
end
|
778
|
+
|
779
|
+
# この順序年代が始まる時点
|
780
|
+
#
|
781
|
+
# Date at which the ordinal era began
|
782
|
+
#
|
783
|
+
# @return [When::BasicTypes::DateTime]
|
784
|
+
#
|
785
|
+
attr_reader :begin
|
786
|
+
|
787
|
+
# この順序年代が終わる時点
|
788
|
+
#
|
789
|
+
# Date at which the ordinal era ended
|
790
|
+
#
|
791
|
+
# @return [When::BasicTypes::DateTime]
|
792
|
+
#
|
793
|
+
def end
|
794
|
+
@end || (@_pool['.->'] ? @_pool['.->'].begin : nil)
|
795
|
+
end
|
796
|
+
|
797
|
+
# 日時が属するか?
|
798
|
+
#
|
799
|
+
# @param [When::TM::TemporalPosition] other
|
800
|
+
#
|
801
|
+
# @return [Boolean]
|
802
|
+
# [ true - 属する ]
|
803
|
+
# [ false - 属さない ]
|
804
|
+
#
|
805
|
+
def include?(other)
|
806
|
+
self.begin <= other && other < self.end
|
807
|
+
end
|
808
|
+
|
809
|
+
# When::TM::TemporalPosition ^ When::TM::OrdinalEra で呼ばれる
|
810
|
+
# @private
|
811
|
+
def ^(other)
|
812
|
+
include?(other) ? self : nil
|
813
|
+
end
|
814
|
+
|
815
|
+
private
|
816
|
+
|
817
|
+
# オブジェクトの正規化
|
818
|
+
def _normalize(args=[], options={})
|
819
|
+
# options
|
820
|
+
@options ||= {}
|
821
|
+
term_options = @options.merge({'namespace'=>@namespace, 'locale'=>@locale})
|
822
|
+
|
823
|
+
label, begun, ended = args
|
824
|
+
|
825
|
+
# label
|
826
|
+
@label = label if label
|
827
|
+
@label = m17n(@label, nil, nil, term_options) if (@label.instance_of?(String))
|
828
|
+
@label._pool['..'] ||= self
|
829
|
+
@_pool[@label.to_s] = @label
|
830
|
+
|
831
|
+
# begin
|
832
|
+
@begin = begun if begun
|
833
|
+
@begin = When.when?(@begin, @options) if @begin
|
834
|
+
@begin = @child[0].begin if !@begin && @child[0]
|
835
|
+
|
836
|
+
# end
|
837
|
+
@end = ended if ended
|
838
|
+
@end = When.when?(@end, @options) if @end
|
839
|
+
@end = @child[-1].end if !@end && @child[-1]
|
840
|
+
end
|
841
|
+
|
842
|
+
# その他のメソッド
|
843
|
+
#
|
844
|
+
# @note
|
845
|
+
# When::TM::OrdinalEra で定義されていないメソッドは
|
846
|
+
# 処理を @begin (type: When::TM::TemporalPosition) に委譲する
|
847
|
+
#
|
848
|
+
def method_missing(name, *args, &block)
|
849
|
+
@begin.send(name.to_sym, *args, &block)
|
850
|
+
end
|
851
|
+
end
|
852
|
+
|
853
|
+
# 暦年代
|
854
|
+
#
|
855
|
+
# see {http://schemas.opengis.net/gml/3.1.1/base/temporalReferenceSystems.xsd#TimeCalendarEraType gml schema}
|
856
|
+
#
|
857
|
+
class CalendarEra < When::TM::Object
|
858
|
+
|
859
|
+
include When
|
860
|
+
|
861
|
+
class << self
|
862
|
+
|
863
|
+
include When::Parts::Resource::Pool
|
864
|
+
|
865
|
+
# When::TM::CalendarEra Class のグローバルな設定を行う
|
866
|
+
#
|
867
|
+
# @param [Array<String>] order When::TM::CalendarEra の検索順序を指定するIRI文字列のArray
|
868
|
+
#
|
869
|
+
# @return [void]
|
870
|
+
#
|
871
|
+
def _setup_(order=nil)
|
872
|
+
@_lock_ = Mutex.new if When.multi_thread
|
873
|
+
@_lock_.lock if @_lock_
|
874
|
+
@_pool = {}
|
875
|
+
@order = order || DefaultEpochs
|
876
|
+
@_lock_.unlock if @_lock_
|
877
|
+
end
|
878
|
+
|
879
|
+
# When::TM::CalendarEra オブジェクトを検索し取得する
|
880
|
+
#
|
881
|
+
# @overload _instance(key, epoch=nil, reverse=nil, options={})
|
882
|
+
# @param [String, Regexp] key 検索する暦年代または、暦年代にマッチする正規表現
|
883
|
+
# @param [Integer] epoch 年数を昇順にカウントする方式での暦元(0年)の通年(デフォルトは nil - 指定なし)
|
884
|
+
# @param [Integer] reverse 年数を降順にカウントする方式での暦元(0年)の通年(デフォルトは nil - 指定なし)
|
885
|
+
# @param [Hash] options
|
886
|
+
# @option options [String] :area 暦年代の使用地域の指定(デフォルトは nil - 指定なし)
|
887
|
+
# @option options [String] :period 暦年代の使用時代の指定(デフォルトは nil - 指定なし)
|
888
|
+
# @option options [Integer] :count 何件ヒットするまで検索するかを指定(デフォルトは 1件)
|
889
|
+
# @option options [String] the_others 例えば When::TM::CalendarEra オブジェクトの epoch_of_use に 'name' などの
|
890
|
+
# 指定がある場合、:name に指定しておけば、検索での絞り込みに使用できる。
|
891
|
+
#
|
892
|
+
def _instance(*args)
|
893
|
+
# パラメータ
|
894
|
+
args = args.dup
|
895
|
+
options = (args[-1].kind_of?(Hash)) ? args.pop.dup : {}
|
896
|
+
key, epoch, reverse = options.delete(:label) || args
|
897
|
+
key = When::Parts::Locale.ideographic_unification(key)
|
898
|
+
if key.kind_of?(String)
|
899
|
+
key, *parents = key.split(/::/).reverse
|
900
|
+
else
|
901
|
+
parents = []
|
902
|
+
end
|
903
|
+
area = options.delete(:area)
|
904
|
+
period = options.delete(:period)
|
905
|
+
count = options.delete(:count) || 1
|
906
|
+
|
907
|
+
# 候補
|
908
|
+
_setup_ unless @_pool
|
909
|
+
pool = _candidates(options, area, period, key, epoch, false) +
|
910
|
+
_candidates(options, area, period, key, reverse, true)
|
911
|
+
_compact(pool, parents)
|
912
|
+
return pool unless pool.size < count
|
913
|
+
|
914
|
+
@order.each do |iri|
|
915
|
+
When.CalendarEra(iri)
|
916
|
+
pool = _candidates(options, area, period, key, epoch, false) +
|
917
|
+
_candidates(options, area, period, key, reverse, true)
|
918
|
+
_compact(pool, parents)
|
919
|
+
return pool unless pool.size < count
|
920
|
+
end
|
921
|
+
|
922
|
+
return []
|
923
|
+
end
|
924
|
+
|
925
|
+
private
|
926
|
+
|
927
|
+
# 候補の抽出
|
928
|
+
def _candidates(options, area, period, key, epoch, reverse)
|
929
|
+
regexp, key = key if key.kind_of?(Regexp)
|
930
|
+
return [] unless @_pool[area] &&
|
931
|
+
@_pool[area][period] &&
|
932
|
+
@_pool[area][period][key] &&
|
933
|
+
@_pool[area][period][key][epoch]
|
934
|
+
pool = @_pool[area][period][key][epoch].dup
|
935
|
+
pool.delete_if {|e| regexp !~ e.name} if regexp
|
936
|
+
return pool if options.empty?
|
937
|
+
pool.delete_if {|e| !_match(e, reverse, options) }
|
938
|
+
end
|
939
|
+
|
940
|
+
def _match(epoch, reverse, options)
|
941
|
+
return false unless epoch.reverse? == reverse
|
942
|
+
target = {:reference_event => epoch.reference_event,
|
943
|
+
:reference_date => epoch.reference_date,
|
944
|
+
:julian_reference => epoch.julian_reference
|
945
|
+
}
|
946
|
+
options.each_pair do |k,v|
|
947
|
+
return false unless (v === (target.key?(k) ? target[k] : epoch.options[k]))
|
948
|
+
end
|
949
|
+
return true
|
950
|
+
end
|
951
|
+
|
952
|
+
def _compact(pool, parents)
|
953
|
+
pool.uniq!
|
954
|
+
return if parents.empty?
|
955
|
+
pool.delete_if {|e|
|
956
|
+
!parents.each do |parent|
|
957
|
+
e = e.parent
|
958
|
+
break false if parent != e.name
|
959
|
+
end
|
960
|
+
}
|
961
|
+
end
|
962
|
+
end
|
963
|
+
|
964
|
+
# @private
|
965
|
+
HashProperty =
|
966
|
+
[:reference_event, :reference_date, :julian_reference, :dating_system, # :epoch_of_use
|
967
|
+
:epoch, :epoch_year, :options]
|
968
|
+
|
969
|
+
# この暦年代を識別する名称
|
970
|
+
#
|
971
|
+
# Name by which this calendar era is known
|
972
|
+
#
|
973
|
+
# @return [String]
|
974
|
+
# 通常 String のサブクラスである When::BasicTypes::M17n を使用する。
|
975
|
+
#
|
976
|
+
alias :name :label
|
977
|
+
|
978
|
+
# この暦年代の基点となる事象
|
979
|
+
#
|
980
|
+
# Event used as the datum for this calendar era
|
981
|
+
#
|
982
|
+
# @return [String]
|
983
|
+
# 通常 String のサブクラスである When::BasicTypes::M17n を使用する。
|
984
|
+
#
|
985
|
+
# @note
|
986
|
+
# [Accession,代始]:: 天皇・皇帝などの代始めの改元,必ずしも践祚と連動しない。
|
987
|
+
# :: JIS X7108 附属書D表3に参照事象の例として「新しい天皇の即位」とある。
|
988
|
+
# :: これは践祚を意味するので、岡田芳朗氏によれば適切ではないとのこと。
|
989
|
+
# :: 英語には適切な訳語がないと思われる。
|
990
|
+
# [FelicitousEvent,祥瑞]:: 祥瑞の発生に伴う改元
|
991
|
+
# [NaturalDisaster,災異]:: 災異の発生に伴う改元
|
992
|
+
# [InauspiciousYear,革年]:: 甲子革令・辛酉革命説による改元
|
993
|
+
# [Foundation,創業]:: 建国による元号の制定
|
994
|
+
# [CalendarReform,改暦]:: 改暦に伴う epoch_of_use の境界
|
995
|
+
#
|
996
|
+
attr_reader :reference_event
|
997
|
+
alias :referenceEvent :reference_event
|
998
|
+
|
999
|
+
# この暦による参照事象の日付
|
1000
|
+
#
|
1001
|
+
# Date of the reference event in the calendar being described
|
1002
|
+
#
|
1003
|
+
# @return [When::TM::CalDate]
|
1004
|
+
#
|
1005
|
+
# @note
|
1006
|
+
# 明治以前の改元は当該年の初めにに遡って適用された。しかし、日記などの資料は当然旧年号で
|
1007
|
+
# 記載されている。このような場合、reference_date の分解能を「年」とする。
|
1008
|
+
# 本ライブラリでは、reference_date の分解能が「年」の場合、When::TM::TemporalPosition._instance
|
1009
|
+
# の options[:lower] で年号使用の下限を年初とするか、epoch_of_use の下限とするかを
|
1010
|
+
# 指定することができる。
|
1011
|
+
#
|
1012
|
+
attr_reader :reference_date
|
1013
|
+
alias :referenceDate :reference_date
|
1014
|
+
|
1015
|
+
# 参照事象のユリウス日
|
1016
|
+
#
|
1017
|
+
# Julian date of the reference event
|
1018
|
+
#
|
1019
|
+
# @return [When::TM::JulianDate]
|
1020
|
+
#
|
1021
|
+
attr_reader :julian_reference
|
1022
|
+
alias :julianReference :julian_reference
|
1023
|
+
|
1024
|
+
# この暦年代が日付の基礎として使用する期間
|
1025
|
+
#
|
1026
|
+
# Period for which the era was used as a basis for dating
|
1027
|
+
#
|
1028
|
+
# @return [Array<When::TM::TemporalPosition>]
|
1029
|
+
#
|
1030
|
+
# @note
|
1031
|
+
# 途中の改暦を指定するために要素が必要になることがあり、要素数が2を超えることがある。
|
1032
|
+
# 最初の要素が When::TimeValue::MIN(-Infinity)の場合、年数を降順にカウントする。
|
1033
|
+
#
|
1034
|
+
attr_reader :epoch
|
1035
|
+
|
1036
|
+
# この暦年代と関連付けられた暦 (relation - Basis)
|
1037
|
+
#
|
1038
|
+
# The calendar associated with the calendar eras being described
|
1039
|
+
#
|
1040
|
+
# @return [Array<When::TM::Calendar>]
|
1041
|
+
#
|
1042
|
+
attr_reader :dating_system
|
1043
|
+
alias :datingSystem :dating_system
|
1044
|
+
|
1045
|
+
# この暦年代の元年の年番号(additional attribute)
|
1046
|
+
#
|
1047
|
+
# The year number of the calendar associated with the first year of this calendar era
|
1048
|
+
#
|
1049
|
+
# @return [Integer]
|
1050
|
+
#
|
1051
|
+
attr_reader :epoch_year
|
1052
|
+
alias :epochYear :epoch_year
|
1053
|
+
|
1054
|
+
# その他の属性 - additional attribute
|
1055
|
+
#
|
1056
|
+
# @return [Hash]
|
1057
|
+
# [ 'area' => 暦年代の使用地域 [When::BasicTypes::M17n] ]
|
1058
|
+
# [ 'period' => 暦年代の使用時代 [When::BasicTypes::M17n] ]
|
1059
|
+
# [ the others => epoch_of_use の 'name' などの指定を反映 [String] ]
|
1060
|
+
#
|
1061
|
+
attr_reader :options
|
1062
|
+
|
1063
|
+
# この暦年代が日付の基礎として使用する期間
|
1064
|
+
#
|
1065
|
+
# Period for which the era was used as a basis for dating
|
1066
|
+
#
|
1067
|
+
# @return [When::TM::Period]
|
1068
|
+
#
|
1069
|
+
# @note
|
1070
|
+
# epoch_of_use メソッドの戻り値は ISO19108 で When::TM::Period と規定されている。
|
1071
|
+
# このため変数 @epoch とは別に、本メソッドを提供する。
|
1072
|
+
#
|
1073
|
+
def epoch_of_use
|
1074
|
+
@epoch_of_use ||=
|
1075
|
+
Period.new(*([0, -1].map {|i|
|
1076
|
+
date = @epoch[i]
|
1077
|
+
if date.kind_of?(CalDate)
|
1078
|
+
options = date._attr
|
1079
|
+
options[:frame] = options.delete(:clock)
|
1080
|
+
date = JulianDate.universal_time(date.universal_time, options)
|
1081
|
+
end
|
1082
|
+
Instant.new(date) # See JIS X7108 5.3.2.2 e) When::TM::Period は直接 JulianDate を保持できない
|
1083
|
+
}))
|
1084
|
+
end
|
1085
|
+
alias :epochOfUse :epoch_of_use
|
1086
|
+
|
1087
|
+
# 年数の数え方
|
1088
|
+
#
|
1089
|
+
# @return [Boolean]
|
1090
|
+
# [ true - 降順 (Before Common Era 方式)]
|
1091
|
+
# [ false - 昇順 (Common Era 方式) ]
|
1092
|
+
#
|
1093
|
+
def reverse?
|
1094
|
+
@epoch[0].indeterminated_position == TimeValue::Min
|
1095
|
+
end
|
1096
|
+
|
1097
|
+
# 未来永劫使用するか?
|
1098
|
+
#
|
1099
|
+
# @return [Boolean]
|
1100
|
+
# [ true - する ]
|
1101
|
+
# [ false - しない ]
|
1102
|
+
#
|
1103
|
+
def unlimited?
|
1104
|
+
@epoch[-1].indeterminated_position == TimeValue::Max
|
1105
|
+
end
|
1106
|
+
|
1107
|
+
# 時間の歩度
|
1108
|
+
#
|
1109
|
+
# @return [Numeric]
|
1110
|
+
#
|
1111
|
+
def rate_of_clock
|
1112
|
+
_typical_epoch.rate_of_clock
|
1113
|
+
end
|
1114
|
+
|
1115
|
+
# 当該の暦年代の日付に変換する
|
1116
|
+
#
|
1117
|
+
# @param [When::TM::TemporalPosition] date
|
1118
|
+
# @param [Hash] trans_options 以下の通り
|
1119
|
+
# @option trans_options [Hash] :lower 暦年代適用の下限
|
1120
|
+
# [ true - epoch_of_use の始め(省略時) ]
|
1121
|
+
# [ :reference_date - 参照事象の日付 ]
|
1122
|
+
# @option trans_options [Hash] :upper 暦年代適用の上限
|
1123
|
+
# [ true - epoch_of_use の終わり(省略時) ]
|
1124
|
+
# [ :reference_date - 参照事象の日付 ]
|
1125
|
+
#
|
1126
|
+
# @return [When::TM::TemporalPosition]
|
1127
|
+
# [ When::TimeValue::Before - 当該の暦年代より前の日付である ]
|
1128
|
+
# [ When::TimeValue::After - 当該の暦年代より後の日付である ]
|
1129
|
+
# [ その他 - 当該の暦年代の日付に変換された When::TM::TemporalPosition ]
|
1130
|
+
#
|
1131
|
+
def trans(date, trans_options={})
|
1132
|
+
# 当該日付の決定
|
1133
|
+
date = Position.any_other(date, trans_options) unless date.kind_of?(Array)
|
1134
|
+
epoch, cal_date =
|
1135
|
+
case date
|
1136
|
+
when Array ; _trans_array(date)
|
1137
|
+
when JulianDate, DateAndTime ; _trans_date(date, date.clock)
|
1138
|
+
when TimeValue ; _trans_date(date)
|
1139
|
+
when Numeric ; _trans_date(JulianDate.universal_time((date-JulianDate::JD19700101)*Duration::DAY))
|
1140
|
+
else ; raise TypeError, "Irregal Seed Date Type"
|
1141
|
+
end
|
1142
|
+
return epoch unless cal_date
|
1143
|
+
|
1144
|
+
# 上下限の確認
|
1145
|
+
trans_options ||= {}
|
1146
|
+
return TimeValue::Before if cal_date.to_i < lower_bound(trans_options[:lower] || :reference_date)
|
1147
|
+
return TimeValue::After if cal_date.to_i > upper_bound(trans_options[:upper] || true)
|
1148
|
+
|
1149
|
+
# 発見した日時の属性設定
|
1150
|
+
cal_date.calendar_era = self
|
1151
|
+
cal_date.calendar_era_name = [@label, @epoch_year, reverse?, cal_date.to_i < @epoch[0].to_i]
|
1152
|
+
cal_date.cal_date[0] -= @epoch_year
|
1153
|
+
cal_date.trans = trans_options.dup
|
1154
|
+
cal_date.query = epoch.query.dup
|
1155
|
+
return cal_date
|
1156
|
+
end
|
1157
|
+
|
1158
|
+
# When::TM::TemporalPosition ^ When::TM::CalendarEra で呼ばれる
|
1159
|
+
# @private
|
1160
|
+
def ^(date, options={})
|
1161
|
+
date = Position.any_other(date, options)
|
1162
|
+
cal_date = trans(date, (date.trans||{}).merge(options))
|
1163
|
+
return nil unless cal_date.kind_of?(CalDate)
|
1164
|
+
return cal_date
|
1165
|
+
end
|
1166
|
+
|
1167
|
+
# other と @julian_reference とを比較する
|
1168
|
+
#
|
1169
|
+
# @param [Comparable] other 比較対象
|
1170
|
+
#
|
1171
|
+
# @return [Integer] 比較結果を 負, 0, 正の値で返す
|
1172
|
+
#
|
1173
|
+
def <=>(other) #TODO @precision は?
|
1174
|
+
@julian_reference.universal_time <=> other.julian_reference.universal_time
|
1175
|
+
end
|
1176
|
+
|
1177
|
+
# 暦年代の下限
|
1178
|
+
# @private
|
1179
|
+
def lower_bound(type=nil)
|
1180
|
+
@lower_bound[type] ||= @epoch[0].indeterminated_position == TimeValue::Min ? -Float::MAX :
|
1181
|
+
@reference_date.precision == YEAR &&
|
1182
|
+
@reference_date.cal_date[YEAR-1] == 0 ? @epoch[0].ceil(YEAR).to_i :
|
1183
|
+
case type
|
1184
|
+
when true ; @epoch[0].to_i
|
1185
|
+
when :reference_date ; @reference_date.to_i
|
1186
|
+
else ; [@reference_date.to_i, @epoch[0].to_i].min
|
1187
|
+
end
|
1188
|
+
end
|
1189
|
+
|
1190
|
+
# 暦年代の上限
|
1191
|
+
# @private
|
1192
|
+
def upper_bound(type=nil)
|
1193
|
+
@upper_bound[type] ||= @epoch[-1].indeterminated_position == TimeValue::Max ? +Float::MAX :
|
1194
|
+
begin
|
1195
|
+
next_era = succ
|
1196
|
+
next_ref = next_era.reference_date if next_era.respond_to?(:reference_date)
|
1197
|
+
next_ref &&
|
1198
|
+
next_ref.precision == YEAR &&
|
1199
|
+
next_ref.cal_date[YEAR-1] == 0 ? @epoch[-1].ceil(YEAR).to_i :
|
1200
|
+
case type
|
1201
|
+
when true ; @epoch[-1].to_i - 1
|
1202
|
+
when :reference_date ; @reference_date.to_i
|
1203
|
+
else ; [@reference_date.to_i, @epoch[-1].to_i - 1].max
|
1204
|
+
end
|
1205
|
+
end
|
1206
|
+
end
|
1207
|
+
|
1208
|
+
protected
|
1209
|
+
|
1210
|
+
# @private
|
1211
|
+
def _normalize_leaf_era
|
1212
|
+
# r_date and others
|
1213
|
+
case @reference_date
|
1214
|
+
when String ; format, r_date, r_era = When::BasicTypes::DateTime._to_array(@reference_date)
|
1215
|
+
when Array ; r_era, *r_date = @reference_date
|
1216
|
+
when CalDate ; r_era, r_date = @reference_date.calendar_era_name, @reference_date.cal_date
|
1217
|
+
when nil ;
|
1218
|
+
else ; raise TypeError, "ReferenceDate is invalid type"
|
1219
|
+
end
|
1220
|
+
r_era, r_year = r_era
|
1221
|
+
|
1222
|
+
epochs = @epoch.dup
|
1223
|
+
epochs.shift if (epochs[0].indeterminated_position == TimeValue::Min)
|
1224
|
+
# j_date and calculated reference_date !((julian_reference == nil) && (reference_date != nil))
|
1225
|
+
if @julian_reference
|
1226
|
+
jdn = @julian_reference.to_i
|
1227
|
+
epoch = epochs[0]
|
1228
|
+
epochs.each do |e|
|
1229
|
+
if (e.indeterminated_position == TimeValue::Max)
|
1230
|
+
epoch = e
|
1231
|
+
break
|
1232
|
+
elsif (jdn < e.to_i)
|
1233
|
+
break
|
1234
|
+
else
|
1235
|
+
epoch = e
|
1236
|
+
end
|
1237
|
+
end
|
1238
|
+
@reference_date = epoch.frame.jul_trans(When.when?(jdn), {:frame=>epoch.frame})
|
1239
|
+
j_date = @reference_date.cal_date
|
1240
|
+
elsif (@reference_date == nil)
|
1241
|
+
@reference_date = epochs[0].dup
|
1242
|
+
j_date = @reference_date.cal_date
|
1243
|
+
end
|
1244
|
+
|
1245
|
+
# epoch_year
|
1246
|
+
@epoch_year ||= r_year
|
1247
|
+
@epoch_year = @epoch_year.to_i if (@epoch_year)
|
1248
|
+
raise ArgumentError, "EpochYear mismatch" unless (@epoch_year == r_year)
|
1249
|
+
unless @epoch_year
|
1250
|
+
raise ArgumentError, "ReferenceDate is absent" unless r_date
|
1251
|
+
@epoch_year = epochs[0].cal_date[0] * 1 - r_date[0] * 1
|
1252
|
+
end
|
1253
|
+
|
1254
|
+
# j_date and calculated reference_date ((julian_reference == nil) && (reference_date != nil))
|
1255
|
+
unless j_date
|
1256
|
+
j_date = [+r_date[0]+@epoch_year, *r_date[1..-1]]
|
1257
|
+
epochs.each_index do |i|
|
1258
|
+
e = epochs[i]
|
1259
|
+
d = CalDate.new(j_date,{:frame=>e.frame})
|
1260
|
+
if (e.indeterminated_position == TimeValue::Max)
|
1261
|
+
@reference_date = d
|
1262
|
+
break
|
1263
|
+
elsif (d.to_i < e.to_i)
|
1264
|
+
@reference_date = d if (i==0)
|
1265
|
+
break
|
1266
|
+
else
|
1267
|
+
@reference_date = d
|
1268
|
+
end
|
1269
|
+
end
|
1270
|
+
end
|
1271
|
+
|
1272
|
+
# julian_reference and reference_date
|
1273
|
+
@julian_reference = JulianDate.universal_time(@reference_date.universal_time)
|
1274
|
+
@reference_date.cal_date[0] -= @epoch_year
|
1275
|
+
@reference_date.calendar_era_name = [(r_era ? r_era : @label), @epoch_year]
|
1276
|
+
if (r_date)
|
1277
|
+
raise ArgumentError, "JulianReference and ReferenceDate are mismatch" unless (@epoch_year == +j_date[0]-(+r_date[0]))
|
1278
|
+
raise ArgumentError, "JulianReference and ReferenceDate are mismatch" unless (j_date[1..-1] == r_date[1..-1])
|
1279
|
+
#raise ArgumentError, "JulianReference and ReferenceDate are mismatch" unless (j_date == r_date)
|
1280
|
+
if (r_date[1] == nil)
|
1281
|
+
@reference_date.precision = YEAR
|
1282
|
+
elsif (r_date[2] == nil)
|
1283
|
+
@reference_date.precision = MONTH
|
1284
|
+
end
|
1285
|
+
end
|
1286
|
+
end
|
1287
|
+
|
1288
|
+
# @private
|
1289
|
+
def _register_calendar_era
|
1290
|
+
return unless @label.kind_of?(When::BasicTypes::M17n)
|
1291
|
+
|
1292
|
+
# dating_system
|
1293
|
+
@dating_system = (@epoch.map {|e| e.frame}).compact.uniq
|
1294
|
+
|
1295
|
+
if @epoch.length == 1
|
1296
|
+
epoch[0].frame.synchronize {
|
1297
|
+
epoch[0].frame.domain |= When::Parts::GeometricComplex.new([[epoch[0],true]])
|
1298
|
+
} if epoch[0].frame
|
1299
|
+
elsif reverse?
|
1300
|
+
epoch[1].frame.synchronize {
|
1301
|
+
epoch[1].frame.domain |= When::Parts::GeometricComplex.new([[epoch[1],true]], true)
|
1302
|
+
} if epoch[1].frame
|
1303
|
+
else
|
1304
|
+
(epoch.length-1).times do |i|
|
1305
|
+
epoch[i].frame.synchronize {
|
1306
|
+
epoch[i].frame.domain |= When::Parts::GeometricComplex.new([[epoch[i],true], [epoch[i+1],false]])
|
1307
|
+
} if epoch[i].frame
|
1308
|
+
end
|
1309
|
+
end
|
1310
|
+
|
1311
|
+
@dating_system.each do |f|
|
1312
|
+
f.synchronize do
|
1313
|
+
f.reference_frame << self
|
1314
|
+
f.reference_frame.uniq!
|
1315
|
+
f.reference_frame.sort!
|
1316
|
+
first = f.domain.first(When.when?('-Infinity'))
|
1317
|
+
last = f.domain.last(When.when?('+Infinity'))
|
1318
|
+
f.domain_of_validity = When::EX::Extent.new(
|
1319
|
+
When::TM::Period.new(
|
1320
|
+
When::TM::Instant.new(first),
|
1321
|
+
When::TM::Instant.new(last))) if first
|
1322
|
+
end
|
1323
|
+
end
|
1324
|
+
|
1325
|
+
# インデクス登録
|
1326
|
+
((@area||{}).values + [nil]).each do |a|
|
1327
|
+
self.class[a] ||= {}
|
1328
|
+
((@period||{}).values + [nil]).each do |p|
|
1329
|
+
self.class[a][p] ||= {}
|
1330
|
+
(@label.values + [nil]).each do |k|
|
1331
|
+
self.class[a][p][k] ||= {}
|
1332
|
+
[@epoch_year, nil].each do |e|
|
1333
|
+
self.class[a][p][k][e] ||= []
|
1334
|
+
self.class[a][p][k][e] << self
|
1335
|
+
end
|
1336
|
+
end
|
1337
|
+
end
|
1338
|
+
end
|
1339
|
+
end
|
1340
|
+
|
1341
|
+
private
|
1342
|
+
|
1343
|
+
# オブジェクトの正規化
|
1344
|
+
def _normalize(args=[], options={})
|
1345
|
+
# area, period
|
1346
|
+
term_options = {:namespace=>@namespace, :locale=>@locale, :options=>options}
|
1347
|
+
@area = m17n(@area, nil, nil, term_options) if (@area.instance_of?(String))
|
1348
|
+
@period = m17n(@period, nil, nil, term_options) if (@period.instance_of?(String))
|
1349
|
+
|
1350
|
+
# 暦年代の上下限
|
1351
|
+
@lower_bound = {}
|
1352
|
+
@upper_bound = {}
|
1353
|
+
|
1354
|
+
# other attributes
|
1355
|
+
if (@child && @child.length>0)
|
1356
|
+
_non_leaf_era(args, term_options)
|
1357
|
+
#_register_calendar_era unless _pool['..'].kind_of?(CalendarEra)
|
1358
|
+
@child.each do |era|
|
1359
|
+
era._register_calendar_era
|
1360
|
+
end
|
1361
|
+
else
|
1362
|
+
_set_leaf_era(args, term_options)
|
1363
|
+
_normalize_leaf_era unless @epoch[0].indeterminated_position == TimeValue::Min
|
1364
|
+
end
|
1365
|
+
end
|
1366
|
+
|
1367
|
+
def _non_leaf_era(args, term_options)
|
1368
|
+
@label = m17n(@label, nil, nil, term_options) if (@label.instance_of?(String))
|
1369
|
+
if @label
|
1370
|
+
@label._pool['..'] = self # TODO ここを ||= にすると leaf? の判定がおかしくなる
|
1371
|
+
@_pool[@label.to_s] = @label
|
1372
|
+
end
|
1373
|
+
|
1374
|
+
# reference_date, reference_event & label
|
1375
|
+
@reference_date = @child[0].reference_date
|
1376
|
+
@reference_event = @child[0].reference_event
|
1377
|
+
@epoch_year = @child[0].epoch_year
|
1378
|
+
@julian_reference = @child[0].julian_reference
|
1379
|
+
|
1380
|
+
# options
|
1381
|
+
@options ||= {}
|
1382
|
+
@options.update({'area'=>@area, 'period'=>@period})
|
1383
|
+
|
1384
|
+
# epoch
|
1385
|
+
@epoch = []
|
1386
|
+
@child.each do |c|
|
1387
|
+
c.epoch.each do |e|
|
1388
|
+
@epoch << e unless e == @epoch[-1]
|
1389
|
+
end
|
1390
|
+
end
|
1391
|
+
end
|
1392
|
+
|
1393
|
+
def _set_leaf_era(args, term_options)
|
1394
|
+
# 変数の読み込み
|
1395
|
+
reference_date, reference_event, *epochs = args
|
1396
|
+
|
1397
|
+
# reference_date & label
|
1398
|
+
if reference_date
|
1399
|
+
@reference_date = reference_date
|
1400
|
+
@label = m17n(@reference_date[/^\[[^\]]+\]|^[^-+0-9]+/], nil, nil, term_options)
|
1401
|
+
end
|
1402
|
+
@label._pool['..'] ||= self
|
1403
|
+
@_pool[@label.to_s] = @label
|
1404
|
+
|
1405
|
+
# reference_event
|
1406
|
+
@reference_event = reference_event if reference_event
|
1407
|
+
@reference_event ||= ""
|
1408
|
+
@reference_event = m17n(@reference_event, nil, nil, term_options) if @reference_event.instance_of?(String)
|
1409
|
+
@reference_event._pool['..'] ||= self
|
1410
|
+
@_pool[@reference_event.to_s] = @reference_event
|
1411
|
+
|
1412
|
+
# options
|
1413
|
+
term_options[:options][:query] ||= {}
|
1414
|
+
@options ||= {}
|
1415
|
+
@options.update(term_options[:options][:query])
|
1416
|
+
@options.update({'area'=>@area, 'period'=>@period})
|
1417
|
+
|
1418
|
+
# epoch
|
1419
|
+
@epoch ||= epochs
|
1420
|
+
@epoch[0] ||= '-Infinity'
|
1421
|
+
@epoch[1] ||= '+Infinity'
|
1422
|
+
term_options[:options][:frame] ||= When.Resource('_c:Gregorian')
|
1423
|
+
epoch = ''
|
1424
|
+
@epoch = @epoch.map {|e|
|
1425
|
+
case e
|
1426
|
+
when ''
|
1427
|
+
When.when?('+Infinity')
|
1428
|
+
when String
|
1429
|
+
d, f = e.split(/\^{1,2}/)
|
1430
|
+
term_options[:options][:frame] = When.Resource(f, '_c:') if (f)
|
1431
|
+
d.split(/;/).each do |v|
|
1432
|
+
v.strip!
|
1433
|
+
if (v =~ /^[-+\d]|^Now$|^Unknown$|^[-+]Infinity$/i)
|
1434
|
+
epoch = v
|
1435
|
+
break
|
1436
|
+
end
|
1437
|
+
k, c = v.split(/\s*[:=]\s*/, 2)
|
1438
|
+
if (c.kind_of?(String))
|
1439
|
+
code = m17n(c.gsub(/%2C/,','), nil, nil, term_options)
|
1440
|
+
@_pool[code.to_s] ||= code
|
1441
|
+
@options[k] = term_options[:options][:query][k] = @_pool[code.to_s]
|
1442
|
+
else
|
1443
|
+
@options.delete(k)
|
1444
|
+
term_options[:options][:query].delete(k)
|
1445
|
+
end
|
1446
|
+
end
|
1447
|
+
When.when?(epoch, @options.merge({:frame=>term_options[:options][:frame], :validate=>:epoch}))
|
1448
|
+
else
|
1449
|
+
e
|
1450
|
+
end
|
1451
|
+
}
|
1452
|
+
|
1453
|
+
# normalize for last era
|
1454
|
+
last_era = _pool['..'].child[-1] if _pool['..'].kind_of?(CalendarEra)
|
1455
|
+
if last_era
|
1456
|
+
if last_era.epoch[0].indeterminated_position == TimeValue::Min
|
1457
|
+
last_era.epoch[0].frame = @epoch[0].frame
|
1458
|
+
last_era.epoch[1] = @epoch[0]
|
1459
|
+
last_era._normalize_leaf_era
|
1460
|
+
elsif last_era.epoch[-1].indeterminated_position == TimeValue::Max
|
1461
|
+
last_era.epoch[-1] = @epoch[0]
|
1462
|
+
end
|
1463
|
+
end
|
1464
|
+
end
|
1465
|
+
|
1466
|
+
# 配下のオブジェクトの前後関係の設定
|
1467
|
+
def _sequence
|
1468
|
+
return unless @child
|
1469
|
+
prev = nil
|
1470
|
+
if @_pool['..'].respond_to?(:child) && @_pool['..'].child
|
1471
|
+
(@_pool['..'].child.length-1).downto(0) do |i|
|
1472
|
+
v = @_pool['..'].child[i]
|
1473
|
+
next if (v.epoch[0]>=self.epoch[0])
|
1474
|
+
prev = v
|
1475
|
+
break
|
1476
|
+
end
|
1477
|
+
end
|
1478
|
+
@child.each do |v|
|
1479
|
+
if prev
|
1480
|
+
v._pool['.<-'] = prev
|
1481
|
+
prev._pool['.->'] ||= v
|
1482
|
+
while (prev.child && prev.child[-1]) do
|
1483
|
+
prev = prev.child[-1]
|
1484
|
+
prev._pool['.->'] ||= v
|
1485
|
+
end
|
1486
|
+
end
|
1487
|
+
@_pool[v.label.to_s] = v
|
1488
|
+
prev = v
|
1489
|
+
end
|
1490
|
+
end
|
1491
|
+
|
1492
|
+
def _trans_array(date)
|
1493
|
+
date = date.dup
|
1494
|
+
cal_date = frame = nil
|
1495
|
+
epoch = @epoch[0]
|
1496
|
+
@epoch.each do |e|
|
1497
|
+
cal_date = CalDate.new(date,{:frame=>e.frame}) unless (frame == e.frame)
|
1498
|
+
frame = e.frame
|
1499
|
+
break if (e.indeterminated_position == TimeValue::Max)
|
1500
|
+
break if (cal_date < e)
|
1501
|
+
epoch = e
|
1502
|
+
end
|
1503
|
+
cal_date = CalDate.new(date, {:frame=>epoch.frame}) unless (frame == epoch.frame)
|
1504
|
+
return epoch, cal_date
|
1505
|
+
end
|
1506
|
+
|
1507
|
+
def _trans_date(date, clock=nil)
|
1508
|
+
unless rate_of_clock == date.rate_of_clock
|
1509
|
+
date = JulianDate.dynamical_time(date.dynamical_time, {:time_standard=>_typical_epoch.time_standard})
|
1510
|
+
clock = _typical_epoch.clock
|
1511
|
+
end
|
1512
|
+
frac = (clock) ? clock.universal_time : 0
|
1513
|
+
sdn, time = (date.universal_time - frac).divmod(Duration::DAY)
|
1514
|
+
sdn += JulianDate::JD19700101
|
1515
|
+
epoch = @epoch[0]
|
1516
|
+
return TimeValue::Before if sdn < lower_bound
|
1517
|
+
return TimeValue::After if sdn > upper_bound
|
1518
|
+
@epoch.each do |e|
|
1519
|
+
break if (e.indeterminated_position == When::TimeValue::Max)
|
1520
|
+
break if (sdn < e.to_i)
|
1521
|
+
epoch = e
|
1522
|
+
end
|
1523
|
+
frame = epoch.frame
|
1524
|
+
cal_date = frame.to_cal_date(sdn)
|
1525
|
+
return epoch, CalDate.new(cal_date, {:frame=>frame}) unless clock
|
1526
|
+
return epoch, DateAndTime.new(cal_date, time+frac, {:frame=>frame, :clock=>clock})
|
1527
|
+
end
|
1528
|
+
|
1529
|
+
# 代表的な元期
|
1530
|
+
#
|
1531
|
+
# @return [When::TM::TemporalPosition]
|
1532
|
+
#
|
1533
|
+
def _typical_epoch
|
1534
|
+
@_typical_epoch ||= reverse? ? @epoch[-1] : @epoch[0]
|
1535
|
+
end
|
1536
|
+
|
1537
|
+
# その他のメソッド
|
1538
|
+
#
|
1539
|
+
# @note
|
1540
|
+
# When::TM::CalendarEra で定義されていないメソッドは
|
1541
|
+
# 処理を @reference_date (type: When::TM::TemporalPosition) に委譲する
|
1542
|
+
#
|
1543
|
+
def method_missing(name, *args, &block)
|
1544
|
+
@reference_date.send(name.to_sym, *args, &block)
|
1545
|
+
end
|
1546
|
+
end
|
1547
|
+
end
|