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.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/lib/when_exe.rb +89 -3
  3. data/lib/when_exe/basictypes.rb +37 -7
  4. data/lib/when_exe/calendarnote.rb +18 -13
  5. data/lib/when_exe/calendartypes.rb +3 -9
  6. data/lib/when_exe/coordinates.rb +23 -373
  7. data/lib/when_exe/ephemeris.rb +7 -7
  8. data/lib/when_exe/ephemeris/notes.rb +0 -14
  9. data/lib/when_exe/events.rb +1851 -0
  10. data/lib/when_exe/icalendar.rb +121 -4
  11. data/lib/when_exe/linkeddata.rb +29 -18
  12. data/lib/when_exe/locales/akt.rb +63 -0
  13. data/lib/when_exe/locales/locale.rb +60 -11
  14. data/lib/when_exe/mini_application.rb +14 -8
  15. data/lib/when_exe/namespace.rb +42 -0
  16. data/lib/when_exe/parts/enumerator.rb +13 -2
  17. data/lib/when_exe/parts/geometric_complex.rb +51 -1
  18. data/lib/when_exe/parts/method_cash.rb +15 -10
  19. data/lib/when_exe/parts/resource.rb +47 -29
  20. data/lib/when_exe/region/chinese.rb +4 -3
  21. data/lib/when_exe/region/chinese/calendars.rb +4 -4
  22. data/lib/when_exe/region/chinese/epochs.rb +6 -6
  23. data/lib/when_exe/region/chinese/notes.rb +3 -3
  24. data/lib/when_exe/region/chinese/twins.rb +6 -6
  25. data/lib/when_exe/region/islamic.rb +1 -1
  26. data/lib/when_exe/region/japanese.rb +4 -4
  27. data/lib/when_exe/region/japanese/eclipses.rb +2 -2
  28. data/lib/when_exe/region/japanese/location.rb +93 -0
  29. data/lib/when_exe/region/japanese/notes.rb +29 -11
  30. data/lib/when_exe/region/japanese/residues.rb +1 -1
  31. data/lib/when_exe/region/japanese/twins.rb +18 -6
  32. data/lib/when_exe/region/location.rb +40 -0
  33. data/lib/when_exe/region/martian.rb +1 -1
  34. data/lib/when_exe/region/ryukyu.rb +1 -1
  35. data/lib/when_exe/spatial.rb +611 -0
  36. data/lib/when_exe/timestandard.rb +3 -3
  37. data/lib/when_exe/tmobjects.rb +32 -0
  38. data/lib/when_exe/tmposition.rb +211 -1318
  39. data/lib/when_exe/tmptypes.rb +1265 -0
  40. data/lib/when_exe/tmreference.rb +35 -0
  41. data/lib/when_exe/version.rb +3 -3
  42. data/test/events/example-datasets +7 -0
  43. data/test/events/history-dataset.csv +22 -0
  44. data/test/events/japanese-holiday-index.csv +28 -0
  45. data/test/events/japanese-holiday.csv +77 -0
  46. data/test/events/japanese-holiday.ttl +778 -0
  47. data/test/events/make_events_ttl.rb +18 -0
  48. data/test/events/mori_wikichoshi.csv +14 -0
  49. data/test/events/ndl_koyomi.csv +220 -0
  50. data/test/events/ndl_koyomi_index.csv +44 -0
  51. data/test/events/primeminister-dataset.csv +19 -0
  52. data/test/events/shogun-dataset.csv +22 -0
  53. data/test/events/test-history-dataset-edge-sparql.csv +26 -0
  54. data/test/events/test-history-dataset-edge.csv +27 -0
  55. data/test/events/test-history-dataset-sparql.csv +22 -0
  56. data/test/events/test-history-dataset.csv +23 -0
  57. data/test/events/test-history-events-edge.ttl +89 -0
  58. data/test/events/test-history-events.csv +6 -0
  59. data/test/examples/Terms.m17n +1 -1
  60. data/test/test.rb +6 -0
  61. data/test/test/coordinates.rb +2 -2
  62. data/test/test/events.rb +32 -0
  63. data/test/test/region/japanese.rb +20 -0
  64. data/test/test/region/m17n.rb +2 -2
  65. data/test/test/region/mayan.rb +6 -6
  66. data/test/test/tmposition.rb +63 -1
  67. metadata +26 -2
@@ -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