when_exe 0.3.7 → 0.3.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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