when_exe 0.4.4 → 0.4.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/when_exe.rb +89 -3
- data/lib/when_exe/basictypes.rb +37 -7
- data/lib/when_exe/calendarnote.rb +18 -13
- data/lib/when_exe/calendartypes.rb +3 -9
- data/lib/when_exe/coordinates.rb +23 -373
- data/lib/when_exe/ephemeris.rb +7 -7
- data/lib/when_exe/ephemeris/notes.rb +0 -14
- data/lib/when_exe/events.rb +1851 -0
- data/lib/when_exe/icalendar.rb +121 -4
- data/lib/when_exe/linkeddata.rb +29 -18
- data/lib/when_exe/locales/akt.rb +63 -0
- data/lib/when_exe/locales/locale.rb +60 -11
- data/lib/when_exe/mini_application.rb +14 -8
- data/lib/when_exe/namespace.rb +42 -0
- data/lib/when_exe/parts/enumerator.rb +13 -2
- data/lib/when_exe/parts/geometric_complex.rb +51 -1
- data/lib/when_exe/parts/method_cash.rb +15 -10
- data/lib/when_exe/parts/resource.rb +47 -29
- data/lib/when_exe/region/chinese.rb +4 -3
- data/lib/when_exe/region/chinese/calendars.rb +4 -4
- data/lib/when_exe/region/chinese/epochs.rb +6 -6
- data/lib/when_exe/region/chinese/notes.rb +3 -3
- data/lib/when_exe/region/chinese/twins.rb +6 -6
- data/lib/when_exe/region/islamic.rb +1 -1
- data/lib/when_exe/region/japanese.rb +4 -4
- data/lib/when_exe/region/japanese/eclipses.rb +2 -2
- data/lib/when_exe/region/japanese/location.rb +93 -0
- data/lib/when_exe/region/japanese/notes.rb +29 -11
- data/lib/when_exe/region/japanese/residues.rb +1 -1
- data/lib/when_exe/region/japanese/twins.rb +18 -6
- data/lib/when_exe/region/location.rb +40 -0
- data/lib/when_exe/region/martian.rb +1 -1
- data/lib/when_exe/region/ryukyu.rb +1 -1
- data/lib/when_exe/spatial.rb +611 -0
- data/lib/when_exe/timestandard.rb +3 -3
- data/lib/when_exe/tmobjects.rb +32 -0
- data/lib/when_exe/tmposition.rb +211 -1318
- data/lib/when_exe/tmptypes.rb +1265 -0
- data/lib/when_exe/tmreference.rb +35 -0
- data/lib/when_exe/version.rb +3 -3
- data/test/events/example-datasets +7 -0
- data/test/events/history-dataset.csv +22 -0
- data/test/events/japanese-holiday-index.csv +28 -0
- data/test/events/japanese-holiday.csv +77 -0
- data/test/events/japanese-holiday.ttl +778 -0
- data/test/events/make_events_ttl.rb +18 -0
- data/test/events/mori_wikichoshi.csv +14 -0
- data/test/events/ndl_koyomi.csv +220 -0
- data/test/events/ndl_koyomi_index.csv +44 -0
- data/test/events/primeminister-dataset.csv +19 -0
- data/test/events/shogun-dataset.csv +22 -0
- data/test/events/test-history-dataset-edge-sparql.csv +26 -0
- data/test/events/test-history-dataset-edge.csv +27 -0
- data/test/events/test-history-dataset-sparql.csv +22 -0
- data/test/events/test-history-dataset.csv +23 -0
- data/test/events/test-history-events-edge.ttl +89 -0
- data/test/events/test-history-events.csv +6 -0
- data/test/examples/Terms.m17n +1 -1
- data/test/test.rb +6 -0
- data/test/test/coordinates.rb +2 -2
- data/test/test/events.rb +32 -0
- data/test/test/region/japanese.rb +20 -0
- data/test/test/region/m17n.rb +2 -2
- data/test/test/region/mayan.rb +6 -6
- data/test/test/tmposition.rb +63 -1
- metadata +26 -2
@@ -0,0 +1,1265 @@
|
|
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::TM
|
9
|
+
|
10
|
+
#
|
11
|
+
# 時間座標 - 単一の時間間隔によって定義する連続な間隔尺度を基礎とする
|
12
|
+
#
|
13
|
+
# see {http://schemas.opengis.net/gml/3.1.1/base/temporalAppendix.xsd#TimeCoordinateType gml schema}
|
14
|
+
#
|
15
|
+
class Coordinate < TemporalPosition
|
16
|
+
|
17
|
+
class << self
|
18
|
+
# 内部時間によるオブジェクトの生成
|
19
|
+
alias :universal_time :new
|
20
|
+
|
21
|
+
# 外部時間によるオブジェクトの生成
|
22
|
+
#
|
23
|
+
# @param [Numeric] dynamical_time 外部時間による時間座標値
|
24
|
+
#
|
25
|
+
# @param [Hash] options 下記の通り
|
26
|
+
# @option options [When::TimeStandard] :time_standard
|
27
|
+
#
|
28
|
+
# @return [When::TM::Coordinate]
|
29
|
+
#
|
30
|
+
def dynamical_time(dynamical_time, options={})
|
31
|
+
universal_time(When.Resource(options[:time_standard] || 'UniversalTime', '_t:').from_dynamical_time(dynamical_time), options)
|
32
|
+
end
|
33
|
+
|
34
|
+
# 他種の時間位置によるオブジェクトの生成
|
35
|
+
#
|
36
|
+
# @param [Numeric, When::TM::ClockTime, ::Time, ::Date, ::DateTime] time 他種の時間位置によるオブジェクト
|
37
|
+
#
|
38
|
+
# @param [Hash] options 下記の通り
|
39
|
+
# @option options [When::TM::Clock] :clock
|
40
|
+
# @option options [When::Parts::Timezone] :tz
|
41
|
+
#
|
42
|
+
# @return [When::TM::Coordinate]
|
43
|
+
#
|
44
|
+
def new(time, options={})
|
45
|
+
options = options.dup
|
46
|
+
options[:frame] = Clock.get_clock_option(options)
|
47
|
+
case time
|
48
|
+
when Numeric
|
49
|
+
options[:frame] ||= When::UTC unless time.kind_of?(Integer)
|
50
|
+
universal_time = (2*time - (2*JulianDate::JD19700101-1)) * Duration::DAY.to_i / 2.0
|
51
|
+
when ClockTime
|
52
|
+
options[:frame] ||= time.clock
|
53
|
+
universal_time = time.clk_time[0] + time.universal_time
|
54
|
+
when ::Time
|
55
|
+
options[:frame] ||= When.Clock(time.gmtoff)
|
56
|
+
universal_time = options[:frame].time_standard.from_time_object(time)
|
57
|
+
when TimeValue
|
58
|
+
options[:frame] ||= time.clock
|
59
|
+
universal_time = time.universal_time
|
60
|
+
else
|
61
|
+
if ::Object.const_defined?(:Date) && ::Date.method_defined?(:+) && time.respond_to?(:ajd)
|
62
|
+
case time
|
63
|
+
when ::DateTime
|
64
|
+
options[:frame] ||= When.Clock((time.offset * 86400).to_i)
|
65
|
+
universal_time = (2*time.ajd - (2*JulianDate::JD19700101-1)) * Duration::DAY.to_i / 2.0
|
66
|
+
when ::Date
|
67
|
+
universal_time = JulianDate._d_to_t(time.jd)
|
68
|
+
if options[:frame] && options[:frame].rate_of_clock != 1.0
|
69
|
+
universal_time = options[:frame].time_standard.from_dynamical_time(
|
70
|
+
When::TimeStandard.to_dynamical_time(universal_time))
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
raise TypeError, "Can't create #{self} from #{time.class}" unless universal_time
|
76
|
+
universal_time(universal_time, options)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# この時間位置と関連付けられた時間参照系 (relation - Reference)
|
81
|
+
#
|
82
|
+
# The time reference system associated with the temporal position being described
|
83
|
+
#
|
84
|
+
# @return [When::TM::ReferenceSystem]
|
85
|
+
#
|
86
|
+
alias :clock :frame
|
87
|
+
|
88
|
+
# 内部時間による時間座標値
|
89
|
+
#
|
90
|
+
# @return [Numeric]
|
91
|
+
#
|
92
|
+
attr_accessor :universal_time
|
93
|
+
alias :coordinateValue :universal_time
|
94
|
+
protected :universal_time=
|
95
|
+
|
96
|
+
# 内部時間(ローカル)
|
97
|
+
#
|
98
|
+
# @return [Numeric]
|
99
|
+
#
|
100
|
+
# 1970-01-01T00:00:00(ローカル) からの Universal Coordinated Time の経過時間 / 128秒
|
101
|
+
#
|
102
|
+
def local_time
|
103
|
+
@universal_time
|
104
|
+
end
|
105
|
+
|
106
|
+
# CoordinateSystem による時間座標値
|
107
|
+
#
|
108
|
+
# @return [Numeric]
|
109
|
+
#
|
110
|
+
def coordinateValue
|
111
|
+
(universal_time - frame.origin.universal_time) / frame.interval.to_f
|
112
|
+
end
|
113
|
+
|
114
|
+
# 加算
|
115
|
+
#
|
116
|
+
# @param [Numeric, When::TM::IntervalLength] other
|
117
|
+
#
|
118
|
+
# @return [When::TM::TemporalPosition]
|
119
|
+
#
|
120
|
+
def +(other)
|
121
|
+
other = other.to_interval_length if other.kind_of?(PeriodDuration)
|
122
|
+
super(other)
|
123
|
+
end
|
124
|
+
|
125
|
+
# 減算
|
126
|
+
#
|
127
|
+
# @param [When::TM::TemporalPosition, Numeric, When::TM::IntervalLength] other
|
128
|
+
#
|
129
|
+
# @return [When::TM::TemporalPosition] if other is a Numeric or When::TM::IntervalLength
|
130
|
+
# @return [When::TM::IntervalLength] if other is a When::TM::TemporalPosition
|
131
|
+
#
|
132
|
+
def -(other)
|
133
|
+
other = other.to_interval_length if other.kind_of?(PeriodDuration)
|
134
|
+
super(other)
|
135
|
+
end
|
136
|
+
|
137
|
+
# 前の時刻
|
138
|
+
#
|
139
|
+
# @return [When::TM::TemporalPosition]
|
140
|
+
#
|
141
|
+
# 分解能に対応する Duration だけ,日時を戻す
|
142
|
+
#
|
143
|
+
def prev
|
144
|
+
self - period
|
145
|
+
end
|
146
|
+
|
147
|
+
# 次の時刻
|
148
|
+
#
|
149
|
+
# @return [When::TM::TemporalPosition]
|
150
|
+
#
|
151
|
+
# 分解能に対応する Duration だけ,日時を進める
|
152
|
+
#
|
153
|
+
def succ
|
154
|
+
self + period
|
155
|
+
end
|
156
|
+
alias :next :succ
|
157
|
+
|
158
|
+
# オブジェクトの生成
|
159
|
+
#
|
160
|
+
# @param [Numeric] universal_time 内部時間による時間座標値
|
161
|
+
#
|
162
|
+
# @param [Hash] options 下記の通り
|
163
|
+
# @option options [When::TM::CoordinateSystem] :frame
|
164
|
+
#
|
165
|
+
def initialize(universal_time, options={})
|
166
|
+
super(options)
|
167
|
+
@universal_time = universal_time
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
#
|
172
|
+
# ユリウス日
|
173
|
+
#
|
174
|
+
# see {http://schemas.opengis.net/gml/3.1.1/base/temporalAppendix.xsd#JulianDateType CALENdeRsign}
|
175
|
+
#
|
176
|
+
class JulianDate < Coordinate
|
177
|
+
|
178
|
+
# Julian Day Number
|
179
|
+
# 19700101T120000Z
|
180
|
+
JD19700101 = 2440588
|
181
|
+
|
182
|
+
# Modified Julian Date
|
183
|
+
#
|
184
|
+
# see {https://en.wikipedia.org/wiki/Julian_day#Variants MJD}
|
185
|
+
JDN_of_MJD = 2400000.5
|
186
|
+
|
187
|
+
# Countdown to Equinoctial Planetconjunction
|
188
|
+
#
|
189
|
+
# see {http://www.calendersign.com/en/cs_cep-pec.php CEP}
|
190
|
+
JDN_of_CEP = 2698162
|
191
|
+
|
192
|
+
class << self
|
193
|
+
|
194
|
+
JD19700100_5 = JD19700101 - 0.5
|
195
|
+
|
196
|
+
#
|
197
|
+
# 日時の内部表現をユリウス日に変換
|
198
|
+
#
|
199
|
+
# @param [Numeric] t
|
200
|
+
#
|
201
|
+
# @return [Numeric]
|
202
|
+
#
|
203
|
+
def _t_to_d(t)
|
204
|
+
t / Duration::DAY + JD19700100_5
|
205
|
+
end
|
206
|
+
|
207
|
+
#
|
208
|
+
# ユリウス日をに日時の内部表現変換
|
209
|
+
#
|
210
|
+
# @param [Numeric] d
|
211
|
+
#
|
212
|
+
# @return [Numeric]
|
213
|
+
#
|
214
|
+
def _d_to_t(d)
|
215
|
+
(d - JD19700100_5) * Duration::DAY
|
216
|
+
end
|
217
|
+
|
218
|
+
# Generation of Temporal Objetct
|
219
|
+
#
|
220
|
+
# @param [String] specification ユリウス通日を表す文字列
|
221
|
+
# @param [Hash] options 暦法や時法などの指定 (see {When::TM::TemporalPosition._instance})
|
222
|
+
#
|
223
|
+
# @return [When::TM::TemporalPosition, When::TM::Duration, When::Parts::GeometricComplex or Array<them>]
|
224
|
+
#
|
225
|
+
def parse(specification, options={})
|
226
|
+
num, *calendars = specification.split(/\^{1,2}/)
|
227
|
+
jdn = num.sub!(/[.@]/, '.') ? num.to_f : num.to_i
|
228
|
+
case num
|
229
|
+
when /MJD/i ; jdn += JDN_of_MJD
|
230
|
+
when /CEP/i ; jdn += JDN_of_CEP
|
231
|
+
when /DTB/i ; jdn = When.Resource('_t:UniversalTime').from_dynamical_date(jdn)
|
232
|
+
end
|
233
|
+
frame = calendars.shift || options[:frame]
|
234
|
+
return self.new(jdn, options) unless frame
|
235
|
+
calendars.unshift(frame).inject(jdn) {|date, calendar| When.Calendar(calendar).jul_trans(date, options)}
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
# 加算
|
240
|
+
#
|
241
|
+
# @param [Numeric, When::TM::IntervalLength] other
|
242
|
+
#
|
243
|
+
# @return [When::TM::TemporalPosition]
|
244
|
+
#
|
245
|
+
def +(other)
|
246
|
+
new_date = super
|
247
|
+
new_date.frame = new_date.frame._daylight(new_date.universal_time) if new_date.frame && new_date.frame._need_validate
|
248
|
+
return new_date
|
249
|
+
end
|
250
|
+
|
251
|
+
# 減算
|
252
|
+
#
|
253
|
+
# @param [When::TM::TemporalPosition, Numeric, When::TM::IntervalLength] other
|
254
|
+
#
|
255
|
+
# @return [When::TM::TemporalPosition]
|
256
|
+
#
|
257
|
+
def -(other)
|
258
|
+
new_date = super
|
259
|
+
new_date.frame = new_date.frame._daylight(new_date.universal_time) if new_date.kind_of?(TimeValue) && new_date.frame && new_date.frame._need_validate
|
260
|
+
return new_date
|
261
|
+
end
|
262
|
+
|
263
|
+
# ユリウス日が指定の剰余となる日
|
264
|
+
#
|
265
|
+
# @param [When::Coordinates::Residue] other
|
266
|
+
#
|
267
|
+
# @return [When::TM::TemporalPosition]
|
268
|
+
#
|
269
|
+
def &(other)
|
270
|
+
raise TypeError,"The right operand should be When::Coordinates::Residue" unless other.kind_of?(Residue)
|
271
|
+
raise ArgumentError,"The right operand should have a unit 'day'" unless other.event == 'day'
|
272
|
+
jdn = to_i
|
273
|
+
new_date = self.dup
|
274
|
+
new_date.universal_time += ((other & jdn) - jdn) * Duration::DAY
|
275
|
+
return new_date
|
276
|
+
end
|
277
|
+
|
278
|
+
# ユリウス日の剰余
|
279
|
+
#
|
280
|
+
# @param [When::Coordinates::Residue] other
|
281
|
+
#
|
282
|
+
# @return [Numeric]
|
283
|
+
#
|
284
|
+
def %(other)
|
285
|
+
raise TypeError,"The right operand should be When::Coordinates::Residue" unless other.kind_of?(Residue)
|
286
|
+
raise ArgumentError,"The right operand should have a unit 'day'" unless other.event == 'day'
|
287
|
+
other % to_i
|
288
|
+
end
|
289
|
+
|
290
|
+
private
|
291
|
+
|
292
|
+
# オブジェクトの生成
|
293
|
+
#
|
294
|
+
# @param [Numeric] universal_time 内部時間による時間座標値
|
295
|
+
#
|
296
|
+
# @param [Hash] options 以下の通り
|
297
|
+
# @option options [When::TM::Clock] :frame
|
298
|
+
# @option options [Integer] :precision
|
299
|
+
#
|
300
|
+
def initialize(universal_time, options={})
|
301
|
+
@frame = options.delete(:frame)
|
302
|
+
@frame = When.Clock(@frame) if @frame.kind_of?(String)
|
303
|
+
@frame = @frame._daylight(universal_time) if @frame && @frame._need_validate
|
304
|
+
precision = options.delete(:precision)
|
305
|
+
precision ||= DAY unless @frame.kind_of?(Clock)
|
306
|
+
@precision = Index.precision(precision)
|
307
|
+
super
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
#
|
312
|
+
# 順序時間参照系で参照する位置
|
313
|
+
#
|
314
|
+
# see {http://schemas.opengis.net/gml/3.1.1/base/temporalAppendix.xsd#TimeOrdinalPositionType gml schema}
|
315
|
+
#
|
316
|
+
class OrdinalPosition < TemporalPosition
|
317
|
+
|
318
|
+
# この順序位置と関連付けられた順序年代 (relation - Reference)
|
319
|
+
#
|
320
|
+
# The ordinal era associated with the ordinal position being described
|
321
|
+
#
|
322
|
+
# @return [When::TM::OrdinalEra]
|
323
|
+
#
|
324
|
+
attr_reader :ordinal_position
|
325
|
+
alias :ordinalPosition :ordinal_position
|
326
|
+
|
327
|
+
# オブジェクトの生成
|
328
|
+
#
|
329
|
+
# @param [When::TM::OrdinalEra] ordinal_position この順序位置と関連付けられた順序年代
|
330
|
+
# @param [Hash] options see {When::TM::TemporalPosition._instance}
|
331
|
+
#
|
332
|
+
def initialize(ordinal_position, options={})
|
333
|
+
super(options)
|
334
|
+
@ordinal_position = ordinal_position
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
338
|
+
#
|
339
|
+
# 時刻
|
340
|
+
#
|
341
|
+
# see {http://schemas.opengis.net/gml/3.1.1/base/temporalAppendix.xsd#ClockTimeType gml schema}
|
342
|
+
#
|
343
|
+
class ClockTime < TemporalPosition
|
344
|
+
|
345
|
+
# 時刻要素
|
346
|
+
#
|
347
|
+
# @return [Array<Numeric>]
|
348
|
+
#
|
349
|
+
# @note ISO19108 では sequence<Integer> だが、閏時・閏秒などが表現可能なよう Numeric としている。
|
350
|
+
#
|
351
|
+
attr_reader :clk_time
|
352
|
+
alias :clkTime :clk_time
|
353
|
+
|
354
|
+
# この時間位置と関連付けられた時間参照系 (relation - Reference)
|
355
|
+
#
|
356
|
+
# The time reference system associated with the temporal position being described
|
357
|
+
#
|
358
|
+
# @return [When::TM::ReferenceSystem]
|
359
|
+
#
|
360
|
+
alias :clock :frame
|
361
|
+
|
362
|
+
# 内部時間
|
363
|
+
#
|
364
|
+
# @param [Integer] sdn 参照事象の通し番号
|
365
|
+
#
|
366
|
+
# @return [Numeric]
|
367
|
+
#
|
368
|
+
# T00:00:00Z からの Universal Coordinated Time の経過時間 / 128秒
|
369
|
+
#
|
370
|
+
# 時法によっては、異なる意味を持つことがある
|
371
|
+
#
|
372
|
+
def universal_time(sdn=nil)
|
373
|
+
raise NameError, "Temporal Reference System is not defined" unless @frame
|
374
|
+
@universal_time ||= @frame.to_universal_time(@clk_time, sdn)
|
375
|
+
end
|
376
|
+
|
377
|
+
# 内部時間(ローカル)
|
378
|
+
#
|
379
|
+
# @param [Integer] sdn 参照事象の通し番号
|
380
|
+
#
|
381
|
+
# @return [Numeric]
|
382
|
+
#
|
383
|
+
# T00:00:00(ローカル) からの Universal Coordinated Time の経過時間 / 128秒
|
384
|
+
#
|
385
|
+
# 時法によっては、異なる意味を持つことがある
|
386
|
+
#
|
387
|
+
def local_time(sdn=nil)
|
388
|
+
raise NameError, "Temporal Reference System is not defined" unless @frame
|
389
|
+
@local_time ||= @frame.to_local_time(@clk_time, sdn)
|
390
|
+
end
|
391
|
+
|
392
|
+
# 繰り上がり
|
393
|
+
#
|
394
|
+
# @return [Numeric]
|
395
|
+
#
|
396
|
+
# 日付の境界が午前0時でない場合、clk_time の最上位桁に 0 以外が入ることがある
|
397
|
+
#
|
398
|
+
def carry
|
399
|
+
return @clk_time[0]
|
400
|
+
end
|
401
|
+
|
402
|
+
# 要素の参照
|
403
|
+
#
|
404
|
+
# @param [Integer, String] index 参照する要素の指定
|
405
|
+
#
|
406
|
+
# @return [Numeric]
|
407
|
+
#
|
408
|
+
def value(index)
|
409
|
+
@clk_time[_digit(index) {|digit| digit >= DAY}]
|
410
|
+
end
|
411
|
+
|
412
|
+
#protected
|
413
|
+
# 属性のコピー
|
414
|
+
# @private
|
415
|
+
def _copy(options={})
|
416
|
+
@clk_time = options[:time] if options.key?(:time)
|
417
|
+
if options.key?(:clock)
|
418
|
+
options.delete(:frame)
|
419
|
+
@frame = options[:clock]
|
420
|
+
end
|
421
|
+
if options.key?(:tz_prop)
|
422
|
+
@frame = @frame.dup
|
423
|
+
@frame.tz_prop = options[:tz_prop]
|
424
|
+
end
|
425
|
+
return super
|
426
|
+
end
|
427
|
+
|
428
|
+
# オブジェクトの生成
|
429
|
+
#
|
430
|
+
# @param [String] time ISO8601形式の時刻表現
|
431
|
+
# @param [Array<Numeric>] time (日, 時, 分, 秒)
|
432
|
+
#
|
433
|
+
#
|
434
|
+
# @param [Hash] options 以下の通り
|
435
|
+
# @option options [When::TM::Clock] :frame
|
436
|
+
# @option options [Integer] :precision
|
437
|
+
#
|
438
|
+
def initialize(time, options={})
|
439
|
+
# 参照系の取得
|
440
|
+
@frame = options[:frame] || Clock.local_time
|
441
|
+
@frame = When.Clock(@frame) if (@frame.kind_of?(String))
|
442
|
+
options.delete(:frame)
|
443
|
+
|
444
|
+
# 時刻表現の解読 ( Time Zone の解釈 )
|
445
|
+
if (time.kind_of?(String))
|
446
|
+
case time
|
447
|
+
when /\A([-+])?(\d{2,}?):?(\d{2})?:?(\d{2}(\.\d+)?)?\z/
|
448
|
+
sign, hh, mm, ss = $~[1..4]
|
449
|
+
time = @frame._validate([0,0,0,0],
|
450
|
+
[0,
|
451
|
+
-(sign.to_s + "0" + hh.to_s).to_i,
|
452
|
+
-(sign.to_s + "0" + mm.to_s).to_i,
|
453
|
+
Pair._en_number(-(sign.to_s + "0" + ss.to_s).to_f)])
|
454
|
+
time[0] = Pair.new(0, time[0].to_i) if (time[0] != 0)
|
455
|
+
when /\AZ\z/
|
456
|
+
time = [0,0,0,0]
|
457
|
+
else
|
458
|
+
raise ArgumentError, "Invalid Time Format"
|
459
|
+
end
|
460
|
+
end
|
461
|
+
@clk_time = time
|
462
|
+
|
463
|
+
# 分解能
|
464
|
+
@precision = @frame._precision(time, options.delete(:precision))
|
465
|
+
|
466
|
+
super(options)
|
467
|
+
end
|
468
|
+
|
469
|
+
private
|
470
|
+
|
471
|
+
# オブジェクトの正規化
|
472
|
+
def _normalize(options={})
|
473
|
+
# strftime で使用する locale
|
474
|
+
@keys |= @frame.keys
|
475
|
+
|
476
|
+
# 時刻の正規化
|
477
|
+
@clk_time = @frame._validate(@clk_time) unless options[:validate]
|
478
|
+
end
|
479
|
+
|
480
|
+
# 加減算共通処理
|
481
|
+
def _plus(period)
|
482
|
+
self.dup._copy({:time=>@frame._validate(@clk_time, @frame._arrange_length(period.time)),
|
483
|
+
:events=>nil, :query=>nil, :validate=>:done})
|
484
|
+
end
|
485
|
+
end
|
486
|
+
|
487
|
+
#
|
488
|
+
# 暦日
|
489
|
+
#
|
490
|
+
# see {gml schema}[link:http://schemas.opengis.net/gml/3.1.1/base/temporalAppendix.xsd#CalDateType]
|
491
|
+
#
|
492
|
+
class CalDate < TemporalPosition
|
493
|
+
|
494
|
+
# 検索オプション
|
495
|
+
# @private
|
496
|
+
SearchOption = {After=>[0, -2, Before], Before=>[-2, 0, After]}
|
497
|
+
|
498
|
+
# 日付要素
|
499
|
+
#
|
500
|
+
# @return [Array<Numeric>]
|
501
|
+
#
|
502
|
+
# @note ISO19108 では sequence<Integer> だが、閏月などが表現可能なよう Numeric としている。
|
503
|
+
#
|
504
|
+
attr_reader :cal_date
|
505
|
+
alias :calDate :cal_date
|
506
|
+
|
507
|
+
# この時間位置と関連付けられた時間参照系 (relation - Reference)
|
508
|
+
#
|
509
|
+
# The time reference system associated with the temporal position being described
|
510
|
+
#
|
511
|
+
# @return [When::TM::ReferenceSystem]
|
512
|
+
#
|
513
|
+
alias :calendar :frame
|
514
|
+
|
515
|
+
# 暦年代
|
516
|
+
#
|
517
|
+
# @return [When::TM::CalendarEra]
|
518
|
+
#
|
519
|
+
attr_accessor :calendar_era
|
520
|
+
private :calendar_era=
|
521
|
+
alias :calendarEra :calendar_era
|
522
|
+
|
523
|
+
# 暦年代属性
|
524
|
+
#
|
525
|
+
# @return [Array] ( name, epoch, reverse, go back )
|
526
|
+
# - name [String] 暦年代名
|
527
|
+
# - epoch [Integer] 使用する When::TM::Calendar で暦元に対応する年
|
528
|
+
# - reverse [Boolean] 年数が昇順(false,nil)か降順(true)か
|
529
|
+
# - go back [Boolean] 参照イベントより前の暦日か(true)、否か(false,nil)
|
530
|
+
#
|
531
|
+
attr_accessor :calendar_era_props
|
532
|
+
private :calendar_era_props=
|
533
|
+
|
534
|
+
# 暦年代名
|
535
|
+
#
|
536
|
+
# @return [String] 暦年代名
|
537
|
+
#
|
538
|
+
def calendar_era_name
|
539
|
+
@calendar_era_props ? @calendar_era_props[0] : nil
|
540
|
+
end
|
541
|
+
alias :calendarEraName :calendar_era_name
|
542
|
+
|
543
|
+
# 暦年代元期
|
544
|
+
#
|
545
|
+
# @return [Integer] 使用する When::TM::Calendar で暦元に対応する年
|
546
|
+
#
|
547
|
+
def calendar_era_epoch
|
548
|
+
@calendar_era_props ? @calendar_era_props[1] : 0
|
549
|
+
end
|
550
|
+
|
551
|
+
# 暦年代正逆
|
552
|
+
#
|
553
|
+
# @return [Boolean] 年数が昇順(false,nil)か降順(true)か
|
554
|
+
#
|
555
|
+
def calendar_era_reverse
|
556
|
+
@calendar_era_props ? @calendar_era_props[2] : false
|
557
|
+
end
|
558
|
+
|
559
|
+
# 暦年代遡及
|
560
|
+
#
|
561
|
+
# @return [Boolean] 参照イベントより前の暦日か(true)、否か(false,nil)
|
562
|
+
#
|
563
|
+
def calendar_era_go_back
|
564
|
+
@calendar_era_props ? @calendar_era_props[3] : false
|
565
|
+
end
|
566
|
+
|
567
|
+
# 時法の取得 - ダミー
|
568
|
+
def clock
|
569
|
+
nil
|
570
|
+
end
|
571
|
+
|
572
|
+
# 内部時間
|
573
|
+
#
|
574
|
+
# @return [Numeric]
|
575
|
+
#
|
576
|
+
# 当日正午の 1970-01-01T00:00:00Z からの Universal Coordinated Time の経過時間 / 128秒
|
577
|
+
#
|
578
|
+
def universal_time
|
579
|
+
return super if [Now, Max, Min].include?(@indeterminated_position)
|
580
|
+
@universal_time ||= JulianDate._d_to_t(to_i)
|
581
|
+
end
|
582
|
+
alias :local_time :universal_time
|
583
|
+
|
584
|
+
# ユリウス日
|
585
|
+
#
|
586
|
+
# @return [Integer]
|
587
|
+
#
|
588
|
+
# -4712-01-01からの経過日数に対応する通番
|
589
|
+
#
|
590
|
+
def to_i
|
591
|
+
@sdn ||= _to_i
|
592
|
+
end
|
593
|
+
|
594
|
+
#
|
595
|
+
# 暦法上の通日
|
596
|
+
#
|
597
|
+
def _to_i
|
598
|
+
void, epoch = @calendar_era_props
|
599
|
+
if epoch
|
600
|
+
date = @cal_date.dup
|
601
|
+
date[0] += epoch
|
602
|
+
else
|
603
|
+
date = @cal_date
|
604
|
+
end
|
605
|
+
@frame.to_julian_date(date)
|
606
|
+
end
|
607
|
+
private :_to_i
|
608
|
+
|
609
|
+
# 前の日時
|
610
|
+
#
|
611
|
+
# @return [When::TM::TemporalPosition]
|
612
|
+
#
|
613
|
+
# 分解能に対応する Duration だけ,日時を戻す
|
614
|
+
#
|
615
|
+
def prev
|
616
|
+
@precision==When::DAY ? _force_euqal_day(-1) : self-period
|
617
|
+
rescue RangeError
|
618
|
+
(When::Gregorian ^ self) - period
|
619
|
+
end
|
620
|
+
|
621
|
+
# 次の日時
|
622
|
+
#
|
623
|
+
# @return [When::TM::TemporalPosition]
|
624
|
+
#
|
625
|
+
# 分解能に対応する Duration だけ,日時を進める
|
626
|
+
#
|
627
|
+
def succ
|
628
|
+
@precision==When::DAY ? _force_euqal_day(+1) : self+period
|
629
|
+
rescue RangeError
|
630
|
+
(When::Gregorian ^ self) + period
|
631
|
+
end
|
632
|
+
alias :next :succ
|
633
|
+
|
634
|
+
# 剰余類化
|
635
|
+
#
|
636
|
+
# @param [Numeric] remainder 剰余
|
637
|
+
# @param [Integer] divisor 法(>0)
|
638
|
+
#
|
639
|
+
# @return [When::Coordinates::Residue] 当日、当年を基準とする剰余類
|
640
|
+
#
|
641
|
+
def to_residue(remainder, divisor)
|
642
|
+
When::Coordinates::Residue.new(remainder, divisor, {'day' => least_significant_coordinate,
|
643
|
+
'year' => most_significant_coordinate})
|
644
|
+
end
|
645
|
+
|
646
|
+
# 暦年代の削除
|
647
|
+
#
|
648
|
+
# @return [When::TM::CalDate] 暦年代を削除した When::TM::CalDate
|
649
|
+
#
|
650
|
+
def without_era
|
651
|
+
target = dup
|
652
|
+
return target unless calendar_era
|
653
|
+
options = _attr
|
654
|
+
options[:era] = nil
|
655
|
+
options[:era_name] = nil
|
656
|
+
options[:date] = cal_date.dup
|
657
|
+
options[:date][0] += calendar_era_epoch
|
658
|
+
target._copy(options)
|
659
|
+
end
|
660
|
+
|
661
|
+
# 要素の参照
|
662
|
+
#
|
663
|
+
# @param [Integer, String] index 参照する要素の指定
|
664
|
+
#
|
665
|
+
# @return [Numeric]
|
666
|
+
#
|
667
|
+
def value(index)
|
668
|
+
@cal_date[(_digit(index) {|digit| digit <= DAY})-1]
|
669
|
+
end
|
670
|
+
|
671
|
+
#
|
672
|
+
# 最上位の要素
|
673
|
+
#
|
674
|
+
# @return [Numeric] 暦年代の epoch に関わらず暦法に従った年の通し番号を返す
|
675
|
+
#
|
676
|
+
def most_significant_coordinate
|
677
|
+
coordinate = @cal_date[0]
|
678
|
+
coordinate += calendar_era_epoch if @calendar_era_props
|
679
|
+
@frame.index_of_MSC.times do |i|
|
680
|
+
coordinate = +coordinate * @frame.indices[i].unit + @cal_date[i+1] - @frame.indices[i].base
|
681
|
+
end
|
682
|
+
coordinate
|
683
|
+
end
|
684
|
+
|
685
|
+
#
|
686
|
+
# 最下位の要素
|
687
|
+
#
|
688
|
+
# @return [Numeric] 剰余類の演算に用いる日の通し番号を返す
|
689
|
+
#
|
690
|
+
def least_significant_coordinate
|
691
|
+
return to_i + @frame.indices[-1].shift
|
692
|
+
end
|
693
|
+
|
694
|
+
# ユリウス日または通年が指定の剰余となる日
|
695
|
+
#
|
696
|
+
# @param [When::Coordinates::Residue] other
|
697
|
+
#
|
698
|
+
# @return [When::TM::CalDate]
|
699
|
+
#
|
700
|
+
def &(other)
|
701
|
+
raise TypeError,"The right operand should be When::Coordinates::Residue" unless other.kind_of?(Residue)
|
702
|
+
case other.event
|
703
|
+
when 'day'
|
704
|
+
# 指定の剰余となる日
|
705
|
+
sdn = other & to_i
|
706
|
+
options = {:date=>_date_with_era(@frame.to_cal_date(sdn)), :events=>nil, :query=>@query, :validate=>:done}
|
707
|
+
options[:precision] = When::DAY if precision < When::DAY
|
708
|
+
result = self.dup._copy(options)
|
709
|
+
result.send(:_force_euqal_day, sdn-result.to_i)
|
710
|
+
|
711
|
+
when 'year'
|
712
|
+
# 指定の剰余となる年
|
713
|
+
date = @frame.send(:_decode, _date_without_era)
|
714
|
+
date[0] = (other & (date[0] + @frame.diff_to_CE)) - @frame.diff_to_CE
|
715
|
+
options = {:date=>_date_with_era(@frame.send(:_encode, date)), :events=>nil, :query=>@query}
|
716
|
+
options[:precision] = When::YEAR if precision < When::YEAR
|
717
|
+
return self.dup._copy(options)
|
718
|
+
|
719
|
+
else
|
720
|
+
raise ArgumentError,"The right operand should have a unit 'day' or 'year'"
|
721
|
+
end
|
722
|
+
end
|
723
|
+
|
724
|
+
# ユリウス日または通年の剰余
|
725
|
+
#
|
726
|
+
# @param [When::Coordinates::Residue] other
|
727
|
+
#
|
728
|
+
# @return [Numeric]
|
729
|
+
#
|
730
|
+
def %(other)
|
731
|
+
raise TypeError,"The right operand should be When::Coordinates::Residue" unless other.kind_of?(Residue)
|
732
|
+
if precision <= When::YEAR && other.units['year'] && other.event != 'year'
|
733
|
+
other.to('year') % (most_significant_coordinate + @frame.epoch_in_CE)
|
734
|
+
else
|
735
|
+
case other.event
|
736
|
+
when 'day' ; other % least_significant_coordinate
|
737
|
+
when 'year' ; other % (most_significant_coordinate + @frame.epoch_in_CE)
|
738
|
+
else ; raise ArgumentError,"The right operand should have a unit 'day' or 'year'"
|
739
|
+
end
|
740
|
+
end
|
741
|
+
end
|
742
|
+
|
743
|
+
# 下位桁の切り捨て
|
744
|
+
#
|
745
|
+
# @param [Integer] digit 切り捨てずに残す、最下位の桁
|
746
|
+
#
|
747
|
+
# @param [Integer] precision 切り捨て結果の分解能
|
748
|
+
#
|
749
|
+
# @return [When::TM::CalDate]
|
750
|
+
#
|
751
|
+
def floor(digit=DAY, precision=digit)
|
752
|
+
options = {:date=>@cal_date[0..(digit-1)], :events=>nil, :query=>nil}
|
753
|
+
options[:precision] = precision if precision
|
754
|
+
self.dup._copy(options)
|
755
|
+
end
|
756
|
+
|
757
|
+
# 下位桁の切り上げ
|
758
|
+
#
|
759
|
+
# @param [Integer] digit 切り上げずに残す、最下位の桁
|
760
|
+
#
|
761
|
+
# @param [Integer] precision 切り上げ結果の分解能
|
762
|
+
#
|
763
|
+
# @return [When::TM::CalDate]
|
764
|
+
#
|
765
|
+
def ceil(digit=DAY, precision=digit)
|
766
|
+
(self + PeriodDuration.new(1, digit, (-@frame.indices.length)..0)).floor(digit, precision)
|
767
|
+
end
|
768
|
+
|
769
|
+
# 要素数 ― 上位要素に含まれる下位要素の数
|
770
|
+
#
|
771
|
+
# @param [Integer] upper 上位要素のインデックス
|
772
|
+
# @param [Integer] lower 下位要素のインデックス(DAY または MONTH)
|
773
|
+
#
|
774
|
+
# @return [Integer]
|
775
|
+
#
|
776
|
+
def length(upper, lower=DAY)
|
777
|
+
range = [floor(upper).to_i, ceil(upper).to_i]
|
778
|
+
range = range.map {|d| (Residue.mod(d) {|m| frame._new_month(m)})[0]} if lower == MONTH
|
779
|
+
range[1] - range[0]
|
780
|
+
end
|
781
|
+
|
782
|
+
# 時刻情報のない When::TM::CalDate を返す
|
783
|
+
#
|
784
|
+
# @return [When::TM::CalDate]
|
785
|
+
#
|
786
|
+
alias :to_cal_date :dup
|
787
|
+
alias :to_CalDate :to_cal_date
|
788
|
+
|
789
|
+
# 暦年代が末端の参照であるか?
|
790
|
+
#
|
791
|
+
# @return [Boolean]
|
792
|
+
#
|
793
|
+
def leaf?
|
794
|
+
! @calendar_era.respond_to?(:_pool) || @calendar_era.leaf?
|
795
|
+
end
|
796
|
+
|
797
|
+
# 属性の Hash
|
798
|
+
# @private
|
799
|
+
def _attr
|
800
|
+
super.merge({:era_name=>@calendar_era_props, :era=>@calendar_era})
|
801
|
+
end
|
802
|
+
protected
|
803
|
+
|
804
|
+
# 属性のコピー
|
805
|
+
# @private
|
806
|
+
def _copy(options={})
|
807
|
+
@cal_date = options[:date] if options.key?(:date)
|
808
|
+
@calendar_era = options[:era] if options.key?(:era)
|
809
|
+
@calendar_era_props = options[:era_name] if options.key?(:era_name)
|
810
|
+
return super
|
811
|
+
end
|
812
|
+
|
813
|
+
# オブジェクトの生成
|
814
|
+
#
|
815
|
+
# @param [Array<Numeric>] date 日付表現
|
816
|
+
#
|
817
|
+
# @param [Hash] options 下記の通り (see also {When::TM::TemporalPosition._instance})
|
818
|
+
# @option options [When::TM::Calendar] :frame
|
819
|
+
# @option options [When::TM::CalendarEra, When::BasicTypes::M17n, Array<When::BasicTypes::M17n, Integer>] :era_name
|
820
|
+
# (Integer は 当該年号の 0 年に相当する通年)
|
821
|
+
# @option options [Integer] :precision
|
822
|
+
#
|
823
|
+
def initialize(date, options={})
|
824
|
+
# 年号 & 日付
|
825
|
+
@calendar_era_props = options[:era_name]
|
826
|
+
@calendar_era = options[:era]
|
827
|
+
@cal_date = date
|
828
|
+
|
829
|
+
super(options)
|
830
|
+
end
|
831
|
+
|
832
|
+
private
|
833
|
+
|
834
|
+
# オブジェクトの正規化
|
835
|
+
def _normalize(options={})
|
836
|
+
|
837
|
+
# 日付配列の長さ
|
838
|
+
cal_date_index = @cal_date.compact.length
|
839
|
+
|
840
|
+
# 日付の正規化
|
841
|
+
if @calendar_era_props
|
842
|
+
# Calendar Era がある場合
|
843
|
+
trans_options = @trans || {} # TODO? 消す
|
844
|
+
count = trans_options[:count] || 1
|
845
|
+
query_options = (@query || {}).dup
|
846
|
+
query_options[:label] = @calendar_era_props
|
847
|
+
query_options[:count] = count
|
848
|
+
era = date = nil
|
849
|
+
if @calendar_era
|
850
|
+
era, date = _search_era(@calendar_era, trans_options)
|
851
|
+
else
|
852
|
+
eras = CalendarEra._instance(query_options)
|
853
|
+
raise ArgumentError, "CalendarEraName doesn't exist: #{query_options[:label]}" if eras.empty?
|
854
|
+
eras.each do |e|
|
855
|
+
era, date = _search_era(e, trans_options)
|
856
|
+
next unless era
|
857
|
+
count -= 1
|
858
|
+
break unless count > 0
|
859
|
+
end
|
860
|
+
end
|
861
|
+
raise RangeError, "Out of CalendarEra Range" unless era
|
862
|
+
@calendar_era_props = date.calendar_era_props
|
863
|
+
@calendar_era = era
|
864
|
+
@cal_date = date.cal_date
|
865
|
+
@frame = date.frame
|
866
|
+
@query = (@query||{}).merge(date.query)
|
867
|
+
@trans = (@trans||{}).merge(date.trans)
|
868
|
+
@keys |= calendar_era_name.keys | @frame.keys
|
869
|
+
else
|
870
|
+
# Calendar Era がない場合
|
871
|
+
@frame = When.Resource(options[:frame] || @frame || 'Gregorian', '_c:')
|
872
|
+
@cal_date = @frame._validate(@cal_date) unless options[:validate] == :done
|
873
|
+
@keys |= @frame.keys
|
874
|
+
end
|
875
|
+
|
876
|
+
# 分解能
|
877
|
+
precision = options.delete(:precision) || @precision
|
878
|
+
cal_date_index =
|
879
|
+
case options.delete(:_format)
|
880
|
+
when :century ; CENTURY
|
881
|
+
when :week, :day ; DAY
|
882
|
+
else ; cal_date_index - (@frame.indices.length + 1)
|
883
|
+
end
|
884
|
+
precision ||= cal_date_index if cal_date_index < DAY
|
885
|
+
precision ||= @clk_time.precision if @clk_time
|
886
|
+
@precision = Index.precision(precision || DAY)
|
887
|
+
end
|
888
|
+
|
889
|
+
# 暦年代を探す
|
890
|
+
def _search_era(era, trans_options)
|
891
|
+
cal_date = @cal_date.dup
|
892
|
+
cal_date[0] = -cal_date[0] if era.reverse?
|
893
|
+
cal_date[0] += era.epoch_year
|
894
|
+
date = era.trans(cal_date, trans_options)
|
895
|
+
loop do
|
896
|
+
case date
|
897
|
+
when Before, After
|
898
|
+
i0, i1, reverse = SearchOption[date]
|
899
|
+
new_era = (date == Before) ? era.prev : era.succ
|
900
|
+
break unless new_era
|
901
|
+
date = new_era.trans(cal_date, trans_options)
|
902
|
+
if date == reverse
|
903
|
+
cal_date = new_era.epoch[i0].frame.to_cal_date(era.epoch[i1].frame.to_julian_date(cal_date))
|
904
|
+
date = new_era.trans(cal_date, trans_options)
|
905
|
+
break if date == reverse
|
906
|
+
end
|
907
|
+
era = new_era
|
908
|
+
when TimeValue
|
909
|
+
return era, date
|
910
|
+
else
|
911
|
+
break
|
912
|
+
end
|
913
|
+
end
|
914
|
+
return nil
|
915
|
+
end
|
916
|
+
|
917
|
+
# 加減算共通処理
|
918
|
+
def _plus(period)
|
919
|
+
_frame_adjust(period, self.dup._copy({:date=>_date_with_era(@frame._validate(_date_without_era,
|
920
|
+
@frame._arrange_length(period.date))),
|
921
|
+
:events=>nil, :query=>nil, :validate=>:done}))
|
922
|
+
end
|
923
|
+
|
924
|
+
# 年号を除外した @frame の暦法に対応する日付
|
925
|
+
def _date_without_era
|
926
|
+
date = @cal_date.dup
|
927
|
+
date[0] += calendar_era_epoch if @calendar_era_props
|
928
|
+
date
|
929
|
+
end
|
930
|
+
|
931
|
+
# 年号に続く日付
|
932
|
+
def _date_with_era(date)
|
933
|
+
date[0] -= calendar_era_epoch if @calendar_era_props
|
934
|
+
date
|
935
|
+
end
|
936
|
+
|
937
|
+
# 暦法が変わった場合の補正
|
938
|
+
def _frame_adjust(period, date)
|
939
|
+
return date if @frame.equal?(date.frame) || (period.to_day||0) == 0
|
940
|
+
diff = period.to_day - (date.to_i - to_i)
|
941
|
+
return date if diff == 0
|
942
|
+
date.send(:_force_euqal_day, diff)
|
943
|
+
end
|
944
|
+
end
|
945
|
+
|
946
|
+
#
|
947
|
+
# 時刻を伴った日付
|
948
|
+
#
|
949
|
+
# see {http://schemas.opengis.net/gml/3.1.1/base/temporalAppendix.xsd#DateAndTimeType gml schema}
|
950
|
+
#
|
951
|
+
class DateAndTime < CalDate
|
952
|
+
|
953
|
+
# 時刻要素
|
954
|
+
#
|
955
|
+
# @return [When::TM::ClockTime]
|
956
|
+
#
|
957
|
+
attr_reader :clk_time
|
958
|
+
alias :clkTime :clk_time
|
959
|
+
|
960
|
+
# 時法の取得
|
961
|
+
#
|
962
|
+
# @return [When::TM::Clock]
|
963
|
+
#
|
964
|
+
def clock
|
965
|
+
@clk_time.frame
|
966
|
+
end
|
967
|
+
|
968
|
+
# 内部時間
|
969
|
+
#
|
970
|
+
# @return [Numeric]
|
971
|
+
#
|
972
|
+
# 1970-01-01T00:00:00Z からの Universal Coordinated Time の経過時間 / 128秒
|
973
|
+
#
|
974
|
+
# 暦法によっては、異なる意味を持つことがある
|
975
|
+
#
|
976
|
+
def universal_time
|
977
|
+
return super if [Now, Max, Min].include?(@indeterminated_position)
|
978
|
+
raise NameError, "Temporal Reference System is not defined" unless (@frame && clock)
|
979
|
+
@universal_time ||= (to_i - JulianDate::JD19700101) * Duration::DAY + @clk_time.universal_time(to_i)
|
980
|
+
end
|
981
|
+
|
982
|
+
# 内部時間(ローカル)
|
983
|
+
#
|
984
|
+
# @return [Numeric]
|
985
|
+
#
|
986
|
+
# 1970-01-01T00:00:00(ローカル) からの Universal Coordinated Time の経過時間 / 128秒
|
987
|
+
#
|
988
|
+
# 暦法によっては、異なる意味を持つことがある
|
989
|
+
#
|
990
|
+
def local_time
|
991
|
+
return super if [Now, Max, Min].include?(@indeterminated_position)
|
992
|
+
raise NameError, "Temporal Reference System is not defined" unless (@frame && clock)
|
993
|
+
@local_time ||= (to_i - JulianDate::JD19700101) * Duration::DAY + @clk_time.local_time(to_i)
|
994
|
+
end
|
995
|
+
|
996
|
+
# 要素の参照
|
997
|
+
#
|
998
|
+
# @param [Integer] index 参照する要素の指定
|
999
|
+
#
|
1000
|
+
# @return [Numeric]
|
1001
|
+
#
|
1002
|
+
def value(index)
|
1003
|
+
digit = _digit(index)
|
1004
|
+
return (digit <= DAY) ? @cal_date[digit-1] : @clk_time.clk_time[digit]
|
1005
|
+
end
|
1006
|
+
|
1007
|
+
# ユリウス日または通年が指定の剰余となる日
|
1008
|
+
#
|
1009
|
+
# @param [When::Coordinates::Residue] other
|
1010
|
+
#
|
1011
|
+
# @return [When::TM::DateAndTime]
|
1012
|
+
#
|
1013
|
+
def &(other)
|
1014
|
+
raise TypeError,"The right operand should be When::Coordinates::Residue" unless other.kind_of?(Residue)
|
1015
|
+
case other.event
|
1016
|
+
when 'day'
|
1017
|
+
# 指定の剰余となる日
|
1018
|
+
sdn = other & to_i
|
1019
|
+
options = {:date=>_date_with_era(@frame.to_cal_date(sdn)), :time=>@clk_time.clk_time.dup,
|
1020
|
+
:events=>nil, :query=>@query, :validate=>:done}
|
1021
|
+
options[:precision] = When::DAY if precision < When::DAY
|
1022
|
+
result = self.dup._copy(options)
|
1023
|
+
result.send(:_force_euqal_day, sdn-result.to_i)
|
1024
|
+
|
1025
|
+
when 'year'
|
1026
|
+
# 指定の剰余となる年
|
1027
|
+
date = @frame.send(:_decode, _date_without_era)
|
1028
|
+
date[0] = (other & (date[0] + @frame.diff_to_CE)) - @frame.diff_to_CE
|
1029
|
+
options = {:date=>_date_with_era(@frame.send(:_encode, date)), :time=>@clk_time.clk_time.dup,
|
1030
|
+
:events=>nil, :query=>@query}
|
1031
|
+
options[:precision] = When::YEAR if precision < When::YEAR
|
1032
|
+
return self.dup._copy(options)
|
1033
|
+
|
1034
|
+
else
|
1035
|
+
raise ArgumentError,"The right operand should have a unit 'day' or 'year'"
|
1036
|
+
end
|
1037
|
+
end
|
1038
|
+
|
1039
|
+
# 下位桁の切り捨て
|
1040
|
+
#
|
1041
|
+
# @param [Integer] digit 切り捨てずに残す、最下位の桁
|
1042
|
+
#
|
1043
|
+
# @param [Integer] precision 切り捨て結果の分解能
|
1044
|
+
#
|
1045
|
+
# @return [When::TM::DateAndTime]
|
1046
|
+
#
|
1047
|
+
def floor(digit=DAY, precision=digit)
|
1048
|
+
count = digit - clock.indices.length
|
1049
|
+
|
1050
|
+
if digit>=DAY
|
1051
|
+
date = @cal_date.dup
|
1052
|
+
elsif @calendar_era_props
|
1053
|
+
date = @cal_date.dup
|
1054
|
+
date[0] += calendar_era_epoch
|
1055
|
+
date = @frame._validate(date[0..(digit-1)])
|
1056
|
+
date[0] -= calendar_era_epoch
|
1057
|
+
else
|
1058
|
+
date = @frame._validate(@cal_date[0..(digit-1)])
|
1059
|
+
end
|
1060
|
+
|
1061
|
+
time = @clk_time.clk_time[0..((digit<=DAY) ? 0 : ((count>=0) ? -1 : digit))]
|
1062
|
+
time[0] += to_i
|
1063
|
+
time = clock._validate(time)
|
1064
|
+
time[0] -= to_i
|
1065
|
+
|
1066
|
+
if (count >= 0)
|
1067
|
+
factor = 10**count
|
1068
|
+
time[-1] = (time[-1] * factor).floor.to_f / factor
|
1069
|
+
end
|
1070
|
+
|
1071
|
+
# オブジェクトの生成
|
1072
|
+
options = {:date=>date, :validate=>:done, :events=>nil, :query=>nil,
|
1073
|
+
:time=>(digit<=DAY) ? time : @clk_time.dup._copy({:time=>time})}
|
1074
|
+
options[:precision] = precision if precision
|
1075
|
+
return self.dup._copy(options)
|
1076
|
+
end
|
1077
|
+
|
1078
|
+
# 下位桁の切り上げ
|
1079
|
+
#
|
1080
|
+
# @param [Integer] digit 切り上げずに残す、最下位の桁
|
1081
|
+
#
|
1082
|
+
# @param [Integer] precision 切り上げ結果の分解能
|
1083
|
+
#
|
1084
|
+
# @return [When::TM::DateAndTime]
|
1085
|
+
#
|
1086
|
+
def ceil(digit=DAY, precision=digit)
|
1087
|
+
length = clock.indices.length
|
1088
|
+
count = digit - length
|
1089
|
+
period = PeriodDuration.new((count<=0) ? 1 : 0.1**count, digit, (-@frame.indices.length)..length)
|
1090
|
+
result = floor(digit, precision) + period
|
1091
|
+
result += clock.tz_difference if (result.universal_time <= self.universal_time)
|
1092
|
+
return result
|
1093
|
+
end
|
1094
|
+
|
1095
|
+
# 位置情報
|
1096
|
+
#
|
1097
|
+
# @return [When::Coordinates::Spatial]
|
1098
|
+
#
|
1099
|
+
def location
|
1100
|
+
@location ||= @clk_time.frame.location
|
1101
|
+
end
|
1102
|
+
|
1103
|
+
# 時刻情報のない When::TM::CalDate を返す
|
1104
|
+
#
|
1105
|
+
# @return [When::TM::CalDate]
|
1106
|
+
#
|
1107
|
+
def to_cal_date
|
1108
|
+
options = _attr
|
1109
|
+
options.delete(:clock)
|
1110
|
+
options[:precision] = [When::DAY, options[:precision]].min
|
1111
|
+
CalDate.new(@cal_date, options)
|
1112
|
+
end
|
1113
|
+
alias :to_CalDate :to_cal_date
|
1114
|
+
|
1115
|
+
# 標準ライブラリの DateTime オブジェクトへの変換
|
1116
|
+
#
|
1117
|
+
alias :to_date_or_datetime :to_datetime
|
1118
|
+
|
1119
|
+
#protected
|
1120
|
+
|
1121
|
+
# 属性の Hash
|
1122
|
+
# @private
|
1123
|
+
def _attr
|
1124
|
+
super.merge({:clock=>clock})
|
1125
|
+
end
|
1126
|
+
|
1127
|
+
# 属性のコピー
|
1128
|
+
# @private
|
1129
|
+
def _copy(options={})
|
1130
|
+
# 夏時間の調整
|
1131
|
+
case options[:time]
|
1132
|
+
when Array
|
1133
|
+
if clock._need_validate
|
1134
|
+
if @calendar_era_props
|
1135
|
+
date = options[:date].dup
|
1136
|
+
date[0] += calendar_era_epoch
|
1137
|
+
else
|
1138
|
+
date = options[:date]
|
1139
|
+
end
|
1140
|
+
new_clock = clock._daylight([@frame, date, options[:time]])
|
1141
|
+
options[:time] = options[:time].map {|t| t * 1}
|
1142
|
+
else
|
1143
|
+
new_clock = clock
|
1144
|
+
end
|
1145
|
+
options[:time] = @clk_time.dup._copy(options.merge({:clock=>new_clock}))
|
1146
|
+
when nil
|
1147
|
+
options[:time] = @clk_time.dup._copy(options)
|
1148
|
+
end
|
1149
|
+
|
1150
|
+
return super(options)
|
1151
|
+
end
|
1152
|
+
|
1153
|
+
# オブジェクトの生成
|
1154
|
+
#
|
1155
|
+
# @param [Array<Numeric>] date 日付表現
|
1156
|
+
# @param [Array<Numeric>] time 時刻表現
|
1157
|
+
# @param [Hash] options 下記の通り (see also {When::TM::TemporalPosition._instance})
|
1158
|
+
# @option options [When::TM::Calendar] :frame
|
1159
|
+
# @option options [When::TM::Clock] :clock
|
1160
|
+
# @option options [When::TM::CalendarEra, When::BasicTypes::M17n, Array<When::BasicTypes::M17n, Integer>] :era_name
|
1161
|
+
# (Integer は 当該年号の 0 年に相当する通年)
|
1162
|
+
# @option options [Integer] :precision
|
1163
|
+
#
|
1164
|
+
def initialize(date, time, options={})
|
1165
|
+
options[:time] = time
|
1166
|
+
super(date, options)
|
1167
|
+
end
|
1168
|
+
|
1169
|
+
private
|
1170
|
+
|
1171
|
+
# オブジェクトの正規化
|
1172
|
+
def _normalize(options={})
|
1173
|
+
|
1174
|
+
# Clock
|
1175
|
+
unless options[:validate]
|
1176
|
+
clock = Clock.get_clock_option(options)
|
1177
|
+
clock ||= options[:time].frame if options[:time].kind_of?(ClockTime)
|
1178
|
+
clock ||= Clock.local_time
|
1179
|
+
end
|
1180
|
+
clock = When.Clock(clock) if clock.kind_of?(String)
|
1181
|
+
clock_is_timezone = clock && !clock.kind_of?(When::TM::Clock)
|
1182
|
+
clock = clock.daylight if clock_is_timezone
|
1183
|
+
|
1184
|
+
# ClockTime
|
1185
|
+
@clk_time =
|
1186
|
+
case options[:time]
|
1187
|
+
when ClockTime ; options[:time]
|
1188
|
+
when Array ; ClockTime.new(options[:time], {:frame=>clock, :precision=>options[:precision], :validate=>:done})
|
1189
|
+
else ; clock.to_clk_time(options[:time], {:precision=>options[:precision]})
|
1190
|
+
end
|
1191
|
+
|
1192
|
+
super
|
1193
|
+
|
1194
|
+
# 日付と時刻の正規化
|
1195
|
+
unless options[:validate]
|
1196
|
+
time = @clk_time.clk_time
|
1197
|
+
precision = @clk_time.precision
|
1198
|
+
second = time[clock.base.length-1]
|
1199
|
+
second -= clock.base[-1] if second
|
1200
|
+
if second && second != 0 && time_standard.has_leap?
|
1201
|
+
zero = DateAndTime.new(@cal_date, time[0..-2],
|
1202
|
+
{:frame=>@frame, :clock=>clock, :precision=>precision,
|
1203
|
+
:era_name=>@calendar_era_props, :era=>options[:era],
|
1204
|
+
:time_standard=>time_standard, :location=>@location})
|
1205
|
+
end
|
1206
|
+
|
1207
|
+
# 日付と時刻の関係の調整
|
1208
|
+
@cal_date = _date_with_era(@frame._validate(_date_without_era) {|jdn|
|
1209
|
+
time[0] += jdn
|
1210
|
+
time[0..-1] = clock._validate(time)
|
1211
|
+
jdn = time[0] * 1
|
1212
|
+
time[0] -= jdn
|
1213
|
+
jdn
|
1214
|
+
})
|
1215
|
+
|
1216
|
+
# 夏時間の調整
|
1217
|
+
if clock._need_validate
|
1218
|
+
if @calendar_era_props
|
1219
|
+
cal_date = @cal_date.dup
|
1220
|
+
cal_date[0] += calendar_era_epoch
|
1221
|
+
else
|
1222
|
+
cal_date = @cal_date
|
1223
|
+
end
|
1224
|
+
clock = clock._daylight([@frame, cal_date, time])
|
1225
|
+
end
|
1226
|
+
time = [time[0]] + time[1..-1].map {|t| t * 1}
|
1227
|
+
@clk_time = ClockTime.new(time, {:frame=>clock, :precision=>precision, :validate=>:done}) if clock_is_timezone
|
1228
|
+
|
1229
|
+
# 閏秒
|
1230
|
+
if zero
|
1231
|
+
leap = ((dynamical_time - zero.dynamical_time) * clock.second - second).to_i
|
1232
|
+
if leap != 0 && leap.abs < clock.second
|
1233
|
+
@cal_date = zero.cal_date
|
1234
|
+
@clk_time = zero.clk_time
|
1235
|
+
@clk_time.clk_time[-1] += second
|
1236
|
+
leap /= clock.second
|
1237
|
+
@universal_time = @local_time = When::Coordinates::LeapSeconds.new(@local_time-leap, leap, 1/clock.second)
|
1238
|
+
@dynamical_time -= leap
|
1239
|
+
end
|
1240
|
+
end
|
1241
|
+
end
|
1242
|
+
|
1243
|
+
# 後処理
|
1244
|
+
@keys |= @clk_time.keys
|
1245
|
+
end
|
1246
|
+
|
1247
|
+
# 加減算共通処理
|
1248
|
+
def _plus(period)
|
1249
|
+
# 日時の加算
|
1250
|
+
time = @clk_time.clk_time.dup
|
1251
|
+
pdate = @frame._arrange_length(period.date)
|
1252
|
+
ptime = clock._arrange_length(period.time)
|
1253
|
+
date = _date_with_era(@frame._validate(_date_without_era, pdate) {|jdn|
|
1254
|
+
time[0] += jdn
|
1255
|
+
time = clock._validate(time, ptime)
|
1256
|
+
jdn = time[0] * 1
|
1257
|
+
time[0] -= jdn
|
1258
|
+
jdn
|
1259
|
+
})
|
1260
|
+
|
1261
|
+
# オブジェクトの生成
|
1262
|
+
_frame_adjust(period, self.dup._copy({:date=>date, :time=>time, :validate=>:done, :events=>nil, :query=>nil}))
|
1263
|
+
end
|
1264
|
+
end
|
1265
|
+
end
|