when_exe 0.3.7 → 0.3.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (108) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +210 -171
  3. data/bin/irb.rc +1 -0
  4. data/lib/when_exe.rb +78 -53
  5. data/lib/when_exe/basictypes.rb +27 -8
  6. data/lib/when_exe/calendarnote.rb +848 -805
  7. data/lib/when_exe/calendartypes.rb +110 -240
  8. data/lib/when_exe/coordinates.rb +2440 -2175
  9. data/lib/when_exe/core/compatibility.rb +1 -1
  10. data/lib/when_exe/core/duration.rb +13 -11
  11. data/lib/when_exe/core/extension.rb +38 -45
  12. data/lib/when_exe/ephemeris.rb +43 -14
  13. data/lib/when_exe/ephemeris/eclipse.rb +149 -0
  14. data/lib/when_exe/ephemeris/notes.rb +39 -7
  15. data/lib/when_exe/icalendar.rb +2 -6
  16. data/lib/when_exe/inspect.rb +1408 -1399
  17. data/lib/when_exe/parts/enumerator.rb +486 -477
  18. data/lib/when_exe/parts/resource.rb +1101 -1069
  19. data/lib/when_exe/parts/timezone.rb +6 -5
  20. data/lib/when_exe/region/babylonian.rb +405 -405
  21. data/lib/when_exe/region/bahai.rb +21 -61
  22. data/lib/when_exe/region/chinese/epochs.rb +81 -81
  23. data/lib/when_exe/region/chinese/twins.rb +51 -51
  24. data/lib/when_exe/region/christian.rb +7 -2
  25. data/lib/when_exe/region/coptic.rb +1 -1
  26. data/lib/when_exe/region/discordian.rb +9 -16
  27. data/lib/when_exe/region/french.rb +1 -1
  28. data/lib/when_exe/region/hanke_henry.rb +57 -0
  29. data/lib/when_exe/region/indian.rb +41 -73
  30. data/lib/when_exe/region/international_fixed.rb +97 -0
  31. data/lib/when_exe/region/iranian.rb +203 -203
  32. data/lib/when_exe/region/japanese.rb +13 -13
  33. data/lib/when_exe/region/japanese/eclipses.rb +1194 -0
  34. data/lib/when_exe/region/japanese/notes.rb +1482 -1383
  35. data/lib/when_exe/region/japanese/residues.rb +726 -721
  36. data/lib/when_exe/region/japanese/twins.rb +37 -37
  37. data/lib/when_exe/region/jewish.rb +2 -2
  38. data/lib/when_exe/region/pax.rb +60 -0
  39. data/lib/when_exe/region/positivist.rb +100 -0
  40. data/lib/when_exe/region/roman.rb +333 -334
  41. data/lib/when_exe/region/shire.rb +3 -20
  42. data/lib/when_exe/region/thai.rb +2 -2
  43. data/lib/when_exe/region/tibetan.rb +3 -3
  44. data/lib/when_exe/region/tranquility.rb +208 -0
  45. data/lib/when_exe/region/vanishing_leprechaun.rb +53 -0
  46. data/lib/when_exe/region/vietnamese.rb +4 -4
  47. data/lib/when_exe/region/world.rb +9 -13
  48. data/lib/when_exe/region/world_season.rb +89 -0
  49. data/lib/when_exe/region/zoroastrian.rb +4 -2
  50. data/lib/when_exe/tmobjects.rb +14 -4
  51. data/lib/when_exe/tmposition.rb +239 -81
  52. data/lib/when_exe/tmreference.rb +57 -28
  53. data/lib/when_exe/version.rb +1 -1
  54. data/link_to_online_documents +6 -3
  55. data/test/examples/today.rb +1 -1
  56. data/test/scripts.rb +23 -0
  57. data/test/scripts/2.ext.rb +169 -0
  58. data/test/scripts/2.rb +169 -0
  59. data/test/scripts/3.ext.rb +133 -0
  60. data/test/scripts/3.rb +134 -0
  61. data/test/scripts/4.ext.rb +112 -0
  62. data/test/scripts/4.min.rb +65 -0
  63. data/test/scripts/4.rb +136 -0
  64. data/test/scripts/5.ext.rb +78 -0
  65. data/test/scripts/5.rb +81 -0
  66. data/test/scripts/6.gcal.rb +131 -0
  67. data/test/scripts/6.rb +205 -0
  68. data/test/scripts/6.tz.rb +105 -0
  69. data/test/scripts/7.phase.rb +109 -0
  70. data/test/scripts/7.rb +95 -0
  71. data/test/scripts/7.term.rb +128 -0
  72. data/test/scripts/7.week.rb +84 -0
  73. data/test/scripts/8.ext.rb +61 -0
  74. data/test/scripts/8.rb +62 -0
  75. data/test/scripts/9.ext.rb +131 -0
  76. data/test/scripts/9.rb +130 -0
  77. data/test/scripts/chinese-luni-solar.rb +52 -0
  78. data/test/{examples → scripts}/geometric_complex.rb +41 -41
  79. data/test/scripts/geometric_complex.txt +18 -0
  80. data/test/scripts/korea.rb +59 -0
  81. data/test/scripts/thai-reviewed.txt +211 -0
  82. data/test/scripts/thai.rb +36 -0
  83. data/test/scripts/thai.txt +210 -0
  84. data/test/test.rb +7 -0
  85. data/test/test/basictypes.rb +22 -0
  86. data/test/test/coordinates.rb +2 -1
  87. data/test/test/ephemeris.rb +34 -2
  88. data/test/test/icalendar.rb +12 -0
  89. data/test/test/inspect.rb +37 -1
  90. data/test/test/parts.rb +4 -3
  91. data/test/test/region/armenian.rb +20 -0
  92. data/test/test/region/bahai.rb +58 -0
  93. data/test/test/region/chinese.rb +14 -3
  94. data/test/test/region/christian.rb +16 -35
  95. data/test/test/region/discordian.rb +20 -0
  96. data/test/test/region/indian.rb +30 -2
  97. data/test/test/region/japanese.rb +24 -0
  98. data/test/test/region/jewish.rb +2 -0
  99. data/test/test/region/m17n.rb +9 -0
  100. data/test/test/region/reforms.rb +121 -0
  101. data/test/test/region/residue.rb +17 -11
  102. data/test/test/region/shire.rb +58 -0
  103. data/test/test/region/swedish.rb +45 -0
  104. data/test/test/region/zoroastrian.rb +58 -0
  105. data/test/test/tmobjects.rb +74 -0
  106. data/test/test/tmposition.rb +468 -397
  107. data/when_exe.gemspec +2 -2
  108. metadata +49 -6
@@ -185,14 +185,16 @@ module When
185
185
  Fasli = [{'Epoch'=>{
186
186
  'ZRE'=>{'origin_of_MSC'=>1737},
187
187
  'YZ' =>{'origin_of_MSC'=>-630}
188
- }}, Bahai, {
188
+ }}, TableBasedWithSunset, {
189
189
  'label' => 'Zoroastrian::Fasli',
190
190
  'indices' => [
191
191
  When.Index('ZoroastrianNotes::month::Month', {:unit =>13}),
192
192
  When::Coordinates::DefaultDayIndex
193
193
  ],
194
194
  'origin_of_MSC' => -630,
195
- 'epoch_in_CE' => 0,
195
+ 'diff_to_CE' => 0,
196
+ 'engine_month' => 3,
197
+ 'engine_day' => 21,
196
198
  'rule_table' => {
197
199
  365 => {'Length'=>[30] * 12 + [5]},
198
200
  366 => {'Length'=>[30] * 12 + [6]}
@@ -569,7 +569,12 @@ module When::TM
569
569
  value = @current
570
570
  @current = (@count_limit.kind_of?(Numeric) && @count >= @count_limit) ? nil :
571
571
  (@current==:first) ? @first :
572
- (@direction==:forward) ? @first + @parent * @count : @first - @parent * @count
572
+ (@direction==:reverse) ? @first - @parent * @count : @first + @parent * @count
573
+ if @last
574
+ sign = @parent.sign
575
+ sign = -sign if @direction==:reverse
576
+ @current = nil if (sign * (@current <=> @last)) > 0
577
+ end
573
578
  @count += 1
574
579
  return value
575
580
  end
@@ -735,7 +740,7 @@ module When::TM
735
740
  end
736
741
  interval = self.dup
737
742
  interval.duration = @duration + diff
738
- internal.value = interval.duration / (@radix ** (-@factor) * @unit_quantity)
743
+ interval.value = interval.duration / (@radix ** (-@factor) * @unit_quantity)
739
744
  return interval
740
745
  end
741
746
 
@@ -750,7 +755,7 @@ module When::TM
750
755
  def -(other)
751
756
  interval = self.dup
752
757
  interval.duration = @duration - (other.kind_of?(Duration) ? other.duration : other * SECOND)
753
- internal.value = interval.duration / (@radix ** (-@factor) * @unit_quantity)
758
+ interval.value = interval.duration / (@radix ** (-@factor) * @unit_quantity)
754
759
  return interval
755
760
  end
756
761
 
@@ -1097,11 +1102,16 @@ module When::TM
1097
1102
  # @return [Integer] 0 との比較により、負,0,正の値を返す
1098
1103
  #
1099
1104
  def sign
1105
+ @sign ||= _sign
1106
+ end
1107
+
1108
+ def _sign
1100
1109
  ((@week || @date || []) + (@time || [])).each do |v|
1101
1110
  return -1 if +v < 0
1102
1111
  end
1103
1112
  return +1
1104
1113
  end
1114
+ private :_sign
1105
1115
 
1106
1116
  # 比較
1107
1117
  #
@@ -1293,7 +1303,7 @@ module When::TM
1293
1303
  # 属性 @duration の計算
1294
1304
  #
1295
1305
  def _duration
1296
- @duration = nil
1306
+ @duration = @sign = nil
1297
1307
 
1298
1308
  if @time
1299
1309
  @duration = +@time[HOUR ] * Duration::HOUR
@@ -207,6 +207,9 @@ module When::TM
207
207
  # @private
208
208
  HashProperty = Position::HashProperty
209
209
 
210
+ # @private
211
+ DateTimeInstanceMethods = ::Object.const_defined?(:Date) && ::Date.method_defined?(:+) ? ::DateTime.instance_methods : []
212
+
210
213
  # この時間位置の意味づけ
211
214
  #
212
215
  # @return [When::TM::IndeterminateValue]
@@ -306,34 +309,17 @@ module When::TM
306
309
  #
307
310
  def _instance(specification, options={})
308
311
 
309
- # Suffix - Frame specification
310
- rfc5545form, frame, *rest = specification.split(/\^{1,2}/)
311
- return rest.inject(_instance(rfc5545form + '^' + frame, options)) {|p,c| When.Resource(c, '_c:').jul_trans(p)} if rest.size > 0
312
-
313
- options[:frame] = When.Resource(frame, '_c:') if (frame)
314
-
315
- # Prefix - RFC 5545 Options
316
- if (rfc5545form =~ /\A([^:]+[^-:\d]{2}):([^:].+)\z/)
317
- rfc5545option, iso8601form = $~[1..2]
318
- rfc5545option.split(/;/).each do |eq|
319
- key, value = eq.split(/=/, 2)
320
- case key
321
- when 'VALUE' ; options[:precision] = value
322
- when 'TZID' ; options[:clock] =
323
- case When::V::Timezone[value]
324
- when Array ; When::V::Timezone[value][-1]
325
- when nil ; When::Parts::Timezone.new(value)
326
- else ; When::V::Timezone[value]
327
- end
328
- else ; options[key] = value
329
- end
330
- end
331
- else
332
- iso8601form = rfc5545form
333
- end
334
- options = options.dup
312
+ # prefix - RFC 5545 Options
313
+ iso8601form = When::Parts::Resource::ContentLine.extract_rfc5545_Property(specification, options)
314
+
315
+ # suffix - Frame specification
316
+ iso8601form, frame, *rest = iso8601form.split(/\^{1,2}/)
317
+ return rest.inject(_instance(iso8601form + '^' + frame, options)) {|p,c| When.Resource(c, '_c:').jul_trans(p)} unless rest.empty?
335
318
 
336
- # IndeterminateValue
319
+ # add frame to options
320
+ options = options.merge({:frame=>When.Resource(frame, '_c:')}) if frame
321
+
322
+ # indeterminateValue
337
323
  if (iso8601form.sub!(/\/After$|^Before\/|^Now$|^Unknown$|^[-+]Infinity\z/i, ''))
338
324
  options[:indeterminated_position] = When::TimeValue::S[$&.sub(/\//,'')]
339
325
  case options[:indeterminated_position]
@@ -433,6 +419,77 @@ module When::TM
433
419
  end
434
420
  end
435
421
 
422
+ # When::TM::TemporalPosition の生成
423
+ #
424
+ # @see When.TemporalPosition
425
+ #
426
+ def _temporal_position(*args)
427
+ # 引数の解釈
428
+ options = args[-1].kind_of?(Hash) ? args.pop.dup : {}
429
+ validate = options.delete(:invalid)
430
+ options = TemporalPosition._options(options)
431
+ options[:frame] ||= 'Gregorian'
432
+ options[:frame] = When.Resource(options[:frame], '_c:') if options[:frame].kind_of?(String)
433
+ case args[0]
434
+ when String
435
+ options[:era_name] = When::EncodingConversion.to_internal_encoding(args.shift)
436
+ when Array
437
+ options[:era_name] = args.shift
438
+ options[:era_name][0] = When::EncodingConversion.to_internal_encoding(options[:era_name][0])
439
+ end
440
+
441
+ # 時間位置の生成
442
+ res = []
443
+ abbrs = Array(options[:abbr])
444
+ date = Array.new(options[:frame].indices.length-1) {
445
+ element = args.shift
446
+ abbr = abbrs.shift
447
+ res << element.to('year') if element.kind_of?(When::Coordinates::Residue)
448
+ element.kind_of?(Numeric) ? element : (abbr || 1)
449
+ }
450
+ date += Array.new(2) {
451
+ element = args.shift
452
+ abbr = abbrs.shift
453
+ res << element.to('day') if element.kind_of?(When::Coordinates::Residue)
454
+ case element
455
+ when Numeric ; element
456
+ when nil ; abbr
457
+ else ; nil
458
+ end
459
+ }
460
+ if args.length > 0
461
+ options[:clock] ||= Clock.local_time
462
+ options[:clock] = When.Clock(options[:clock])
463
+ time = Array.new(options[:clock].indices.length) {args.shift}
464
+ position = DateAndTime.new(date, time.unshift(0), options)
465
+ else
466
+ position = CalDate.new(date, options)
467
+ end
468
+ res.each do |residue|
469
+ position = position.succ if residue.carry < 0
470
+ position &= residue
471
+ end
472
+
473
+ return position unless [:raise, :check].include?(validate)
474
+
475
+ # 時間位置の存在確認
476
+ date[0] = -date[0] if position.calendar_era_name && position.calendar_era_name[2] # 紀元前
477
+ date.each_index do |i|
478
+ break unless date[i]
479
+ next if When::Coordinates::Pair._force_pair(date[i]) == When::Coordinates::Pair._force_pair(position.cal_date[i])
480
+ return nil if validate == :check
481
+ raise ArgumentError, "Specified date not found: #{date}"
482
+ end
483
+ return position unless time
484
+ time.each_index do |i|
485
+ break unless time[i]
486
+ next if When::Coordinates::Pair._force_pair(time[i]) == When::Coordinates::Pair._force_pair(position.clk_time.clk_time[i])
487
+ return nil if validate == :check
488
+ raise ArgumentError, "Specified time not found: #{time}"
489
+ end
490
+ return position
491
+ end
492
+
436
493
  # option の正規化
437
494
  # @private
438
495
  def _options(options)
@@ -484,13 +541,13 @@ module When::TM
484
541
  # TemporalPosition
485
542
  specification =~ /(.+?)(?:\[([-+]?\d+)\])?\z/
486
543
  options[:sdn] = $2.to_i if $2
487
- f, d, t, z, e = When::BasicTypes::DateTime._to_array($1, options)
544
+ f, d, t, z, e, r = When::BasicTypes::DateTime._to_array($1, options)
488
545
  raise ArgumentError, "Timezone conflict: #{z} - #{options[:clock]}" if (z && options[:clock])
489
546
  options.delete(:abbr)
490
547
  z ||= options[:clock]
491
548
  z = When.Clock(z) if (z =~ /\A[A-Z]+\z/)
492
549
 
493
- unless (d)
550
+ unless d
494
551
  # ClockTime
495
552
  raise ArgumentError, "Timezone conflict: #{z} - #{options[:clock]}" if (z && options[:frame])
496
553
  options[:frame] ||= z
@@ -512,6 +569,17 @@ module When::TM
512
569
  PeriodDuration.new((w[0]-1)*7 + (w[1]||1)-1, DAY)
513
570
  position = When::Parts::GeometricComplex.new(position...(position+P1W)) unless w[1]
514
571
  end
572
+ if r
573
+ r.keys.sort.each do |count|
574
+ residue = When.Residue(r[count])
575
+ if count == 0
576
+ residue = residue.to('year')
577
+ else
578
+ position = position.succ if residue.carry < 0
579
+ end
580
+ position &= residue
581
+ end
582
+ end
515
583
  return position
516
584
  end
517
585
  end
@@ -552,6 +620,7 @@ module When::TM
552
620
  else ; raise NameError, "Temporal Reference System is not defined"
553
621
  end
554
622
  end
623
+ alias :local_time :universal_time
555
624
 
556
625
  # 外部時間
557
626
  #
@@ -565,7 +634,7 @@ module When::TM
565
634
  case @indeterminated_position
566
635
  when Max ; +Float::MAX/4
567
636
  when Min ; -Float::MAX/4
568
- else ; time_standard.to_dynamical_time(universal_time)
637
+ else ; time_standard.to_dynamical_time(local_time)
569
638
  end
570
639
  end
571
640
 
@@ -635,8 +704,8 @@ module When::TM
635
704
  #
636
705
  # @return [::DateTime]
637
706
  #
638
- def to_date_time(option={:frame=>When::UTC}, start=_default_start)
639
- return JulianDate.dynamical_time(dynamical_time, option).to_date_time unless time_standard.rate_of_clock == 1.0
707
+ def to_datetime(option={:frame=>When::UTC}, start=_default_start)
708
+ return JulianDate.dynamical_time(dynamical_time, option).to_datetime unless time_standard.rate_of_clock == 1.0
640
709
  raise TypeError, "Clock not assigned" unless clock
641
710
  Rational
642
711
  offset = Rational(-(clock.universal_time/Duration::SECOND).to_i, (Duration::DAY/Duration::SECOND).to_i)
@@ -657,6 +726,7 @@ module When::TM
657
726
  return JulianDate.dynamical_time(dynamical_time, option).to_date unless time_standard.rate_of_clock == 1.0
658
727
  ::Date.jd(to_i, start)
659
728
  end
729
+ alias :to_date_or_datetime :to_date
660
730
 
661
731
  # 組み込みライブラリの Time オブジェクトへの変換
662
732
  #
@@ -961,7 +1031,7 @@ module When::TM
961
1031
  @query = options[:query] if (options.key?(:query))
962
1032
  @location = options[:location] if (options.key?(:location))
963
1033
  @time_standard = options[:time_standard] if (options.key?(:time_standard))
964
- @sdn = @universal_time = @dynamical_time = @period = nil
1034
+ @sdn = @universal_time = @local_time = @dynamical_time = @period = nil
965
1035
  _normalize(options)
966
1036
  return self
967
1037
  end
@@ -999,22 +1069,37 @@ module When::TM
999
1069
 
1000
1070
  # 指定の日を探す
1001
1071
  def _force_euqal_day(diff)
1002
- jdn = self.to_i + diff
1003
- date = self
1004
- done = {}
1005
- loop do
1006
- case
1007
- when date.to_i == jdn
1008
- return date
1009
- when date.to_i > jdn
1010
- next_date = date - When::P1D
1011
- date = (date.to_i == next_date.to_i) ? date - When::P2D : next_date
1012
- when date.to_i < jdn
1013
- next_date = date + When::P1D
1014
- date = (date.to_i == next_date.to_i) ? date + When::P2D : next_date
1072
+ return self if diff == 0
1073
+ date = self + When::P1D * diff
1074
+ return date if date.to_i - to_i == diff
1075
+ if @calendar_era
1076
+ options = _attr
1077
+ options.delete(:era_name)
1078
+ era = @calendar_era
1079
+ jdn = (clock ? to_f : to_i)+diff
1080
+ while era
1081
+ date = era.^(jdn, options)
1082
+ return date if date
1083
+ era = diff > 0 ? era.succ : era.prev
1084
+ end
1085
+ raise RangeError, "can't find target date: #{self} -> #{jdn}"
1086
+ else
1087
+ done = {}
1088
+ jdn = to_i + diff
1089
+ loop do
1090
+ case
1091
+ when date.to_i == jdn
1092
+ return date
1093
+ when date.to_i > jdn
1094
+ next_date = date - When::P1D
1095
+ date = (date.to_i == next_date.to_i) ? date - When::P2D : next_date
1096
+ when date.to_i < jdn
1097
+ next_date = date + When::P1D
1098
+ date = (date.to_i == next_date.to_i) ? date + When::P2D : next_date
1099
+ end
1100
+ raise RangeError, "can't find target date: #{self} -> #{jdn}" if done.key?(date.to_i)
1101
+ done[date.to_i] = true
1015
1102
  end
1016
- raise RangeError, "can't find target date: #{self} -> #{jdn}" if done.key?(date.to_i)
1017
- done[date.to_i] = true
1018
1103
  end
1019
1104
  end
1020
1105
 
@@ -1030,17 +1115,27 @@ module When::TM
1030
1115
  #
1031
1116
  # @note
1032
1117
  # When::TM::TemporalPosition で定義されていないメソッドは
1033
- # 処理を @frame (type: When::TM::Calendar or When::TM::Clock) に委譲する
1118
+ # 処理を @frame(class: When::TM::Calendar or When::TM::Clock)
1119
+ # または to_date_or_datetime(class: ::Date or ::DateTime) に委譲する
1034
1120
  #
1035
1121
  def method_missing(name, *args, &block)
1036
1122
 
1037
1123
  return _method_missing(name, *args, &block) if When::Parts::MethodCash::Escape.key?(name)
1038
- self.class.module_eval %Q{
1039
- def #{name}(*args, &block)
1040
- @frame.send("#{name}", self, *args, &block)
1041
- end
1042
- } unless When::Parts::MethodCash.escape(name)
1043
- @frame.send(name, self, *args, &block)
1124
+ if DateTimeInstanceMethods.include?(name) && ! @frame.respond_to?(name)
1125
+ self.class.module_eval %Q{
1126
+ def #{name}(*args, &block)
1127
+ self.to_date_or_datetime.send("#{name}", *args, &block)
1128
+ end
1129
+ } unless When::Parts::MethodCash.escape(name)
1130
+ self.to_date_or_datetime.send(name, *args, &block)
1131
+ else
1132
+ self.class.module_eval %Q{
1133
+ def #{name}(*args, &block)
1134
+ @frame.send("#{name}", self, *args, &block)
1135
+ end
1136
+ } unless When::Parts::MethodCash.escape(name)
1137
+ @frame.send(name, self, *args, &block)
1138
+ end
1044
1139
  end
1045
1140
  end
1046
1141
 
@@ -1095,7 +1190,7 @@ module When::TM
1095
1190
  options[:frame] ||= time.clock
1096
1191
  universal_time = time.universal_time
1097
1192
  else
1098
- if ::Object.const_defined?(:Date) && time.respond_to?(:ajd)
1193
+ if ::Object.const_defined?(:Date) && ::Date.method_defined?(:+) && time.respond_to?(:ajd)
1099
1194
  case time
1100
1195
  when ::DateTime
1101
1196
  options[:frame] ||= When.Clock((time.offset * 86400).to_i)
@@ -1130,6 +1225,16 @@ module When::TM
1130
1225
  alias :coordinateValue :universal_time
1131
1226
  protected :universal_time=
1132
1227
 
1228
+ # 内部時間(ローカル)
1229
+ #
1230
+ # @return [Numeric]
1231
+ #
1232
+ # 1970-01-01T00:00:00(ローカル) からの Universal Coordinated Time の経過時間 / 128秒
1233
+ #
1234
+ def local_time
1235
+ @universal_time
1236
+ end
1237
+
1133
1238
  # CoordinateSystem による時間座標値
1134
1239
  #
1135
1240
  # @return [Numeric]
@@ -1177,7 +1282,7 @@ module When::TM
1177
1282
  #
1178
1283
  # ユリウス日
1179
1284
  #
1180
- # see {http://schemas.opengis.net/gml/3.1.1/base/temporalAppendix.xsd#JulianDateType gml schema}
1285
+ # see {http://schemas.opengis.net/gml/3.1.1/base/temporalAppendix.xsd#JulianDateType CALENdeRsign}
1181
1286
  #
1182
1287
  class JulianDate < Coordinate
1183
1288
 
@@ -1185,6 +1290,16 @@ module When::TM
1185
1290
  # 19700101T120000Z
1186
1291
  JD19700101 = 2440588
1187
1292
 
1293
+ # Modified Julian Date
1294
+ #
1295
+ # see {http://en.wikipedia.org/wiki/Julian_day#Variants MJD}
1296
+ JDN_of_MJD = 2400000.5
1297
+
1298
+ # Countdown to Equinoctial Planetconjunction
1299
+ #
1300
+ # see {http://www.calendersign.com/en/cs_cep-pec.php CEP}
1301
+ JDN_of_CEP = 2698162
1302
+
1188
1303
  class << self
1189
1304
 
1190
1305
  JD19700100_5 = JD19700101 - 0.5
@@ -1219,8 +1334,12 @@ module When::TM
1219
1334
  # @return [When::TM::TemporalPosition, When::TM::Duration, When::Parts::GeometricComplex or Array<them>]
1220
1335
  #
1221
1336
  def parse(specification, options={})
1222
- jdn, *calendars = specification.split(/\^{1,2}/)
1223
- jdn = jdn.sub!(/[.@]/, '.') ? jdn.to_f : jdn.to_i
1337
+ num, *calendars = specification.split(/\^{1,2}/)
1338
+ jdn = num.sub!(/[.@]/, '.') ? num.to_f : num.to_i
1339
+ case num
1340
+ when/MJD/i ; jdn += JDN_of_MJD
1341
+ when/CEP/i ; jdn += JDN_of_CEP
1342
+ end
1224
1343
  frame = calendars.shift || options[:frame]
1225
1344
  return self.new(jdn, options) unless frame
1226
1345
  calendars.unshift(frame).inject(jdn) {|date, calendar| When.Calendar(calendar).jul_trans(date, options)}
@@ -1340,15 +1459,32 @@ module When::TM
1340
1459
 
1341
1460
  # 内部時間
1342
1461
  #
1462
+ # @param [Integer] sdn 参照事象の通し番号
1463
+ #
1343
1464
  # @return [Numeric]
1344
1465
  #
1345
1466
  # T00:00:00Z からの Universal Coordinated Time の経過時間 / 128秒
1346
1467
  #
1347
1468
  # 時法によっては、異なる意味を持つことがある
1348
1469
  #
1349
- def universal_time
1470
+ def universal_time(sdn=nil)
1471
+ raise NameError, "Temporal Reference System is not defined" unless @frame
1472
+ @universal_time ||= @frame.to_universal_time(@clk_time, sdn)
1473
+ end
1474
+
1475
+ # 内部時間(ローカル)
1476
+ #
1477
+ # @param [Integer] sdn 参照事象の通し番号
1478
+ #
1479
+ # @return [Numeric]
1480
+ #
1481
+ # T00:00:00(ローカル) からの Universal Coordinated Time の経過時間 / 128秒
1482
+ #
1483
+ # 時法によっては、異なる意味を持つことがある
1484
+ #
1485
+ def local_time(sdn=nil)
1350
1486
  raise NameError, "Temporal Reference System is not defined" unless @frame
1351
- @universal_time ||= @frame.to_universal_time(@clk_time)
1487
+ @local_time ||= @frame.to_local_time(@clk_time, sdn)
1352
1488
  end
1353
1489
 
1354
1490
  # 繰り上がり
@@ -1506,6 +1642,7 @@ module When::TM
1506
1642
  return super if [Now, Max, Min].include?(@indeterminated_position)
1507
1643
  @universal_time ||= JulianDate._d_to_t(to_i)
1508
1644
  end
1645
+ alias :local_time :universal_time
1509
1646
 
1510
1647
  # ユリウス日
1511
1648
  #
@@ -1589,17 +1726,18 @@ module When::TM
1589
1726
  when 'day'
1590
1727
  # 指定の剰余となる日
1591
1728
  sdn = other & to_i
1592
- date = @frame.to_cal_date(sdn)
1593
- date[0] -= @calendar_era_name[1] if @calendar_era_name
1594
- result = self.dup._copy({:events=>nil, :query=>@query, :validate=>:done, :date=>date})
1729
+ options = {:date=>_date_with_era(@frame.to_cal_date(sdn)), :events=>nil, :query=>@query, :validate=>:done}
1730
+ options[:precision] = When::DAY if precision < When::DAY
1731
+ result = self.dup._copy(options)
1595
1732
  result.send(:_force_euqal_day, sdn-result.to_i)
1596
1733
 
1597
1734
  when 'year'
1598
1735
  # 指定の剰余となる年
1599
- date = @cal_date.dup
1600
- date[0] = (other & (most_significant_coordinate + @frame._diff_to_CE)) - @frame._diff_to_CE
1601
- date[0] -= @calendar_era_name[1] if @calendar_era_name
1602
- return self.dup._copy({:date=>date, :events=>nil, :query=>@query})
1736
+ date = @frame.send(:_decode, _date_without_era)
1737
+ date[0] = (other & (date[0] + @frame.diff_to_CE)) - @frame.diff_to_CE
1738
+ options = {:date=>_date_with_era(@frame.send(:_encode, date)), :events=>nil, :query=>@query}
1739
+ options[:precision] = When::YEAR if precision < When::YEAR
1740
+ return self.dup._copy(options)
1603
1741
 
1604
1742
  else
1605
1743
  raise ArgumentError,"The right operand should have a unit 'day' or 'year'"
@@ -1615,11 +1753,11 @@ module When::TM
1615
1753
  def %(other)
1616
1754
  raise TypeError,"The right operand should be When::Coordinates::Residue" unless other.kind_of?(Residue)
1617
1755
  if precision <= When::YEAR && other.units['year'] && other.event != 'year'
1618
- other.to('year') % (most_significant_coordinate + @frame._diff_to_CE)
1756
+ other.to('year') % (most_significant_coordinate + @frame.epoch_in_CE)
1619
1757
  else
1620
1758
  case other.event
1621
1759
  when 'day' ; other % least_significant_coordinate
1622
- when 'year' ; other % (most_significant_coordinate + @frame._diff_to_CE)
1760
+ when 'year' ; other % (most_significant_coordinate + @frame.epoch_in_CE)
1623
1761
  else ; raise ArgumentError,"The right operand should have a unit 'day' or 'year'"
1624
1762
  end
1625
1763
  end
@@ -1863,7 +2001,21 @@ module When::TM
1863
2001
  def universal_time
1864
2002
  return super if [Now, Max, Min].include?(@indeterminated_position)
1865
2003
  raise NameError, "Temporal Reference System is not defined" unless (@frame && clock)
1866
- @universal_time ||= (to_i - JulianDate::JD19700101) * Duration::DAY + @clk_time.universal_time
2004
+ @universal_time ||= (to_i - JulianDate::JD19700101) * Duration::DAY + @clk_time.universal_time(to_i)
2005
+ end
2006
+
2007
+ # 内部時間(ローカル)
2008
+ #
2009
+ # @return [Numeric]
2010
+ #
2011
+ # 1970-01-01T00:00:00(ローカル) からの Universal Coordinated Time の経過時間 / 128秒
2012
+ #
2013
+ # 暦法によっては、異なる意味を持つことがある
2014
+ #
2015
+ def local_time
2016
+ return super if [Now, Max, Min].include?(@indeterminated_position)
2017
+ raise NameError, "Temporal Reference System is not defined" unless (@frame && clock)
2018
+ @local_time ||= (to_i - JulianDate::JD19700101) * Duration::DAY + @clk_time.local_time(to_i)
1867
2019
  end
1868
2020
 
1869
2021
  # 要素の参照
@@ -1888,19 +2040,21 @@ module When::TM
1888
2040
  case other.event
1889
2041
  when 'day'
1890
2042
  # 指定の剰余となる日
1891
- sdn = other & to_i
1892
- result = self.dup._copy({:events=>nil, :query=>@query, :validate=>:done,
1893
- :date=>_date_with_era(@frame.to_cal_date(sdn)),
1894
- :time=>@clk_time.clk_time.dup})
2043
+ sdn = other & to_i
2044
+ options = {:date=>_date_with_era(@frame.to_cal_date(sdn)), :time=>@clk_time.clk_time.dup,
2045
+ :events=>nil, :query=>@query, :validate=>:done}
2046
+ options[:precision] = When::DAY if precision < When::DAY
2047
+ result = self.dup._copy(options)
1895
2048
  result.send(:_force_euqal_day, sdn-result.to_i)
1896
2049
 
1897
2050
  when 'year'
1898
2051
  # 指定の剰余となる年
1899
- date = @cal_date.dup
1900
- date[0] = (other & (most_significant_coordinate + @frame._diff_to_CE)) - @frame._diff_to_CE
1901
- return self.dup._copy({:events=>nil, :query=>@query,
1902
- :date=>_date_with_era(date),
1903
- :time=>@clk_time.clk_time.dup})
2052
+ date = @frame.send(:_decode, _date_without_era)
2053
+ date[0] = (other & (date[0] + @frame.diff_to_CE)) - @frame.diff_to_CE
2054
+ options = {:date=>_date_with_era(@frame.send(:_encode, date)), :time=>@clk_time.clk_time.dup,
2055
+ :events=>nil, :query=>@query}
2056
+ options[:precision] = When::YEAR if precision < When::YEAR
2057
+ return self.dup._copy(options)
1904
2058
 
1905
2059
  else
1906
2060
  raise ArgumentError,"The right operand should have a unit 'day' or 'year'"
@@ -1972,6 +2126,10 @@ module When::TM
1972
2126
  end
1973
2127
  alias :to_CalDate :to_cal_date
1974
2128
 
2129
+ # 標準ライブラリの DateTime オブジェクトへの変換
2130
+ #
2131
+ alias :to_date_or_datetime :to_datetime
2132
+
1975
2133
  #protected
1976
2134
 
1977
2135
  # 属性の Hash
@@ -2084,7 +2242,7 @@ module When::TM
2084
2242
  @clk_time = zero.clk_time
2085
2243
  @clk_time.clk_time[-1] += second
2086
2244
  leap /= clock.second
2087
- @universal_time = When::Coordinates::LeapSeconds.new(@universal_time-leap, leap, 1/clock.second)
2245
+ @universal_time = @local_time = When::Coordinates::LeapSeconds.new(@local_time-leap, leap, 1/clock.second)
2088
2246
  @dynamical_time -= leap
2089
2247
  end
2090
2248
  end