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
@@ -57,7 +57,7 @@ module When::TimeStandard
|
|
57
57
|
|
58
58
|
DeltaT = [ 63.467, # 1999
|
59
59
|
63.827, 64.092, 64.300, 64.473, 64.573, 64.689, 64.846, 65.145, 65.456, 65.779, # 2000-
|
60
|
-
66.070, 66.324, 66.603, 66.909, 67.282
|
60
|
+
66.070, 66.324, 66.603, 66.909, 67.282, 67.642 # 2010-
|
61
61
|
]
|
62
62
|
|
63
63
|
class << self
|
@@ -377,7 +377,7 @@ module When::TimeStandard
|
|
377
377
|
#
|
378
378
|
def _normalize_time_basis
|
379
379
|
|
380
|
-
@_time_basis ||= @time_basis || (@location ? @location.long /
|
380
|
+
@_time_basis ||= @time_basis || (@location ? @location.long / @location.degree * 240 : When::UTC)
|
381
381
|
@_time_basis = When::Locale._split(@_time_basis) if @_time_basis.kind_of?(String)
|
382
382
|
@_time_basis = [@_time_basis] unless @_time_basis.kind_of?(Array)
|
383
383
|
@_time_basis = @_time_basis.map {|clock| When.Clock(clock)}
|
@@ -404,7 +404,7 @@ module When::TimeStandard
|
|
404
404
|
# @return [Numeric] difference / day
|
405
405
|
#
|
406
406
|
def localdate_difference
|
407
|
-
@localdate_difference ||= @location.long / (360.0 *
|
407
|
+
@localdate_difference ||= @location.long / (360.0 * @location.degree)
|
408
408
|
end
|
409
409
|
|
410
410
|
# local time と universal time の差 / 128秒
|
data/lib/when_exe/tmobjects.rb
CHANGED
@@ -530,6 +530,13 @@ module When::TM
|
|
530
530
|
#
|
531
531
|
class Duration
|
532
532
|
|
533
|
+
# 繰り返し有無
|
534
|
+
#
|
535
|
+
# @return [Boolean]
|
536
|
+
#
|
537
|
+
attr_accessor :repeat
|
538
|
+
protected :repeat=
|
539
|
+
|
533
540
|
#
|
534
541
|
# When::TM::IntervalLength への変換
|
535
542
|
#
|
@@ -556,6 +563,31 @@ module When::TM
|
|
556
563
|
When::TM::PeriodDuration.new(duration / SECOND, When::SECOND)
|
557
564
|
end
|
558
565
|
|
566
|
+
# オブジェクト変換オプションの遅延適用(ダミー)
|
567
|
+
#
|
568
|
+
# @param [Hash] options 以下の通り
|
569
|
+
# @option options [Hash<Integrt=>When::Coordinates::Residue>] :residue
|
570
|
+
# @option options [When::TM::Clock] :clock
|
571
|
+
# @option options [Array <When::TM::Calendar>] :frame
|
572
|
+
#
|
573
|
+
# @return [When::TM::Duration]
|
574
|
+
#
|
575
|
+
def apply_delayed_options(options)
|
576
|
+
self
|
577
|
+
end
|
578
|
+
|
579
|
+
# 繰り返し設定
|
580
|
+
#
|
581
|
+
# @param [Boolean] repeat 設定
|
582
|
+
#
|
583
|
+
# @return [When::TM::Duration]
|
584
|
+
#
|
585
|
+
def set_repeat(repeat)
|
586
|
+
repeated = dup
|
587
|
+
repeated.repeat = repeat
|
588
|
+
repeated
|
589
|
+
end
|
590
|
+
|
559
591
|
#
|
560
592
|
# Duration 用の Enumerator
|
561
593
|
#
|
data/lib/when_exe/tmposition.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
=begin
|
3
|
-
Copyright (C) 2011-
|
3
|
+
Copyright (C) 2011-2016 Takashi SUGA
|
4
4
|
|
5
5
|
You may use and/or modify this file according to the license described in the LICENSE.txt file included in this archive.
|
6
6
|
=end
|
@@ -313,21 +313,32 @@ module When::TM
|
|
313
313
|
iso8601form = When::Parts::Resource::ContentLine.extract_rfc5545_Property(specification, options).
|
314
314
|
gsub(When::Parts::Resource::IRIDecode) {|c| When::Parts::Resource::IRIDecodeTable[c]}
|
315
315
|
|
316
|
-
#
|
317
|
-
|
316
|
+
# delayed_options
|
317
|
+
delayed_options = {}
|
318
|
+
|
319
|
+
# Frame specifications - 暦法指定の取り出し
|
320
|
+
if iso8601form =~ /\A(.*[^\d]|.+=[^:]+)\((([-+*&%@!>=<?\d.A-Z:]|\{.+?\})+)\)\z/
|
318
321
|
frame, iso8601form = $~[1..2]
|
319
322
|
frame.sub!(/_+\z/, '')
|
320
323
|
else
|
321
324
|
iso8601form, frame, *rest = iso8601form.split(/(?:\^|%5E){1,2}/i)
|
322
|
-
|
325
|
+
delayed_options[:frame] = rest.map{|calendar| When.Resource(calendar, '_c:')} unless rest.empty?
|
323
326
|
end
|
324
327
|
|
325
328
|
# add frame to options
|
326
329
|
options = options.merge({:frame=>When.Resource(frame, '_c:')}) if frame
|
327
330
|
|
331
|
+
return _instance_element(iso8601form, options, delayed_options) unless iso8601form =~ /\A(.+?)(\.{2,3})(.+)\z/
|
332
|
+
first, separater, last = $1, $2, $3
|
333
|
+
When::Events::Range.new(_instance_element(first, options.dup, delayed_options.dup),
|
334
|
+
_instance_element(last, options.dup, delayed_options.dup), separater == '...')
|
335
|
+
end
|
336
|
+
|
337
|
+
def _instance_element(iso8601form, options, delayed_options)
|
338
|
+
|
328
339
|
# indeterminateValue
|
329
340
|
if (iso8601form.sub!(/\/After\z|\ABefore\/|\ANow\z|\AUnknown\z|\A[-+]Infinity\z/i, ''))
|
330
|
-
options[:indeterminated_position] = When::TimeValue::S[$&.sub(
|
341
|
+
options[:indeterminated_position] = When::TimeValue::S[$&.sub('/','')]
|
331
342
|
case options[:indeterminated_position]
|
332
343
|
when When::TimeValue::Now,
|
333
344
|
When::TimeValue::Unknown,
|
@@ -337,10 +348,11 @@ module When::TM
|
|
337
348
|
end
|
338
349
|
end
|
339
350
|
|
340
|
-
# each specification
|
341
|
-
splitted = iso8601form.split(
|
342
|
-
if (splitted[0] =~ /\AR(\d+)?\z/)
|
351
|
+
# each specification - '/' で区切られた個々の要素の取り出し
|
352
|
+
splitted = iso8601form.gsub(/\{.+?\}/) {|m| m.gsub('/', When::Locale::NUL)}.split('/').map {|m| m.gsub(When::Locale::NUL, '/')}
|
353
|
+
if (splitted[0] =~ /\AR(\d+)?(P.+)?\z/)
|
343
354
|
repeat = $1 ? $1.to_i : true
|
355
|
+
delayed_options[:duration] = When.Duration($2) if $2
|
344
356
|
splitted.shift
|
345
357
|
end
|
346
358
|
case splitted.length
|
@@ -353,77 +365,59 @@ module When::TM
|
|
353
365
|
raise ArgumentError, "Irregal ISO8601 Format: #{iso8601form}"
|
354
366
|
end
|
355
367
|
options = self._options(options)
|
356
|
-
element = splitted.map { |v|
|
368
|
+
element = splitted.map { |v|
|
369
|
+
d, r, z2 = _date_time_or_duration(v, options.dup)
|
370
|
+
delayed_options[:residue] = r if r
|
371
|
+
delayed_options[:clock ] = z2 if z2
|
372
|
+
d
|
373
|
+
}
|
357
374
|
|
358
|
-
#
|
375
|
+
# 意味のある繰り返しのない場合
|
376
|
+
has_residue_options = delayed_options[:residue] && (delayed_options[:residue][0].kind_of?(String) ||
|
377
|
+
delayed_options[:residue][2].kind_of?(String))
|
359
378
|
case repeat
|
360
|
-
when nil
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
case element[0]
|
366
|
-
when Duration ; raise TypeError, "Duplicate Duration: #{element[0]} and #{element[1]}"
|
367
|
-
when self ; return When::Parts::GeometricComplex.new(*element)
|
368
|
-
else ; return When::Parts::GeometricComplex.new(element[0].first, element[1])
|
369
|
-
end
|
370
|
-
when self
|
371
|
-
case element[0]
|
372
|
-
when Duration ; return When::Parts::GeometricComplex.new([[element[1]-element[0],false], [element[1],true ]])
|
373
|
-
when self ; return When::Parts::GeometricComplex.new(element[0]..element[1])
|
374
|
-
else ; return When::Parts::GeometricComplex.new(element[0].first..element[1])
|
375
|
-
end
|
376
|
-
else
|
377
|
-
case element[0]
|
378
|
-
when Duration ; return When::Parts::GeometricComplex.new([[element[1].first-element[0],false],
|
379
|
-
[element[1].last-element[0]-1,true ]])
|
380
|
-
when self ; return When::Parts::GeometricComplex.new(element[0]...element[1].last)
|
381
|
-
else ; return When::Parts::GeometricComplex.new(element[0].first...element[1].last)
|
382
|
-
end
|
383
|
-
end
|
384
|
-
when 0 ; return []
|
385
|
-
when Integer ; return [element[0]] * repeat unless element[1]
|
379
|
+
when nil ; return _instance_without_repeat(element).apply_delayed_options(delayed_options) unless has_residue_options
|
380
|
+
when 0 ; return []
|
381
|
+
when Integer
|
382
|
+
return [element[0]] * repeat if element.length == 1 && element[0].kind_of?(When::TM::Duration) # JIS X0301 5.6.3
|
383
|
+
raise ArgumentError, "Duration or TemporalPosition missing" unless element[1] || has_residue_options
|
386
384
|
end
|
387
385
|
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
else ; duration = element[1].first - element[0].first
|
386
|
+
# 繰り返しの起点と間隔
|
387
|
+
base = element[0].kind_of?(Duration) ? element[1] : element[0]
|
388
|
+
duration = _duration_for_repeat(element)
|
389
|
+
|
390
|
+
# 繰り返しのある場合
|
391
|
+
if repeat.kind_of?(Integer) && !has_residue_options
|
392
|
+
|
393
|
+
# iCalendar の機能を使用しない
|
394
|
+
result = []
|
395
|
+
seed = base
|
396
|
+
guard = (base - When::V::Event.default_until)...(base + When::V::Event.default_until)
|
397
|
+
while result.length < repeat && seed >= guard.first && seed < guard.last
|
398
|
+
applied = seed.apply_delayed_options(delayed_options)
|
399
|
+
applied = When::Parts::GeometricComplex.new(applied, delayed_options[:duration]) if delayed_options[:duration]
|
400
|
+
result << applied if applied
|
401
|
+
seed += duration
|
405
402
|
end
|
406
|
-
end
|
407
|
-
base = element[0].kind_of?(Duration) ? element[1] : element[0]
|
408
|
-
|
409
|
-
if repeat.kind_of?(Integer)
|
410
|
-
result = case base
|
411
|
-
when self ; (1..repeat-1).inject([base]) {|a,i| a << (a[-1] + duration) }
|
412
|
-
else ; (1..repeat-1).inject([base]) {|a,i| a << When::Parts::GeometricComplex.new(
|
413
|
-
a[-1].first+duration...a[-1].last+duration)}
|
414
|
-
end
|
415
403
|
result.reverse! if duration.sign < 0
|
416
404
|
return result
|
417
405
|
|
418
406
|
else
|
419
|
-
|
420
|
-
return
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
407
|
+
|
408
|
+
return duration.set_repeat(true) unless base
|
409
|
+
|
410
|
+
# iCalendar の機能を使用する
|
411
|
+
should_limit = base.precision == When::MONTH && !(delayed_options[:residue] && delayed_options[:residue][0])
|
412
|
+
iterator = When::V::Event.iterator_for_ISO8601(base, duration, delayed_options)
|
413
|
+
case repeat
|
414
|
+
when nil ; (result=iterator.succ).precision > base.precision && should_limit && base != result ? nil : result
|
415
|
+
when Integer ; (0...repeat).to_a.map {iterator.succ}
|
416
|
+
else ; iterator
|
417
|
+
end
|
425
418
|
end
|
426
419
|
end
|
420
|
+
private :_instance_element
|
427
421
|
|
428
422
|
# When::TM::TemporalPosition の生成
|
429
423
|
#
|
@@ -463,6 +457,10 @@ module When::TM
|
|
463
457
|
else ; nil
|
464
458
|
end
|
465
459
|
}
|
460
|
+
parse = options.delete(:parse)
|
461
|
+
if parse && parse[:residue] && parse[:residue][2]
|
462
|
+
res << parse[:residue][2]
|
463
|
+
end
|
466
464
|
if args.length > 0
|
467
465
|
options[:clock] ||= Clock.local_time
|
468
466
|
options[:clock] = When.Clock(options[:clock])
|
@@ -503,7 +501,7 @@ module When::TM
|
|
503
501
|
main = {}
|
504
502
|
clock = Clock.get_clock_option(query)
|
505
503
|
main[:clock] = clock if clock
|
506
|
-
[:indeterminated_position, :frame, :events, :precision,
|
504
|
+
[:indeterminated_position, :frame, :events, :precision, :parse,
|
507
505
|
:era_name, :era, :abbr, :extra_year_digits, :ordinal_date_digits, :wkst, :time_standard, :location].each do |key|
|
508
506
|
main[key] = query.delete(key) if query.key?(key)
|
509
507
|
end
|
@@ -573,20 +571,94 @@ module When::TM
|
|
573
571
|
when :week
|
574
572
|
position = ((position + PeriodDuration.new(4, DAY)) & (Residue.day_of_week(options[:wkst]) << 1)) +
|
575
573
|
PeriodDuration.new((w[0]-1)*7 + (w[1]||1)-1, DAY)
|
576
|
-
position = When::Parts::GeometricComplex.new(position
|
574
|
+
position = When::Parts::GeometricComplex.new(position, P1W) unless w[1]
|
577
575
|
end
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
576
|
+
[position, r, z2]
|
577
|
+
end
|
578
|
+
|
579
|
+
# オブジェクト変換オプションの遅延適用対象オブジェクト
|
580
|
+
#
|
581
|
+
# @param [Array<When::TM::TemporalPosition or When::TM::Duration>] element
|
582
|
+
#
|
583
|
+
# @return [When::TM::TemporalPosition] ISO8601 time point
|
584
|
+
# @return [When::Parts::GeometricComplex] ISO8601 遅延適用対象オブジェクト
|
585
|
+
#
|
586
|
+
def _instance_without_repeat(element)
|
587
|
+
case element[1]
|
588
|
+
when nil
|
589
|
+
return element[0]
|
590
|
+
when Duration
|
591
|
+
case element[0]
|
592
|
+
when Duration ; raise TypeError, "Duplicate Duration: #{element[0]} and #{element[1]}"
|
593
|
+
when self ; return When::Parts::GeometricComplex.new(*element)
|
594
|
+
else ; return When::Parts::GeometricComplex.new(element[0].first, element[1])
|
595
|
+
end
|
596
|
+
when self
|
597
|
+
case element[0]
|
598
|
+
when Duration ; return When::Parts::GeometricComplex.new([[element[1]-element[0],false], [element[1],true ]])
|
599
|
+
when self ; return When::Parts::GeometricComplex.new(element[0]..element[1])
|
600
|
+
else ; return When::Parts::GeometricComplex.new(element[0].first..element[1])
|
601
|
+
end
|
602
|
+
else
|
603
|
+
case element[0]
|
604
|
+
when Duration ; return When::Parts::GeometricComplex.new([[element[1].first-element[0],false],
|
605
|
+
[element[1].last-element[0]-1,true ]])
|
606
|
+
when self ; return When::Parts::GeometricComplex.new(element[0]...element[1].last)
|
607
|
+
else ; return When::Parts::GeometricComplex.new(element[0].first...element[1].last)
|
608
|
+
end
|
609
|
+
end
|
610
|
+
end
|
611
|
+
|
612
|
+
# 繰り返し用の Duration 取得
|
613
|
+
#
|
614
|
+
# @param [Array<When::TM::TemporalPosition or When::TM::Duration>] element
|
615
|
+
#
|
616
|
+
# @return [When::TM::Duration] repeating interval
|
617
|
+
#
|
618
|
+
def _duration_for_repeat(element)
|
619
|
+
case element[1]
|
620
|
+
when Duration
|
621
|
+
case element[0]
|
622
|
+
when Duration ; raise TypeError, "Duplicate Duration: #{element[0]} and #{element[1]}"
|
623
|
+
else ; return element[1]
|
624
|
+
end
|
625
|
+
when self
|
626
|
+
case element[0]
|
627
|
+
when Duration ; return -element[0]
|
628
|
+
when self ; return element[1] - element[0]
|
629
|
+
else ; return element[1] - element[0].first
|
630
|
+
end
|
631
|
+
when nil
|
632
|
+
case element[0]
|
633
|
+
when Duration ; return element[0]
|
634
|
+
else ; nil
|
635
|
+
end
|
636
|
+
else
|
637
|
+
case element[0]
|
638
|
+
when Duration ; return -element[0]
|
639
|
+
when self ; return element[1].first - element[0]
|
640
|
+
else ; return element[1].first - element[0].first
|
587
641
|
end
|
588
642
|
end
|
589
|
-
|
643
|
+
end
|
644
|
+
|
645
|
+
# オブジェクト変換オプションの遅延適用
|
646
|
+
#
|
647
|
+
# @param [Object] object 遅延適用するオブジェクト
|
648
|
+
#
|
649
|
+
# @param [Hash] options 以下の通り
|
650
|
+
# @option options [Hash<Integrt=>When::Coordinates::Residue>] :residue
|
651
|
+
# @option options [When::TM::Clock] :clock
|
652
|
+
# @option options [Array <When::TM::Calendar>] :frame
|
653
|
+
#
|
654
|
+
# @return [Object] 遅延適用されたオブジェクト
|
655
|
+
#
|
656
|
+
def _apply_delayed_options(object, options)
|
657
|
+
case object
|
658
|
+
when Array ; object.map {|obj| _apply_delayed_options(obj, options)}
|
659
|
+
when self, When::Parts::GeometricComplex ; object.apply_delayed_options(options)
|
660
|
+
else ; object
|
661
|
+
end
|
590
662
|
end
|
591
663
|
end
|
592
664
|
|
@@ -759,13 +831,15 @@ module When::TM
|
|
759
831
|
#
|
760
832
|
def +(other)
|
761
833
|
case other
|
762
|
-
when Integer
|
763
|
-
when Numeric
|
764
|
-
when
|
765
|
-
when
|
766
|
-
|
767
|
-
else ; raise TypeError, "The right operand should be Numeric or Duration"
|
834
|
+
when Integer ; return self + PeriodDuration.new(other, When::DAY)
|
835
|
+
when Numeric ; return self + IntervalLength.new(other, 'day')
|
836
|
+
when Duration ; begin other = other.set_repeat(false); return other.enum_for(self+other, :forward) end if other.repeat
|
837
|
+
when Array ; return other.map {|o| self + o}
|
838
|
+
else ; raise TypeError, "The right operand should be Numeric or Duration"
|
768
839
|
end
|
840
|
+
return _plus(other) if other.kind_of?(PeriodDuration)
|
841
|
+
@frame.kind_of?(Calendar) ? @frame.jul_trans(JulianDate.dynamical_time(dynamical_time + other.duration), self._attr) :
|
842
|
+
JulianDate.dynamical_time(dynamical_time + other.duration, self._attr)
|
769
843
|
rescue RangeError
|
770
844
|
(@frame ^ self) + other
|
771
845
|
end
|
@@ -779,16 +853,18 @@ module When::TM
|
|
779
853
|
#
|
780
854
|
def -(other)
|
781
855
|
case other
|
782
|
-
when TimeValue
|
783
|
-
|
784
|
-
|
785
|
-
when Integer
|
786
|
-
when Numeric
|
787
|
-
when
|
788
|
-
when
|
789
|
-
|
790
|
-
else ; raise TypeError, "The right operand should be Numeric, Duration or TemporalPosition"
|
856
|
+
when TimeValue; return self.time_standard.rate_of_clock == other.time_standard.rate_of_clock && [@precision, other.precision].min <= When::DAY ?
|
857
|
+
PeriodDuration.new(self.to_i - other.to_i, When::DAY) :
|
858
|
+
IntervalLength.new((self.dynamical_time - other.dynamical_time) / Duration::SECOND, 'second')
|
859
|
+
when Integer ; return self - PeriodDuration.new(other, When::DAY)
|
860
|
+
when Numeric ; return self - IntervalLength.new(other, 'day')
|
861
|
+
when Duration ; begin other = other.set_repeat(false); return other.enum_for(self-other, :reverse) end if other.repeat
|
862
|
+
when Array ; return other.map {|o| self - o}
|
863
|
+
else ; raise TypeError, "The right operand should be Numeric, Duration or TemporalPosition"
|
791
864
|
end
|
865
|
+
return _plus(-other) if other.kind_of?(PeriodDuration)
|
866
|
+
@frame.kind_of?(Calendar) ? @frame.jul_trans(JulianDate.dynamical_time(dynamical_time - other.duration), self._attr) :
|
867
|
+
JulianDate.dynamical_time(dynamical_time - other.duration, self._attr)
|
792
868
|
rescue RangeError
|
793
869
|
(@frame ^ self) - other
|
794
870
|
end
|
@@ -804,31 +880,6 @@ module When::TM
|
|
804
880
|
@period = When.Duration(period_name)
|
805
881
|
end
|
806
882
|
|
807
|
-
# 前の日時
|
808
|
-
#
|
809
|
-
# @return [When::TM::TemporalPosition]
|
810
|
-
#
|
811
|
-
# 分解能に対応する Duration だけ,日時を戻す
|
812
|
-
#
|
813
|
-
def prev
|
814
|
-
@precision==When::DAY ? _force_euqal_day(-1) : self-period
|
815
|
-
rescue RangeError
|
816
|
-
(When::Gregorian ^ self) - period
|
817
|
-
end
|
818
|
-
|
819
|
-
# 次の日時
|
820
|
-
#
|
821
|
-
# @return [When::TM::TemporalPosition]
|
822
|
-
#
|
823
|
-
# 分解能に対応する Duration だけ,日時を進める
|
824
|
-
#
|
825
|
-
def succ
|
826
|
-
@precision==When::DAY ? _force_euqal_day(+1) : self+period
|
827
|
-
rescue RangeError
|
828
|
-
(When::Gregorian ^ self) + period
|
829
|
-
end
|
830
|
-
alias :next :succ
|
831
|
-
|
832
883
|
#
|
833
884
|
# 前後の日時を取得可能か?
|
834
885
|
#
|
@@ -857,7 +908,7 @@ module When::TM
|
|
857
908
|
# @return [Boolean]
|
858
909
|
#
|
859
910
|
def has_time?
|
860
|
-
(@precision >
|
911
|
+
(@precision > DAY)
|
861
912
|
end
|
862
913
|
|
863
914
|
# 指定の日時を含むか?
|
@@ -927,6 +978,10 @@ module When::TM
|
|
927
978
|
return result unless result == 0
|
928
979
|
end
|
929
980
|
@cal_date[prec - 1] <=> other.cal_date[prec - 1]
|
981
|
+
elsif prec < DAY && precision < other.precision
|
982
|
+
return +1 if other.to_i < self.to_i
|
983
|
+
return -1 if other.to_i >= succ.to_i
|
984
|
+
return 0
|
930
985
|
else
|
931
986
|
source = (prec >= self.precision ) ? self : self.floor(prec)
|
932
987
|
target = (prec >= other.precision) ? other : other.floor(prec)
|
@@ -1000,6 +1055,41 @@ module When::TM
|
|
1000
1055
|
scan(other, leaf, &block)
|
1001
1056
|
end
|
1002
1057
|
|
1058
|
+
# オブジェクト変換オプションの遅延適用
|
1059
|
+
#
|
1060
|
+
# @param [Hash] options 以下の通り
|
1061
|
+
# @option options [Hash<Integrt=>When::Coordinates::Residue>] :residue
|
1062
|
+
# @option options [When::TM::Clock] :clock
|
1063
|
+
# @option options [Array <When::TM::Calendar>] :frame
|
1064
|
+
#
|
1065
|
+
# @return [When::TM::TemporalPosition]
|
1066
|
+
#
|
1067
|
+
def apply_delayed_options(options)
|
1068
|
+
position = self
|
1069
|
+
if options[:residue]
|
1070
|
+
options[:residue].keys.sort.each do |count|
|
1071
|
+
options[:residue][count] = When.Residue(options[:residue][count]) unless options[:residue][count].kind_of?(When::Coordinates::Residue)
|
1072
|
+
residue = options[:residue][count]
|
1073
|
+
if count == 0
|
1074
|
+
residue = residue.to('year')
|
1075
|
+
position &= residue
|
1076
|
+
else
|
1077
|
+
upper = position
|
1078
|
+
position = position.succ if residue.carry < 0
|
1079
|
+
position &= residue
|
1080
|
+
return nil if self.precision == When::MONTH && !(upper == position)
|
1081
|
+
end
|
1082
|
+
end
|
1083
|
+
end
|
1084
|
+
if options[:clock]
|
1085
|
+
position = options[:clock] ^ position
|
1086
|
+
end
|
1087
|
+
if options[:frame]
|
1088
|
+
position = options[:frame].inject(position) {|p,c| c.jul_trans(p)}
|
1089
|
+
end
|
1090
|
+
position
|
1091
|
+
end
|
1092
|
+
|
1003
1093
|
# 属性を変更したコピーを作る
|
1004
1094
|
#
|
1005
1095
|
# @param [Hash] options { 属性=>属性値 }
|
@@ -1142,1201 +1232,4 @@ module When::TM
|
|
1142
1232
|
end
|
1143
1233
|
end
|
1144
1234
|
end
|
1145
|
-
|
1146
|
-
#
|
1147
|
-
# 時間座標 - 単一の時間間隔によって定義する連続な間隔尺度を基礎とする
|
1148
|
-
#
|
1149
|
-
# see {http://schemas.opengis.net/gml/3.1.1/base/temporalAppendix.xsd#TimeCoordinateType gml schema}
|
1150
|
-
#
|
1151
|
-
class Coordinate < TemporalPosition
|
1152
|
-
|
1153
|
-
class << self
|
1154
|
-
# 内部時間によるオブジェクトの生成
|
1155
|
-
alias :universal_time :new
|
1156
|
-
|
1157
|
-
# 外部時間によるオブジェクトの生成
|
1158
|
-
#
|
1159
|
-
# @param [Numeric] dynamical_time 外部時間による時間座標値
|
1160
|
-
#
|
1161
|
-
# @param [Hash] options 下記の通り
|
1162
|
-
# @option options [When::TimeStandard] :time_standard
|
1163
|
-
#
|
1164
|
-
# @return [When::TM::Coordinate]
|
1165
|
-
#
|
1166
|
-
def dynamical_time(dynamical_time, options={})
|
1167
|
-
universal_time(When.Resource(options[:time_standard] || 'UniversalTime', '_t:').from_dynamical_time(dynamical_time), options)
|
1168
|
-
end
|
1169
|
-
|
1170
|
-
# 他種の時間位置によるオブジェクトの生成
|
1171
|
-
#
|
1172
|
-
# @param [Numeric, When::TM::ClockTime, ::Time, ::Date, ::DateTime] time 他種の時間位置によるオブジェクト
|
1173
|
-
#
|
1174
|
-
# @param [Hash] options 下記の通り
|
1175
|
-
# @option options [When::TM::Clock] :clock
|
1176
|
-
# @option options [When::Parts::Timezone] :tz
|
1177
|
-
#
|
1178
|
-
# @return [When::TM::Coordinate]
|
1179
|
-
#
|
1180
|
-
def new(time, options={})
|
1181
|
-
options = options.dup
|
1182
|
-
options[:frame] = Clock.get_clock_option(options)
|
1183
|
-
case time
|
1184
|
-
when Numeric
|
1185
|
-
options[:frame] ||= When::UTC unless time.kind_of?(Integer)
|
1186
|
-
universal_time = (2*time - (2*JulianDate::JD19700101-1)) * Duration::DAY.to_i / 2.0
|
1187
|
-
when ClockTime
|
1188
|
-
options[:frame] ||= time.clock
|
1189
|
-
universal_time = time.clk_time[0] + time.universal_time
|
1190
|
-
when ::Time
|
1191
|
-
options[:frame] ||= When.Clock(time.gmtoff)
|
1192
|
-
universal_time = options[:frame].time_standard.from_time_object(time)
|
1193
|
-
when TimeValue
|
1194
|
-
options[:frame] ||= time.clock
|
1195
|
-
universal_time = time.universal_time
|
1196
|
-
else
|
1197
|
-
if ::Object.const_defined?(:Date) && ::Date.method_defined?(:+) && time.respond_to?(:ajd)
|
1198
|
-
case time
|
1199
|
-
when ::DateTime
|
1200
|
-
options[:frame] ||= When.Clock((time.offset * 86400).to_i)
|
1201
|
-
universal_time = (2*time.ajd - (2*JulianDate::JD19700101-1)) * Duration::DAY.to_i / 2.0
|
1202
|
-
when ::Date
|
1203
|
-
universal_time = JulianDate._d_to_t(time.jd)
|
1204
|
-
if options[:frame] && options[:frame].rate_of_clock != 1.0
|
1205
|
-
universal_time = options[:frame].time_standard.from_dynamical_time(
|
1206
|
-
When::TimeStandard.to_dynamical_time(universal_time))
|
1207
|
-
end
|
1208
|
-
end
|
1209
|
-
end
|
1210
|
-
end
|
1211
|
-
raise TypeError, "Can't create #{self} from #{time.class}" unless universal_time
|
1212
|
-
universal_time(universal_time, options)
|
1213
|
-
end
|
1214
|
-
end
|
1215
|
-
|
1216
|
-
# この時間位置と関連付けられた時間参照系 (relation - Reference)
|
1217
|
-
#
|
1218
|
-
# The time reference system associated with the temporal position being described
|
1219
|
-
#
|
1220
|
-
# @return [When::TM::ReferenceSystem]
|
1221
|
-
#
|
1222
|
-
alias :clock :frame
|
1223
|
-
|
1224
|
-
# 内部時間による時間座標値
|
1225
|
-
#
|
1226
|
-
# @return [Numeric]
|
1227
|
-
#
|
1228
|
-
attr_accessor :universal_time
|
1229
|
-
alias :coordinateValue :universal_time
|
1230
|
-
protected :universal_time=
|
1231
|
-
|
1232
|
-
# 内部時間(ローカル)
|
1233
|
-
#
|
1234
|
-
# @return [Numeric]
|
1235
|
-
#
|
1236
|
-
# 1970-01-01T00:00:00(ローカル) からの Universal Coordinated Time の経過時間 / 128秒
|
1237
|
-
#
|
1238
|
-
def local_time
|
1239
|
-
@universal_time
|
1240
|
-
end
|
1241
|
-
|
1242
|
-
# CoordinateSystem による時間座標値
|
1243
|
-
#
|
1244
|
-
# @return [Numeric]
|
1245
|
-
#
|
1246
|
-
def coordinateValue
|
1247
|
-
(universal_time - frame.origin.universal_time) / frame.interval.to_f
|
1248
|
-
end
|
1249
|
-
|
1250
|
-
# 加算
|
1251
|
-
#
|
1252
|
-
# @param [Numeric, When::TM::IntervalLength] other
|
1253
|
-
#
|
1254
|
-
# @return [When::TM::TemporalPosition]
|
1255
|
-
#
|
1256
|
-
def +(other)
|
1257
|
-
other = other.to_interval_length if other.kind_of?(PeriodDuration)
|
1258
|
-
super(other)
|
1259
|
-
end
|
1260
|
-
|
1261
|
-
# 減算
|
1262
|
-
#
|
1263
|
-
# @param [When::TM::TemporalPosition, Numeric, When::TM::IntervalLength] other
|
1264
|
-
#
|
1265
|
-
# @return [When::TM::TemporalPosition] if other is a Numeric or When::TM::IntervalLength
|
1266
|
-
# @return [When::TM::IntervalLength] if other is a When::TM::TemporalPosition
|
1267
|
-
#
|
1268
|
-
def -(other)
|
1269
|
-
other = other.to_interval_length if other.kind_of?(PeriodDuration)
|
1270
|
-
super(other)
|
1271
|
-
end
|
1272
|
-
|
1273
|
-
# オブジェクトの生成
|
1274
|
-
#
|
1275
|
-
# @param [Numeric] universal_time 内部時間による時間座標値
|
1276
|
-
#
|
1277
|
-
# @param [Hash] options 下記の通り
|
1278
|
-
# @option options [When::TM::CoordinateSystem] :frame
|
1279
|
-
#
|
1280
|
-
def initialize(universal_time, options={})
|
1281
|
-
super(options)
|
1282
|
-
@universal_time = universal_time
|
1283
|
-
end
|
1284
|
-
end
|
1285
|
-
|
1286
|
-
#
|
1287
|
-
# ユリウス日
|
1288
|
-
#
|
1289
|
-
# see {http://schemas.opengis.net/gml/3.1.1/base/temporalAppendix.xsd#JulianDateType CALENdeRsign}
|
1290
|
-
#
|
1291
|
-
class JulianDate < Coordinate
|
1292
|
-
|
1293
|
-
# Julian Day Number
|
1294
|
-
# 19700101T120000Z
|
1295
|
-
JD19700101 = 2440588
|
1296
|
-
|
1297
|
-
# Modified Julian Date
|
1298
|
-
#
|
1299
|
-
# see {https://en.wikipedia.org/wiki/Julian_day#Variants MJD}
|
1300
|
-
JDN_of_MJD = 2400000.5
|
1301
|
-
|
1302
|
-
# Countdown to Equinoctial Planetconjunction
|
1303
|
-
#
|
1304
|
-
# see {http://www.calendersign.com/en/cs_cep-pec.php CEP}
|
1305
|
-
JDN_of_CEP = 2698162
|
1306
|
-
|
1307
|
-
class << self
|
1308
|
-
|
1309
|
-
JD19700100_5 = JD19700101 - 0.5
|
1310
|
-
|
1311
|
-
#
|
1312
|
-
# 日時の内部表現をユリウス日に変換
|
1313
|
-
#
|
1314
|
-
# @param [Numeric] t
|
1315
|
-
#
|
1316
|
-
# @return [Numeric]
|
1317
|
-
#
|
1318
|
-
def _t_to_d(t)
|
1319
|
-
t / Duration::DAY + JD19700100_5
|
1320
|
-
end
|
1321
|
-
|
1322
|
-
#
|
1323
|
-
# ユリウス日をに日時の内部表現変換
|
1324
|
-
#
|
1325
|
-
# @param [Numeric] d
|
1326
|
-
#
|
1327
|
-
# @return [Numeric]
|
1328
|
-
#
|
1329
|
-
def _d_to_t(d)
|
1330
|
-
(d - JD19700100_5) * Duration::DAY
|
1331
|
-
end
|
1332
|
-
|
1333
|
-
# Generation of Temporal Objetct
|
1334
|
-
#
|
1335
|
-
# @param [String] specification ユリウス通日を表す文字列
|
1336
|
-
# @param [Hash] options 暦法や時法などの指定 (see {When::TM::TemporalPosition._instance})
|
1337
|
-
#
|
1338
|
-
# @return [When::TM::TemporalPosition, When::TM::Duration, When::Parts::GeometricComplex or Array<them>]
|
1339
|
-
#
|
1340
|
-
def parse(specification, options={})
|
1341
|
-
num, *calendars = specification.split(/\^{1,2}/)
|
1342
|
-
jdn = num.sub!(/[.@]/, '.') ? num.to_f : num.to_i
|
1343
|
-
case num
|
1344
|
-
when/MJD/i ; jdn += JDN_of_MJD
|
1345
|
-
when/CEP/i ; jdn += JDN_of_CEP
|
1346
|
-
end
|
1347
|
-
frame = calendars.shift || options[:frame]
|
1348
|
-
return self.new(jdn, options) unless frame
|
1349
|
-
calendars.unshift(frame).inject(jdn) {|date, calendar| When.Calendar(calendar).jul_trans(date, options)}
|
1350
|
-
end
|
1351
|
-
end
|
1352
|
-
|
1353
|
-
# 加算
|
1354
|
-
#
|
1355
|
-
# @param [Numeric, When::TM::IntervalLength] other
|
1356
|
-
#
|
1357
|
-
# @return [When::TM::TemporalPosition]
|
1358
|
-
#
|
1359
|
-
def +(other)
|
1360
|
-
new_date = super
|
1361
|
-
new_date.frame = new_date.frame._daylight(new_date.universal_time) if new_date.frame && new_date.frame._need_validate
|
1362
|
-
return new_date
|
1363
|
-
end
|
1364
|
-
|
1365
|
-
# ユリウス日が指定の剰余となる日
|
1366
|
-
#
|
1367
|
-
# @param [When::Coordinates::Residue] other
|
1368
|
-
#
|
1369
|
-
# @return [When::TM::TemporalPosition]
|
1370
|
-
#
|
1371
|
-
def &(other)
|
1372
|
-
raise TypeError,"The right operand should be When::Coordinates::Residue" unless other.kind_of?(Residue)
|
1373
|
-
raise ArgumentError,"The right operand should have a unit 'day'" unless other.event == 'day'
|
1374
|
-
jdn = to_i
|
1375
|
-
new_date = self.dup
|
1376
|
-
new_date.universal_time += ((other & jdn) - jdn) * Duration::DAY
|
1377
|
-
return new_date
|
1378
|
-
end
|
1379
|
-
|
1380
|
-
# ユリウス日の剰余
|
1381
|
-
#
|
1382
|
-
# @param [When::Coordinates::Residue] other
|
1383
|
-
#
|
1384
|
-
# @return [Numeric]
|
1385
|
-
#
|
1386
|
-
def %(other)
|
1387
|
-
raise TypeError,"The right operand should be When::Coordinates::Residue" unless other.kind_of?(Residue)
|
1388
|
-
raise ArgumentError,"The right operand should have a unit 'day'" unless other.event == 'day'
|
1389
|
-
other % to_i
|
1390
|
-
end
|
1391
|
-
|
1392
|
-
private
|
1393
|
-
|
1394
|
-
# オブジェクトの生成
|
1395
|
-
#
|
1396
|
-
# @param [Numeric] universal_time 内部時間による時間座標値
|
1397
|
-
#
|
1398
|
-
# @param [Hash] options 以下の通り
|
1399
|
-
# @option options [When::TM::Clock] :frame
|
1400
|
-
# @option options [Integer] :precision
|
1401
|
-
#
|
1402
|
-
def initialize(universal_time, options={})
|
1403
|
-
@frame = options.delete(:frame)
|
1404
|
-
@frame = When.Clock(@frame) if @frame.kind_of?(String)
|
1405
|
-
@frame = @frame._daylight(universal_time) if @frame && @frame._need_validate
|
1406
|
-
precision = options.delete(:precision)
|
1407
|
-
precision ||= DAY unless @frame.kind_of?(Clock)
|
1408
|
-
@precision = Index.precision(precision)
|
1409
|
-
super
|
1410
|
-
end
|
1411
|
-
end
|
1412
|
-
|
1413
|
-
#
|
1414
|
-
# 順序時間参照系で参照する位置
|
1415
|
-
#
|
1416
|
-
# see {http://schemas.opengis.net/gml/3.1.1/base/temporalAppendix.xsd#TimeOrdinalPositionType gml schema}
|
1417
|
-
#
|
1418
|
-
class OrdinalPosition < TemporalPosition
|
1419
|
-
|
1420
|
-
# この順序位置と関連付けられた順序年代 (relation - Reference)
|
1421
|
-
#
|
1422
|
-
# The ordinal era associated with the ordinal position being described
|
1423
|
-
#
|
1424
|
-
# @return [When::TM::OrdinalEra]
|
1425
|
-
#
|
1426
|
-
attr_reader :ordinal_position
|
1427
|
-
alias :ordinalPosition :ordinal_position
|
1428
|
-
|
1429
|
-
# オブジェクトの生成
|
1430
|
-
#
|
1431
|
-
# @param [When::TM::OrdinalEra] ordinal_position この順序位置と関連付けられた順序年代
|
1432
|
-
# @param [Hash] options see {When::TM::TemporalPosition._instance}
|
1433
|
-
#
|
1434
|
-
def initialize(ordinal_position, options={})
|
1435
|
-
super(options)
|
1436
|
-
@ordinal_position = ordinal_position
|
1437
|
-
end
|
1438
|
-
end
|
1439
|
-
|
1440
|
-
#
|
1441
|
-
# 時刻
|
1442
|
-
#
|
1443
|
-
# see {http://schemas.opengis.net/gml/3.1.1/base/temporalAppendix.xsd#ClockTimeType gml schema}
|
1444
|
-
#
|
1445
|
-
class ClockTime < TemporalPosition
|
1446
|
-
|
1447
|
-
# 時刻要素
|
1448
|
-
#
|
1449
|
-
# @return [Array<Numeric>]
|
1450
|
-
#
|
1451
|
-
# @note ISO19108 では sequence<Integer> だが、閏時・閏秒などが表現可能なよう Numeric としている。
|
1452
|
-
#
|
1453
|
-
attr_reader :clk_time
|
1454
|
-
alias :clkTime :clk_time
|
1455
|
-
|
1456
|
-
# この時間位置と関連付けられた時間参照系 (relation - Reference)
|
1457
|
-
#
|
1458
|
-
# The time reference system associated with the temporal position being described
|
1459
|
-
#
|
1460
|
-
# @return [When::TM::ReferenceSystem]
|
1461
|
-
#
|
1462
|
-
alias :clock :frame
|
1463
|
-
|
1464
|
-
# 内部時間
|
1465
|
-
#
|
1466
|
-
# @param [Integer] sdn 参照事象の通し番号
|
1467
|
-
#
|
1468
|
-
# @return [Numeric]
|
1469
|
-
#
|
1470
|
-
# T00:00:00Z からの Universal Coordinated Time の経過時間 / 128秒
|
1471
|
-
#
|
1472
|
-
# 時法によっては、異なる意味を持つことがある
|
1473
|
-
#
|
1474
|
-
def universal_time(sdn=nil)
|
1475
|
-
raise NameError, "Temporal Reference System is not defined" unless @frame
|
1476
|
-
@universal_time ||= @frame.to_universal_time(@clk_time, sdn)
|
1477
|
-
end
|
1478
|
-
|
1479
|
-
# 内部時間(ローカル)
|
1480
|
-
#
|
1481
|
-
# @param [Integer] sdn 参照事象の通し番号
|
1482
|
-
#
|
1483
|
-
# @return [Numeric]
|
1484
|
-
#
|
1485
|
-
# T00:00:00(ローカル) からの Universal Coordinated Time の経過時間 / 128秒
|
1486
|
-
#
|
1487
|
-
# 時法によっては、異なる意味を持つことがある
|
1488
|
-
#
|
1489
|
-
def local_time(sdn=nil)
|
1490
|
-
raise NameError, "Temporal Reference System is not defined" unless @frame
|
1491
|
-
@local_time ||= @frame.to_local_time(@clk_time, sdn)
|
1492
|
-
end
|
1493
|
-
|
1494
|
-
# 繰り上がり
|
1495
|
-
#
|
1496
|
-
# @return [Numeric]
|
1497
|
-
#
|
1498
|
-
# 日付の境界が午前0時でない場合、clk_time の最上位桁に 0 以外が入ることがある
|
1499
|
-
#
|
1500
|
-
def carry
|
1501
|
-
return @clk_time[0]
|
1502
|
-
end
|
1503
|
-
|
1504
|
-
# 要素の参照
|
1505
|
-
#
|
1506
|
-
# @param [Integer, String] index 参照する要素の指定
|
1507
|
-
#
|
1508
|
-
# @return [Numeric]
|
1509
|
-
#
|
1510
|
-
def value(index)
|
1511
|
-
@clk_time[_digit(index) {|digit| digit >= DAY}]
|
1512
|
-
end
|
1513
|
-
|
1514
|
-
#protected
|
1515
|
-
# 属性のコピー
|
1516
|
-
# @private
|
1517
|
-
def _copy(options={})
|
1518
|
-
@clk_time = options[:time] if options.key?(:time)
|
1519
|
-
if options.key?(:clock)
|
1520
|
-
options.delete(:frame)
|
1521
|
-
@frame = options[:clock]
|
1522
|
-
end
|
1523
|
-
if options.key?(:tz_prop)
|
1524
|
-
@frame = @frame.dup
|
1525
|
-
@frame.tz_prop = options[:tz_prop]
|
1526
|
-
end
|
1527
|
-
return super
|
1528
|
-
end
|
1529
|
-
|
1530
|
-
# オブジェクトの生成
|
1531
|
-
#
|
1532
|
-
# @param [String] time ISO8601形式の時刻表現
|
1533
|
-
# @param [Array<Numeric>] time (日, 時, 分, 秒)
|
1534
|
-
#
|
1535
|
-
#
|
1536
|
-
# @param [Hash] options 以下の通り
|
1537
|
-
# @option options [When::TM::Clock] :frame
|
1538
|
-
# @option options [Integer] :precision
|
1539
|
-
#
|
1540
|
-
def initialize(time, options={})
|
1541
|
-
# 参照系の取得
|
1542
|
-
@frame = options[:frame] || Clock.local_time
|
1543
|
-
@frame = When.Clock(@frame) if (@frame.kind_of?(String))
|
1544
|
-
options.delete(:frame)
|
1545
|
-
|
1546
|
-
# 時刻表現の解読 ( Time Zone の解釈 )
|
1547
|
-
if (time.kind_of?(String))
|
1548
|
-
case time
|
1549
|
-
when /\A([-+])?(\d{2,}?):?(\d{2})?:?(\d{2}(\.\d+)?)?\z/
|
1550
|
-
sign, hh, mm, ss = $~[1..4]
|
1551
|
-
time = @frame._validate([0,0,0,0],
|
1552
|
-
[0,
|
1553
|
-
-(sign.to_s + "0" + hh.to_s).to_i,
|
1554
|
-
-(sign.to_s + "0" + mm.to_s).to_i,
|
1555
|
-
Pair._en_number(-(sign.to_s + "0" + ss.to_s).to_f)])
|
1556
|
-
time[0] = Pair.new(0, time[0].to_i) if (time[0] != 0)
|
1557
|
-
when /\AZ\z/
|
1558
|
-
time = [0,0,0,0]
|
1559
|
-
else
|
1560
|
-
raise ArgumentError, "Invalid Time Format"
|
1561
|
-
end
|
1562
|
-
end
|
1563
|
-
@clk_time = time
|
1564
|
-
|
1565
|
-
# 分解能
|
1566
|
-
@precision = @frame._precision(time, options.delete(:precision))
|
1567
|
-
|
1568
|
-
super(options)
|
1569
|
-
end
|
1570
|
-
|
1571
|
-
private
|
1572
|
-
|
1573
|
-
# オブジェクトの正規化
|
1574
|
-
def _normalize(options={})
|
1575
|
-
# strftime で使用する locale
|
1576
|
-
@keys |= @frame.keys
|
1577
|
-
|
1578
|
-
# 時刻の正規化
|
1579
|
-
@clk_time = @frame._validate(@clk_time) unless options[:validate]
|
1580
|
-
end
|
1581
|
-
|
1582
|
-
# 加減算共通処理
|
1583
|
-
def _plus(period)
|
1584
|
-
self.dup._copy({:time=>@frame._validate(@clk_time, @frame._arrange_length(period.time)),
|
1585
|
-
:events=>nil, :query=>nil, :validate=>:done})
|
1586
|
-
end
|
1587
|
-
end
|
1588
|
-
|
1589
|
-
#
|
1590
|
-
# 暦日
|
1591
|
-
#
|
1592
|
-
# see {gml schema}[link:http://schemas.opengis.net/gml/3.1.1/base/temporalAppendix.xsd#CalDateType]
|
1593
|
-
#
|
1594
|
-
class CalDate < TemporalPosition
|
1595
|
-
|
1596
|
-
# 検索オプション
|
1597
|
-
# @private
|
1598
|
-
SearchOption = {After=>[0, -2, Before], Before=>[-2, 0, After]}
|
1599
|
-
|
1600
|
-
# 日付要素
|
1601
|
-
#
|
1602
|
-
# @return [Array<Numeric>]
|
1603
|
-
#
|
1604
|
-
# @note ISO19108 では sequence<Integer> だが、閏月などが表現可能なよう Numeric としている。
|
1605
|
-
#
|
1606
|
-
attr_reader :cal_date
|
1607
|
-
alias :calDate :cal_date
|
1608
|
-
|
1609
|
-
# この時間位置と関連付けられた時間参照系 (relation - Reference)
|
1610
|
-
#
|
1611
|
-
# The time reference system associated with the temporal position being described
|
1612
|
-
#
|
1613
|
-
# @return [When::TM::ReferenceSystem]
|
1614
|
-
#
|
1615
|
-
alias :calendar :frame
|
1616
|
-
|
1617
|
-
# 暦年代
|
1618
|
-
#
|
1619
|
-
# @return [When::TM::CalendarEra]
|
1620
|
-
#
|
1621
|
-
attr_accessor :calendar_era
|
1622
|
-
private :calendar_era=
|
1623
|
-
alias :calendarEra :calendar_era
|
1624
|
-
|
1625
|
-
# 暦年代属性
|
1626
|
-
#
|
1627
|
-
# @return [Array] ( name, epoch, reverse, go back )
|
1628
|
-
# - name [String] 暦年代名
|
1629
|
-
# - epoch [Integer] 使用する When::TM::Calendar で暦元に対応する年
|
1630
|
-
# - reverse [Boolean] 年数が昇順(false,nil)か降順(true)か
|
1631
|
-
# - go back [Boolean] 参照イベントより前の暦日か(true)、否か(false,nil)
|
1632
|
-
#
|
1633
|
-
attr_accessor :calendar_era_props
|
1634
|
-
private :calendar_era_props=
|
1635
|
-
|
1636
|
-
# 暦年代名
|
1637
|
-
#
|
1638
|
-
# @return [String] 暦年代名
|
1639
|
-
#
|
1640
|
-
def calendar_era_name
|
1641
|
-
@calendar_era_props ? @calendar_era_props[0] : nil
|
1642
|
-
end
|
1643
|
-
alias :calendarEraName :calendar_era_name
|
1644
|
-
|
1645
|
-
# 暦年代元期
|
1646
|
-
#
|
1647
|
-
# @return [Integer] 使用する When::TM::Calendar で暦元に対応する年
|
1648
|
-
#
|
1649
|
-
def calendar_era_epoch
|
1650
|
-
@calendar_era_props ? @calendar_era_props[1] : 0
|
1651
|
-
end
|
1652
|
-
|
1653
|
-
# 暦年代正逆
|
1654
|
-
#
|
1655
|
-
# @return [Boolean] 年数が昇順(false,nil)か降順(true)か
|
1656
|
-
#
|
1657
|
-
def calendar_era_reverse
|
1658
|
-
@calendar_era_props ? @calendar_era_props[2] : false
|
1659
|
-
end
|
1660
|
-
|
1661
|
-
# 暦年代遡及
|
1662
|
-
#
|
1663
|
-
# @return [Boolean] 参照イベントより前の暦日か(true)、否か(false,nil)
|
1664
|
-
#
|
1665
|
-
def calendar_era_go_back
|
1666
|
-
@calendar_era_props ? @calendar_era_props[3] : false
|
1667
|
-
end
|
1668
|
-
|
1669
|
-
# 時法の取得 - ダミー
|
1670
|
-
def clock
|
1671
|
-
nil
|
1672
|
-
end
|
1673
|
-
|
1674
|
-
# 内部時間
|
1675
|
-
#
|
1676
|
-
# @return [Numeric]
|
1677
|
-
#
|
1678
|
-
# 当日正午の 1970-01-01T00:00:00Z からの Universal Coordinated Time の経過時間 / 128秒
|
1679
|
-
#
|
1680
|
-
def universal_time
|
1681
|
-
return super if [Now, Max, Min].include?(@indeterminated_position)
|
1682
|
-
@universal_time ||= JulianDate._d_to_t(to_i)
|
1683
|
-
end
|
1684
|
-
alias :local_time :universal_time
|
1685
|
-
|
1686
|
-
# ユリウス日
|
1687
|
-
#
|
1688
|
-
# @return [Integer]
|
1689
|
-
#
|
1690
|
-
# -4712-01-01からの経過日数に対応する通番
|
1691
|
-
#
|
1692
|
-
def to_i
|
1693
|
-
@sdn ||= _to_i
|
1694
|
-
end
|
1695
|
-
|
1696
|
-
#
|
1697
|
-
# 暦法上の通日
|
1698
|
-
#
|
1699
|
-
def _to_i
|
1700
|
-
void, epoch = @calendar_era_props
|
1701
|
-
if epoch
|
1702
|
-
date = @cal_date.dup
|
1703
|
-
date[0] += epoch
|
1704
|
-
else
|
1705
|
-
date = @cal_date
|
1706
|
-
end
|
1707
|
-
@frame.to_julian_date(date)
|
1708
|
-
end
|
1709
|
-
private :_to_i
|
1710
|
-
|
1711
|
-
# 剰余類化
|
1712
|
-
#
|
1713
|
-
# @param [Numeric] remainder 剰余
|
1714
|
-
# @param [Integer] divisor 法(>0)
|
1715
|
-
#
|
1716
|
-
# @return [When::Coordinates::Residue] 当日、当年を基準とする剰余類
|
1717
|
-
#
|
1718
|
-
def to_residue(remainder, divisor)
|
1719
|
-
When::Coordinates::Residue.new(remainder, divisor, {'day' => least_significant_coordinate,
|
1720
|
-
'year' => most_significant_coordinate})
|
1721
|
-
end
|
1722
|
-
|
1723
|
-
# 暦年代の削除
|
1724
|
-
#
|
1725
|
-
# @return [When::TM::CalDate] 暦年代を削除した When::TM::CalDate
|
1726
|
-
#
|
1727
|
-
def without_era
|
1728
|
-
target = dup
|
1729
|
-
return target unless calendar_era
|
1730
|
-
options = _attr
|
1731
|
-
options[:era] = nil
|
1732
|
-
options[:era_name] = nil
|
1733
|
-
options[:date] = cal_date.dup
|
1734
|
-
options[:date][0] += calendar_era_epoch
|
1735
|
-
target._copy(options)
|
1736
|
-
end
|
1737
|
-
|
1738
|
-
# 要素の参照
|
1739
|
-
#
|
1740
|
-
# @param [Integer, String] index 参照する要素の指定
|
1741
|
-
#
|
1742
|
-
# @return [Numeric]
|
1743
|
-
#
|
1744
|
-
def value(index)
|
1745
|
-
@cal_date[(_digit(index) {|digit| digit <= DAY})-1]
|
1746
|
-
end
|
1747
|
-
|
1748
|
-
#
|
1749
|
-
# 最上位の要素
|
1750
|
-
#
|
1751
|
-
# @return [Numeric] 暦年代の epoch に関わらず暦法に従った年の通し番号を返す
|
1752
|
-
#
|
1753
|
-
def most_significant_coordinate
|
1754
|
-
coordinate = @cal_date[0]
|
1755
|
-
coordinate += calendar_era_epoch if @calendar_era_props
|
1756
|
-
@frame.index_of_MSC.times do |i|
|
1757
|
-
coordinate = +coordinate * @frame.indices[i].unit + @cal_date[i+1] - @frame.indices[i].base
|
1758
|
-
end
|
1759
|
-
coordinate
|
1760
|
-
end
|
1761
|
-
|
1762
|
-
#
|
1763
|
-
# 最下位の要素
|
1764
|
-
#
|
1765
|
-
# @return [Numeric] 剰余類の演算に用いる日の通し番号を返す
|
1766
|
-
#
|
1767
|
-
def least_significant_coordinate
|
1768
|
-
return to_i + @frame.indices[-1].shift
|
1769
|
-
end
|
1770
|
-
|
1771
|
-
# ユリウス日または通年が指定の剰余となる日
|
1772
|
-
#
|
1773
|
-
# @param [When::Coordinates::Residue] other
|
1774
|
-
#
|
1775
|
-
# @return [When::TM::CalDate]
|
1776
|
-
#
|
1777
|
-
def &(other)
|
1778
|
-
raise TypeError,"The right operand should be When::Coordinates::Residue" unless other.kind_of?(Residue)
|
1779
|
-
case other.event
|
1780
|
-
when 'day'
|
1781
|
-
# 指定の剰余となる日
|
1782
|
-
sdn = other & to_i
|
1783
|
-
options = {:date=>_date_with_era(@frame.to_cal_date(sdn)), :events=>nil, :query=>@query, :validate=>:done}
|
1784
|
-
options[:precision] = When::DAY if precision < When::DAY
|
1785
|
-
result = self.dup._copy(options)
|
1786
|
-
result.send(:_force_euqal_day, sdn-result.to_i)
|
1787
|
-
|
1788
|
-
when 'year'
|
1789
|
-
# 指定の剰余となる年
|
1790
|
-
date = @frame.send(:_decode, _date_without_era)
|
1791
|
-
date[0] = (other & (date[0] + @frame.diff_to_CE)) - @frame.diff_to_CE
|
1792
|
-
options = {:date=>_date_with_era(@frame.send(:_encode, date)), :events=>nil, :query=>@query}
|
1793
|
-
options[:precision] = When::YEAR if precision < When::YEAR
|
1794
|
-
return self.dup._copy(options)
|
1795
|
-
|
1796
|
-
else
|
1797
|
-
raise ArgumentError,"The right operand should have a unit 'day' or 'year'"
|
1798
|
-
end
|
1799
|
-
end
|
1800
|
-
|
1801
|
-
# ユリウス日または通年の剰余
|
1802
|
-
#
|
1803
|
-
# @param [When::Coordinates::Residue] other
|
1804
|
-
#
|
1805
|
-
# @return [Numeric]
|
1806
|
-
#
|
1807
|
-
def %(other)
|
1808
|
-
raise TypeError,"The right operand should be When::Coordinates::Residue" unless other.kind_of?(Residue)
|
1809
|
-
if precision <= When::YEAR && other.units['year'] && other.event != 'year'
|
1810
|
-
other.to('year') % (most_significant_coordinate + @frame.epoch_in_CE)
|
1811
|
-
else
|
1812
|
-
case other.event
|
1813
|
-
when 'day' ; other % least_significant_coordinate
|
1814
|
-
when 'year' ; other % (most_significant_coordinate + @frame.epoch_in_CE)
|
1815
|
-
else ; raise ArgumentError,"The right operand should have a unit 'day' or 'year'"
|
1816
|
-
end
|
1817
|
-
end
|
1818
|
-
end
|
1819
|
-
|
1820
|
-
# 下位桁の切り捨て
|
1821
|
-
#
|
1822
|
-
# @param [Integer] digit 切り捨てずに残す、最下位の桁
|
1823
|
-
#
|
1824
|
-
# @param [Integer] precision 切り捨て結果の分解能
|
1825
|
-
#
|
1826
|
-
# @return [When::TM::CalDate]
|
1827
|
-
#
|
1828
|
-
def floor(digit=DAY, precision=digit)
|
1829
|
-
options = {:date=>@cal_date[0..(digit-1)], :events=>nil, :query=>nil}
|
1830
|
-
options[:precision] = precision if precision
|
1831
|
-
self.dup._copy(options)
|
1832
|
-
end
|
1833
|
-
|
1834
|
-
# 下位桁の切り上げ
|
1835
|
-
#
|
1836
|
-
# @param [Integer] digit 切り上げずに残す、最下位の桁
|
1837
|
-
#
|
1838
|
-
# @param [Integer] precision 切り上げ結果の分解能
|
1839
|
-
#
|
1840
|
-
# @return [When::TM::CalDate]
|
1841
|
-
#
|
1842
|
-
def ceil(digit=DAY, precision=digit)
|
1843
|
-
(self + PeriodDuration.new(1, digit, (-@frame.indices.length)..0)).floor(digit, precision)
|
1844
|
-
end
|
1845
|
-
|
1846
|
-
# 要素数 ― 上位要素に含まれる下位要素の数
|
1847
|
-
#
|
1848
|
-
# @param [Integer] upper 上位要素のインデックス
|
1849
|
-
# @param [Integer] lower 下位要素のインデックス(DAY または MONTH)
|
1850
|
-
#
|
1851
|
-
# @return [Integer]
|
1852
|
-
#
|
1853
|
-
def length(upper, lower=DAY)
|
1854
|
-
range = [floor(upper).to_i, ceil(upper).to_i]
|
1855
|
-
range = range.map {|d| (Residue.mod(d) {|m| frame._new_month(m)})[0]} if lower == MONTH
|
1856
|
-
range[1] - range[0]
|
1857
|
-
end
|
1858
|
-
|
1859
|
-
# 時刻情報のない When::TM::CalDate を返す
|
1860
|
-
#
|
1861
|
-
# @return [When::TM::CalDate]
|
1862
|
-
#
|
1863
|
-
alias :to_cal_date :dup
|
1864
|
-
alias :to_CalDate :to_cal_date
|
1865
|
-
|
1866
|
-
# 暦年代が末端の参照であるか?
|
1867
|
-
#
|
1868
|
-
# @return [Boolean]
|
1869
|
-
#
|
1870
|
-
def leaf?
|
1871
|
-
! @calendar_era.respond_to?(:_pool) || @calendar_era.leaf?
|
1872
|
-
end
|
1873
|
-
|
1874
|
-
# 属性の Hash
|
1875
|
-
# @private
|
1876
|
-
def _attr
|
1877
|
-
super.merge({:era_name=>@calendar_era_props, :era=>@calendar_era})
|
1878
|
-
end
|
1879
|
-
protected
|
1880
|
-
|
1881
|
-
# 属性のコピー
|
1882
|
-
# @private
|
1883
|
-
def _copy(options={})
|
1884
|
-
@cal_date = options[:date] if options.key?(:date)
|
1885
|
-
@calendar_era = options[:era] if options.key?(:era)
|
1886
|
-
@calendar_era_props = options[:era_name] if options.key?(:era_name)
|
1887
|
-
return super
|
1888
|
-
end
|
1889
|
-
|
1890
|
-
# オブジェクトの生成
|
1891
|
-
#
|
1892
|
-
# @param [Array<Numeric>] date 日付表現
|
1893
|
-
#
|
1894
|
-
# @param [Hash] options 下記の通り (see also {When::TM::TemporalPosition._instance})
|
1895
|
-
# @option options [When::TM::Calendar] :frame
|
1896
|
-
# @option options [When::TM::CalendarEra, When::BasicTypes::M17n, Array<When::BasicTypes::M17n, Integer>] :era_name
|
1897
|
-
# (Integer は 当該年号の 0 年に相当する通年)
|
1898
|
-
# @option options [Integer] :precision
|
1899
|
-
#
|
1900
|
-
def initialize(date, options={})
|
1901
|
-
# 年号 & 日付
|
1902
|
-
@calendar_era_props = options[:era_name]
|
1903
|
-
@calendar_era = options[:era]
|
1904
|
-
@cal_date = date
|
1905
|
-
|
1906
|
-
super(options)
|
1907
|
-
end
|
1908
|
-
|
1909
|
-
private
|
1910
|
-
|
1911
|
-
# オブジェクトの正規化
|
1912
|
-
def _normalize(options={})
|
1913
|
-
|
1914
|
-
# 日付配列の長さ
|
1915
|
-
cal_date_index = @cal_date.compact.length
|
1916
|
-
|
1917
|
-
# 日付の正規化
|
1918
|
-
if @calendar_era_props
|
1919
|
-
# Calendar Era がある場合
|
1920
|
-
trans_options = @trans || {} # TODO? 消す
|
1921
|
-
count = trans_options[:count] || 1
|
1922
|
-
query_options = (@query || {}).dup
|
1923
|
-
query_options[:label] = @calendar_era_props
|
1924
|
-
query_options[:count] = count
|
1925
|
-
era = date = nil
|
1926
|
-
if @calendar_era
|
1927
|
-
era, date = _search_era(@calendar_era, trans_options)
|
1928
|
-
else
|
1929
|
-
eras = CalendarEra._instance(query_options)
|
1930
|
-
raise ArgumentError, "CalendarEraName doesn't exist: #{query_options[:label]}" if eras.empty?
|
1931
|
-
eras.each do |e|
|
1932
|
-
era, date = _search_era(e, trans_options)
|
1933
|
-
next unless era
|
1934
|
-
count -= 1
|
1935
|
-
break unless count > 0
|
1936
|
-
end
|
1937
|
-
end
|
1938
|
-
raise RangeError, "Out of CalendarEra Range" unless era
|
1939
|
-
@calendar_era_props = date.calendar_era_props
|
1940
|
-
@calendar_era = era
|
1941
|
-
@cal_date = date.cal_date
|
1942
|
-
@frame = date.frame
|
1943
|
-
@query = (@query||{}).merge(date.query)
|
1944
|
-
@trans = (@trans||{}).merge(date.trans)
|
1945
|
-
@keys |= calendar_era_name.keys | @frame.keys
|
1946
|
-
else
|
1947
|
-
# Calendar Era がない場合
|
1948
|
-
@frame = When.Resource(options[:frame] || @frame || 'Gregorian', '_c:')
|
1949
|
-
@cal_date = @frame._validate(@cal_date) unless options[:validate] == :done
|
1950
|
-
@keys |= @frame.keys
|
1951
|
-
end
|
1952
|
-
|
1953
|
-
# 分解能
|
1954
|
-
precision = options.delete(:precision) || @precision
|
1955
|
-
cal_date_index =
|
1956
|
-
case options.delete(:_format)
|
1957
|
-
when :century ; CENTURY
|
1958
|
-
when :week, :day ; DAY
|
1959
|
-
else ; cal_date_index - (@frame.indices.length + 1)
|
1960
|
-
end
|
1961
|
-
precision ||= cal_date_index if cal_date_index < DAY
|
1962
|
-
precision ||= @clk_time.precision if @clk_time
|
1963
|
-
@precision = Index.precision(precision || DAY)
|
1964
|
-
end
|
1965
|
-
|
1966
|
-
# 暦年代を探す
|
1967
|
-
def _search_era(era, trans_options)
|
1968
|
-
cal_date = @cal_date.dup
|
1969
|
-
cal_date[0] = -cal_date[0] if era.reverse?
|
1970
|
-
cal_date[0] += era.epoch_year
|
1971
|
-
date = era.trans(cal_date, trans_options)
|
1972
|
-
loop do
|
1973
|
-
case date
|
1974
|
-
when Before, After
|
1975
|
-
i0, i1, reverse = SearchOption[date]
|
1976
|
-
new_era = (date == Before) ? era.prev : era.succ
|
1977
|
-
break unless new_era
|
1978
|
-
date = new_era.trans(cal_date, trans_options)
|
1979
|
-
if date == reverse
|
1980
|
-
cal_date = new_era.epoch[i0].frame.to_cal_date(era.epoch[i1].frame.to_julian_date(cal_date))
|
1981
|
-
date = new_era.trans(cal_date, trans_options)
|
1982
|
-
break if date == reverse
|
1983
|
-
end
|
1984
|
-
era = new_era
|
1985
|
-
when TimeValue
|
1986
|
-
return era, date
|
1987
|
-
else
|
1988
|
-
break
|
1989
|
-
end
|
1990
|
-
end
|
1991
|
-
return nil
|
1992
|
-
end
|
1993
|
-
|
1994
|
-
# 加減算共通処理
|
1995
|
-
def _plus(period)
|
1996
|
-
_frame_adjust(period, self.dup._copy({:date=>_date_with_era(@frame._validate(_date_without_era,
|
1997
|
-
@frame._arrange_length(period.date))),
|
1998
|
-
:events=>nil, :query=>nil, :validate=>:done}))
|
1999
|
-
end
|
2000
|
-
|
2001
|
-
# 年号を除外した @frame の暦法に対応する日付
|
2002
|
-
def _date_without_era
|
2003
|
-
date = @cal_date.dup
|
2004
|
-
date[0] += calendar_era_epoch if @calendar_era_props
|
2005
|
-
date
|
2006
|
-
end
|
2007
|
-
|
2008
|
-
# 年号に続く日付
|
2009
|
-
def _date_with_era(date)
|
2010
|
-
date[0] -= calendar_era_epoch if @calendar_era_props
|
2011
|
-
date
|
2012
|
-
end
|
2013
|
-
|
2014
|
-
# 暦法が変わった場合の補正
|
2015
|
-
def _frame_adjust(period, date)
|
2016
|
-
return date if @frame.equal?(date.frame) || (period.to_day||0) == 0
|
2017
|
-
diff = period.to_day - (date.to_i - to_i)
|
2018
|
-
return date if diff == 0
|
2019
|
-
date.send(:_force_euqal_day, diff)
|
2020
|
-
end
|
2021
|
-
end
|
2022
|
-
|
2023
|
-
#
|
2024
|
-
# 時刻を伴った日付
|
2025
|
-
#
|
2026
|
-
# see {http://schemas.opengis.net/gml/3.1.1/base/temporalAppendix.xsd#DateAndTimeType gml schema}
|
2027
|
-
#
|
2028
|
-
class DateAndTime < CalDate
|
2029
|
-
|
2030
|
-
# 時刻要素
|
2031
|
-
#
|
2032
|
-
# @return [When::TM::ClockTime]
|
2033
|
-
#
|
2034
|
-
attr_reader :clk_time
|
2035
|
-
alias :clkTime :clk_time
|
2036
|
-
|
2037
|
-
# 時法の取得
|
2038
|
-
#
|
2039
|
-
# @return [When::TM::Clock]
|
2040
|
-
#
|
2041
|
-
def clock
|
2042
|
-
@clk_time.frame
|
2043
|
-
end
|
2044
|
-
|
2045
|
-
# 内部時間
|
2046
|
-
#
|
2047
|
-
# @return [Numeric]
|
2048
|
-
#
|
2049
|
-
# 1970-01-01T00:00:00Z からの Universal Coordinated Time の経過時間 / 128秒
|
2050
|
-
#
|
2051
|
-
# 暦法によっては、異なる意味を持つことがある
|
2052
|
-
#
|
2053
|
-
def universal_time
|
2054
|
-
return super if [Now, Max, Min].include?(@indeterminated_position)
|
2055
|
-
raise NameError, "Temporal Reference System is not defined" unless (@frame && clock)
|
2056
|
-
@universal_time ||= (to_i - JulianDate::JD19700101) * Duration::DAY + @clk_time.universal_time(to_i)
|
2057
|
-
end
|
2058
|
-
|
2059
|
-
# 内部時間(ローカル)
|
2060
|
-
#
|
2061
|
-
# @return [Numeric]
|
2062
|
-
#
|
2063
|
-
# 1970-01-01T00:00:00(ローカル) からの Universal Coordinated Time の経過時間 / 128秒
|
2064
|
-
#
|
2065
|
-
# 暦法によっては、異なる意味を持つことがある
|
2066
|
-
#
|
2067
|
-
def local_time
|
2068
|
-
return super if [Now, Max, Min].include?(@indeterminated_position)
|
2069
|
-
raise NameError, "Temporal Reference System is not defined" unless (@frame && clock)
|
2070
|
-
@local_time ||= (to_i - JulianDate::JD19700101) * Duration::DAY + @clk_time.local_time(to_i)
|
2071
|
-
end
|
2072
|
-
|
2073
|
-
# 要素の参照
|
2074
|
-
#
|
2075
|
-
# @param [Integer] index 参照する要素の指定
|
2076
|
-
#
|
2077
|
-
# @return [Numeric]
|
2078
|
-
#
|
2079
|
-
def value(index)
|
2080
|
-
digit = _digit(index)
|
2081
|
-
return (digit <= DAY) ? @cal_date[digit-1] : @clk_time.clk_time[digit]
|
2082
|
-
end
|
2083
|
-
|
2084
|
-
# ユリウス日または通年が指定の剰余となる日
|
2085
|
-
#
|
2086
|
-
# @param [When::Coordinates::Residue] other
|
2087
|
-
#
|
2088
|
-
# @return [When::TM::DateAndTime]
|
2089
|
-
#
|
2090
|
-
def &(other)
|
2091
|
-
raise TypeError,"The right operand should be When::Coordinates::Residue" unless other.kind_of?(Residue)
|
2092
|
-
case other.event
|
2093
|
-
when 'day'
|
2094
|
-
# 指定の剰余となる日
|
2095
|
-
sdn = other & to_i
|
2096
|
-
options = {:date=>_date_with_era(@frame.to_cal_date(sdn)), :time=>@clk_time.clk_time.dup,
|
2097
|
-
:events=>nil, :query=>@query, :validate=>:done}
|
2098
|
-
options[:precision] = When::DAY if precision < When::DAY
|
2099
|
-
result = self.dup._copy(options)
|
2100
|
-
result.send(:_force_euqal_day, sdn-result.to_i)
|
2101
|
-
|
2102
|
-
when 'year'
|
2103
|
-
# 指定の剰余となる年
|
2104
|
-
date = @frame.send(:_decode, _date_without_era)
|
2105
|
-
date[0] = (other & (date[0] + @frame.diff_to_CE)) - @frame.diff_to_CE
|
2106
|
-
options = {:date=>_date_with_era(@frame.send(:_encode, date)), :time=>@clk_time.clk_time.dup,
|
2107
|
-
:events=>nil, :query=>@query}
|
2108
|
-
options[:precision] = When::YEAR if precision < When::YEAR
|
2109
|
-
return self.dup._copy(options)
|
2110
|
-
|
2111
|
-
else
|
2112
|
-
raise ArgumentError,"The right operand should have a unit 'day' or 'year'"
|
2113
|
-
end
|
2114
|
-
end
|
2115
|
-
|
2116
|
-
# 下位桁の切り捨て
|
2117
|
-
#
|
2118
|
-
# @param [Integer] digit 切り捨てずに残す、最下位の桁
|
2119
|
-
#
|
2120
|
-
# @param [Integer] precision 切り捨て結果の分解能
|
2121
|
-
#
|
2122
|
-
# @return [When::TM::DateAndTime]
|
2123
|
-
#
|
2124
|
-
def floor(digit=DAY, precision=digit)
|
2125
|
-
count = digit - clock.indices.length
|
2126
|
-
|
2127
|
-
if digit>=DAY
|
2128
|
-
date = @cal_date.dup
|
2129
|
-
elsif @calendar_era_props
|
2130
|
-
date = @cal_date.dup
|
2131
|
-
date[0] += calendar_era_epoch
|
2132
|
-
date = @frame._validate(date[0..(digit-1)])
|
2133
|
-
date[0] -= calendar_era_epoch
|
2134
|
-
else
|
2135
|
-
date = @frame._validate(@cal_date[0..(digit-1)])
|
2136
|
-
end
|
2137
|
-
|
2138
|
-
time = @clk_time.clk_time[0..((digit<=DAY) ? 0 : ((count>=0) ? -1 : digit))]
|
2139
|
-
time[0] += to_i
|
2140
|
-
time = clock._validate(time)
|
2141
|
-
time[0] -= to_i
|
2142
|
-
|
2143
|
-
if (count >= 0)
|
2144
|
-
factor = 10**count
|
2145
|
-
time[-1] = (time[-1] * factor).floor.to_f / factor
|
2146
|
-
end
|
2147
|
-
|
2148
|
-
# オブジェクトの生成
|
2149
|
-
options = {:date=>date, :validate=>:done, :events=>nil, :query=>nil,
|
2150
|
-
:time=>(digit<=DAY) ? time : @clk_time.dup._copy({:time=>time})}
|
2151
|
-
options[:precision] = precision if precision
|
2152
|
-
return self.dup._copy(options)
|
2153
|
-
end
|
2154
|
-
|
2155
|
-
# 下位桁の切り上げ
|
2156
|
-
#
|
2157
|
-
# @param [Integer] digit 切り上げずに残す、最下位の桁
|
2158
|
-
#
|
2159
|
-
# @param [Integer] precision 切り上げ結果の分解能
|
2160
|
-
#
|
2161
|
-
# @return [When::TM::DateAndTime]
|
2162
|
-
#
|
2163
|
-
def ceil(digit=DAY, precision=digit)
|
2164
|
-
length = clock.indices.length
|
2165
|
-
count = digit - length
|
2166
|
-
period = PeriodDuration.new((count<=0) ? 1 : 0.1**count, digit, (-@frame.indices.length)..length)
|
2167
|
-
result = floor(digit, precision) + period
|
2168
|
-
result += clock.tz_difference if (result.universal_time <= self.universal_time)
|
2169
|
-
return result
|
2170
|
-
end
|
2171
|
-
|
2172
|
-
# 位置情報
|
2173
|
-
#
|
2174
|
-
# @return [When::Coordinates::Spatial]
|
2175
|
-
#
|
2176
|
-
def location
|
2177
|
-
@location ||= @clk_time.frame.location
|
2178
|
-
end
|
2179
|
-
|
2180
|
-
# 時刻情報のない When::TM::CalDate を返す
|
2181
|
-
#
|
2182
|
-
# @return [When::TM::CalDate]
|
2183
|
-
#
|
2184
|
-
def to_cal_date
|
2185
|
-
options = _attr
|
2186
|
-
options.delete(:clock)
|
2187
|
-
options[:precision] = [When::DAY, options[:precision]].min
|
2188
|
-
CalDate.new(@cal_date, options)
|
2189
|
-
end
|
2190
|
-
alias :to_CalDate :to_cal_date
|
2191
|
-
|
2192
|
-
# 標準ライブラリの DateTime オブジェクトへの変換
|
2193
|
-
#
|
2194
|
-
alias :to_date_or_datetime :to_datetime
|
2195
|
-
|
2196
|
-
#protected
|
2197
|
-
|
2198
|
-
# 属性の Hash
|
2199
|
-
# @private
|
2200
|
-
def _attr
|
2201
|
-
super.merge({:clock=>clock})
|
2202
|
-
end
|
2203
|
-
|
2204
|
-
# 属性のコピー
|
2205
|
-
# @private
|
2206
|
-
def _copy(options={})
|
2207
|
-
# 夏時間の調整
|
2208
|
-
case options[:time]
|
2209
|
-
when Array
|
2210
|
-
if clock._need_validate
|
2211
|
-
if @calendar_era_props
|
2212
|
-
date = options[:date].dup
|
2213
|
-
date[0] += calendar_era_epoch
|
2214
|
-
else
|
2215
|
-
date = options[:date]
|
2216
|
-
end
|
2217
|
-
new_clock = clock._daylight([@frame, date, options[:time]])
|
2218
|
-
options[:time] = options[:time].map {|t| t * 1}
|
2219
|
-
else
|
2220
|
-
new_clock = clock
|
2221
|
-
end
|
2222
|
-
options[:time] = @clk_time.dup._copy(options.merge({:clock=>new_clock}))
|
2223
|
-
when nil
|
2224
|
-
options[:time] = @clk_time.dup._copy(options)
|
2225
|
-
end
|
2226
|
-
|
2227
|
-
return super(options)
|
2228
|
-
end
|
2229
|
-
|
2230
|
-
# オブジェクトの生成
|
2231
|
-
#
|
2232
|
-
# @param [Array<Numeric>] date 日付表現
|
2233
|
-
# @param [Array<Numeric>] time 時刻表現
|
2234
|
-
# @param [Hash] options 下記の通り (see also {When::TM::TemporalPosition._instance})
|
2235
|
-
# @option options [When::TM::Calendar] :frame
|
2236
|
-
# @option options [When::TM::Clock] :clock
|
2237
|
-
# @option options [When::TM::CalendarEra, When::BasicTypes::M17n, Array<When::BasicTypes::M17n, Integer>] :era_name
|
2238
|
-
# (Integer は 当該年号の 0 年に相当する通年)
|
2239
|
-
# @option options [Integer] :precision
|
2240
|
-
#
|
2241
|
-
def initialize(date, time, options={})
|
2242
|
-
options[:time] = time
|
2243
|
-
super(date, options)
|
2244
|
-
end
|
2245
|
-
|
2246
|
-
private
|
2247
|
-
|
2248
|
-
# オブジェクトの正規化
|
2249
|
-
def _normalize(options={})
|
2250
|
-
|
2251
|
-
# Clock
|
2252
|
-
unless options[:validate]
|
2253
|
-
clock = Clock.get_clock_option(options)
|
2254
|
-
clock ||= options[:time].frame if options[:time].kind_of?(ClockTime)
|
2255
|
-
clock ||= Clock.local_time
|
2256
|
-
end
|
2257
|
-
clock = When.Clock(clock) if clock.kind_of?(String)
|
2258
|
-
clock_is_timezone = clock && !clock.kind_of?(When::TM::Clock)
|
2259
|
-
clock = clock.daylight if clock_is_timezone
|
2260
|
-
|
2261
|
-
# ClockTime
|
2262
|
-
@clk_time =
|
2263
|
-
case options[:time]
|
2264
|
-
when ClockTime ; options[:time]
|
2265
|
-
when Array ; ClockTime.new(options[:time], {:frame=>clock, :precision=>options[:precision], :validate=>:done})
|
2266
|
-
else ; clock.to_clk_time(options[:time], {:precision=>options[:precision]})
|
2267
|
-
end
|
2268
|
-
|
2269
|
-
super
|
2270
|
-
|
2271
|
-
# 日付と時刻の正規化
|
2272
|
-
unless options[:validate]
|
2273
|
-
time = @clk_time.clk_time
|
2274
|
-
precision = @clk_time.precision
|
2275
|
-
second = time[clock.base.length-1]
|
2276
|
-
second -= clock.base[-1] if second
|
2277
|
-
if second && second != 0 && time_standard.has_leap?
|
2278
|
-
zero = DateAndTime.new(@cal_date, time[0..-2],
|
2279
|
-
{:frame=>@frame, :clock=>clock, :precision=>precision,
|
2280
|
-
:era_name=>@calendar_era_props, :era=>options[:era],
|
2281
|
-
:time_standard=>time_standard, :location=>@location})
|
2282
|
-
end
|
2283
|
-
|
2284
|
-
# 日付と時刻の関係の調整
|
2285
|
-
@cal_date = _date_with_era(@frame._validate(_date_without_era) {|jdn|
|
2286
|
-
time[0] += jdn
|
2287
|
-
time[0..-1] = clock._validate(time)
|
2288
|
-
jdn = time[0] * 1
|
2289
|
-
time[0] -= jdn
|
2290
|
-
jdn
|
2291
|
-
})
|
2292
|
-
|
2293
|
-
# 夏時間の調整
|
2294
|
-
if clock._need_validate
|
2295
|
-
if @calendar_era_props
|
2296
|
-
cal_date = @cal_date.dup
|
2297
|
-
cal_date[0] += calendar_era_epoch
|
2298
|
-
else
|
2299
|
-
cal_date = @cal_date
|
2300
|
-
end
|
2301
|
-
clock = clock._daylight([@frame, cal_date, time])
|
2302
|
-
end
|
2303
|
-
time = [time[0]] + time[1..-1].map {|t| t * 1}
|
2304
|
-
@clk_time = ClockTime.new(time, {:frame=>clock, :precision=>precision, :validate=>:done}) if clock_is_timezone
|
2305
|
-
|
2306
|
-
# 閏秒
|
2307
|
-
if zero
|
2308
|
-
leap = ((dynamical_time - zero.dynamical_time) * clock.second - second).to_i
|
2309
|
-
if leap != 0 && leap.abs < clock.second
|
2310
|
-
@cal_date = zero.cal_date
|
2311
|
-
@clk_time = zero.clk_time
|
2312
|
-
@clk_time.clk_time[-1] += second
|
2313
|
-
leap /= clock.second
|
2314
|
-
@universal_time = @local_time = When::Coordinates::LeapSeconds.new(@local_time-leap, leap, 1/clock.second)
|
2315
|
-
@dynamical_time -= leap
|
2316
|
-
end
|
2317
|
-
end
|
2318
|
-
end
|
2319
|
-
|
2320
|
-
# 後処理
|
2321
|
-
@keys |= @clk_time.keys
|
2322
|
-
end
|
2323
|
-
|
2324
|
-
# 加減算共通処理
|
2325
|
-
def _plus(period)
|
2326
|
-
# 日時の加算
|
2327
|
-
time = @clk_time.clk_time.dup
|
2328
|
-
pdate = @frame._arrange_length(period.date)
|
2329
|
-
ptime = clock._arrange_length(period.time)
|
2330
|
-
date = _date_with_era(@frame._validate(_date_without_era, pdate) {|jdn|
|
2331
|
-
time[0] += jdn
|
2332
|
-
time = clock._validate(time, ptime)
|
2333
|
-
jdn = time[0] * 1
|
2334
|
-
time[0] -= jdn
|
2335
|
-
jdn
|
2336
|
-
})
|
2337
|
-
|
2338
|
-
# オブジェクトの生成
|
2339
|
-
_frame_adjust(period, self.dup._copy({:date=>date, :time=>time, :validate=>:done, :events=>nil, :query=>nil}))
|
2340
|
-
end
|
2341
|
-
end
|
2342
1235
|
end
|