when_exe 0.3.4 → 0.3.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (168) hide show
  1. data/bin/locales.rb +2 -2
  2. data/bin/when.rb +2 -2
  3. data/lib/when_exe.rb +161 -55
  4. data/lib/when_exe/basictypes.rb +34 -26
  5. data/lib/when_exe/calendarnote.rb +654 -0
  6. data/lib/when_exe/calendartypes.rb +49 -474
  7. data/lib/when_exe/coordinates.rb +141 -34
  8. data/lib/when_exe/core/compatibility.rb +22 -2
  9. data/lib/when_exe/core/extension.rb +47 -3
  10. data/lib/when_exe/ephemeris.rb +82 -109
  11. data/lib/when_exe/googlecalendar.rb +1 -1
  12. data/lib/when_exe/icalendar.rb +26 -14
  13. data/lib/when_exe/inspect.rb +82 -68
  14. data/lib/when_exe/locales/af.rb +1 -1
  15. data/lib/when_exe/locales/ar.rb +1 -1
  16. data/lib/when_exe/locales/az.rb +1 -1
  17. data/lib/when_exe/locales/bg.rb +1 -1
  18. data/lib/when_exe/locales/bn.rb +1 -1
  19. data/lib/when_exe/locales/bs.rb +1 -1
  20. data/lib/when_exe/locales/ca.rb +1 -1
  21. data/lib/when_exe/locales/cs.rb +1 -1
  22. data/lib/when_exe/locales/cy.rb +1 -1
  23. data/lib/when_exe/locales/da.rb +1 -1
  24. data/lib/when_exe/locales/de.rb +1 -1
  25. data/lib/when_exe/locales/de_AT.rb +1 -1
  26. data/lib/when_exe/locales/de_CH.rb +1 -1
  27. data/lib/when_exe/locales/el.rb +1 -1
  28. data/lib/when_exe/locales/en.rb +1 -1
  29. data/lib/when_exe/locales/en_AU.rb +1 -1
  30. data/lib/when_exe/locales/en_CA.rb +1 -1
  31. data/lib/when_exe/locales/en_GB.rb +1 -1
  32. data/lib/when_exe/locales/en_IE.rb +1 -1
  33. data/lib/when_exe/locales/en_IN.rb +1 -1
  34. data/lib/when_exe/locales/en_NZ.rb +1 -1
  35. data/lib/when_exe/locales/en_US.rb +1 -1
  36. data/lib/when_exe/locales/eo.rb +1 -1
  37. data/lib/when_exe/locales/es.rb +1 -1
  38. data/lib/when_exe/locales/es_419.rb +1 -1
  39. data/lib/when_exe/locales/es_AR.rb +1 -1
  40. data/lib/when_exe/locales/es_CL.rb +1 -1
  41. data/lib/when_exe/locales/es_CO.rb +1 -1
  42. data/lib/when_exe/locales/es_CR.rb +1 -1
  43. data/lib/when_exe/locales/es_EC.rb +1 -1
  44. data/lib/when_exe/locales/es_MX.rb +1 -1
  45. data/lib/when_exe/locales/es_PA.rb +1 -1
  46. data/lib/when_exe/locales/es_PE.rb +1 -1
  47. data/lib/when_exe/locales/es_VE.rb +1 -1
  48. data/lib/when_exe/locales/et.rb +1 -1
  49. data/lib/when_exe/locales/eu.rb +1 -1
  50. data/lib/when_exe/locales/fa.rb +1 -1
  51. data/lib/when_exe/locales/fi.rb +1 -1
  52. data/lib/when_exe/locales/fr.rb +1 -1
  53. data/lib/when_exe/locales/fr_CA.rb +1 -1
  54. data/lib/when_exe/locales/fr_CH.rb +1 -1
  55. data/lib/when_exe/locales/gl.rb +1 -1
  56. data/lib/when_exe/locales/he.rb +1 -1
  57. data/lib/when_exe/locales/hi.rb +1 -1
  58. data/lib/when_exe/locales/hi_IN.rb +1 -1
  59. data/lib/when_exe/locales/hr.rb +1 -1
  60. data/lib/when_exe/locales/hu.rb +1 -1
  61. data/lib/when_exe/locales/id.rb +1 -1
  62. data/lib/when_exe/locales/is.rb +1 -1
  63. data/lib/when_exe/locales/it.rb +1 -1
  64. data/lib/when_exe/locales/it_CH.rb +1 -1
  65. data/lib/when_exe/locales/ja.rb +1 -1
  66. data/lib/when_exe/locales/kn.rb +1 -1
  67. data/lib/when_exe/locales/ko.rb +1 -1
  68. data/lib/when_exe/locales/lo.rb +1 -1
  69. data/lib/when_exe/locales/locales.rb +1 -1
  70. data/lib/when_exe/locales/lt.rb +1 -1
  71. data/lib/when_exe/locales/lv.rb +1 -1
  72. data/lib/when_exe/locales/mk.rb +1 -1
  73. data/lib/when_exe/locales/mn.rb +1 -1
  74. data/lib/when_exe/locales/ms.rb +1 -1
  75. data/lib/when_exe/locales/nb.rb +1 -1
  76. data/lib/when_exe/locales/ne.rb +1 -1
  77. data/lib/when_exe/locales/nl.rb +1 -1
  78. data/lib/when_exe/locales/nn.rb +1 -1
  79. data/lib/when_exe/locales/or.rb +1 -1
  80. data/lib/when_exe/locales/pl.rb +1 -1
  81. data/lib/when_exe/locales/pt.rb +1 -1
  82. data/lib/when_exe/locales/pt_BR.rb +1 -1
  83. data/lib/when_exe/locales/rm.rb +1 -1
  84. data/lib/when_exe/locales/ro.rb +1 -1
  85. data/lib/when_exe/locales/ru.rb +1 -1
  86. data/lib/when_exe/locales/sk.rb +1 -1
  87. data/lib/when_exe/locales/sl.rb +1 -1
  88. data/lib/when_exe/locales/sr.rb +1 -1
  89. data/lib/when_exe/locales/sv.rb +1 -1
  90. data/lib/when_exe/locales/sw.rb +1 -1
  91. data/lib/when_exe/locales/th.rb +1 -1
  92. data/lib/when_exe/locales/tl.rb +1 -1
  93. data/lib/when_exe/locales/tr.rb +1 -1
  94. data/lib/when_exe/locales/uk.rb +1 -1
  95. data/lib/when_exe/locales/ur.rb +1 -1
  96. data/lib/when_exe/locales/uz.rb +1 -1
  97. data/lib/when_exe/locales/vi.rb +1 -1
  98. data/lib/when_exe/locales/wo.rb +1 -1
  99. data/lib/when_exe/locales/zh_CN.rb +1 -1
  100. data/lib/when_exe/locales/zh_HK.rb +1 -1
  101. data/lib/when_exe/locales/zh_TW.rb +1 -1
  102. data/lib/when_exe/mini_application.rb +6 -2
  103. data/lib/when_exe/parts/enumerator.rb +13 -8
  104. data/lib/when_exe/parts/geometric_complex.rb +3 -5
  105. data/lib/when_exe/parts/locale.rb +185 -28
  106. data/lib/when_exe/parts/method_cash.rb +20 -10
  107. data/lib/when_exe/parts/resource.rb +154 -76
  108. data/lib/when_exe/parts/timezone.rb +11 -6
  109. data/lib/when_exe/region/bahai.rb +2 -2
  110. data/lib/when_exe/region/balinese.rb +296 -296
  111. data/lib/when_exe/region/chinese.rb +564 -564
  112. data/lib/when_exe/region/chinese_calendar.rb +5 -1
  113. data/lib/when_exe/region/chinese_epoch.rb +47 -102
  114. data/lib/when_exe/region/chinese_twin.rb +798 -0
  115. data/lib/when_exe/region/christian.rb +314 -338
  116. data/lib/when_exe/region/coptic.rb +88 -0
  117. data/lib/when_exe/region/ephemeric_notes.rb +322 -307
  118. data/lib/when_exe/region/french.rb +2 -2
  119. data/lib/when_exe/region/indian.rb +361 -272
  120. data/lib/when_exe/region/iranian.rb +2 -2
  121. data/lib/when_exe/region/islamic.rb +3 -3
  122. data/lib/when_exe/region/japanese.rb +1 -1
  123. data/lib/when_exe/region/japanese_notes.rb +165 -103
  124. data/lib/when_exe/region/japanese_residues.rb +56 -55
  125. data/lib/when_exe/region/japanese_twin.rb +228 -0
  126. data/lib/when_exe/region/javanese.rb +2 -2
  127. data/lib/when_exe/region/jewish.rb +2 -2
  128. data/lib/when_exe/region/korean.rb +4 -4
  129. data/lib/when_exe/region/m17n.rb +19 -19
  130. data/lib/when_exe/region/martian.rb +21 -9
  131. data/lib/when_exe/region/mayan.rb +19 -11
  132. data/lib/when_exe/region/moon.rb +7 -7
  133. data/lib/when_exe/region/nihon_shoki.rb +7 -7
  134. data/lib/when_exe/region/roman.rb +100 -100
  135. data/lib/when_exe/region/shire.rb +130 -147
  136. data/lib/when_exe/region/thai.rb +2 -2
  137. data/lib/when_exe/region/tibetan.rb +2 -2
  138. data/lib/when_exe/region/vietnamese.rb +383 -114
  139. data/lib/when_exe/region/world.rb +112 -129
  140. data/lib/when_exe/timestandard.rb +12 -1
  141. data/lib/when_exe/tmposition.rb +28 -14
  142. data/lib/when_exe/tmreference.rb +96 -93
  143. data/lib/when_exe/version.rb +1 -1
  144. data/test/examples/Terms.m17n +2 -2
  145. data/test/examples/sample.json +16 -0
  146. data/test/examples/sample.xml +1 -1
  147. data/test/test.rb +4 -0
  148. data/test/test/basictypes.rb +2 -2
  149. data/test/test/calendarnote.rb +69 -0
  150. data/test/test/calendartypes.rb +41 -1
  151. data/test/test/coordinates.rb +12 -1
  152. data/test/test/ephemeris.rb +13 -66
  153. data/test/test/icalendar.rb +3 -3
  154. data/test/test/inspect.rb +1 -1
  155. data/test/test/parts.rb +7 -4
  156. data/test/test/region/chinese.rb +45 -0
  157. data/test/test/region/coptic.rb +27 -0
  158. data/test/test/region/indian.rb +1 -1
  159. data/test/test/region/japanese.rb +4 -4
  160. data/test/test/region/jewish.rb +1 -1
  161. data/test/test/region/m17n.rb +7 -5
  162. data/test/test/region/residue.rb +2 -2
  163. data/test/test/region/vietnamese.rb +102 -0
  164. data/test/test/timestandard.rb +81 -0
  165. data/test/test/tmposition.rb +1 -1
  166. data/test/test/tmreference.rb +1 -1
  167. data/when_exe.gemspec +2 -2
  168. metadata +16 -7
@@ -22,18 +22,18 @@ module When::Coordinates
22
22
  When::HOUR=>'PT1H', When::MINUTE=>'PT1M', When::SECOND=>'PT1S'}
23
23
  MATCH = {'NS'=>/(N|S|北緯|南緯)/, 'EW'=>/(E|W|東経|西経)/}
24
24
 
25
- # 60進->10進変換
25
+ # 60進->10進変換(1/225度単位)
26
26
  #
27
27
  # @param [String] src 60進法で表した方向付きの数値
28
28
  # @param [String] dir 方向 ('NS' または 'EW')
29
29
  #
30
- # @return [Numeric] 10進変換した数値 (src が nil なら0.0を、Numeric ならそのままsrcを返す)
30
+ # @return [Numeric] 10進変換した数値 (src が nil なら0.0を、Numeric なら 225*src を返す)
31
31
  #
32
- def self.to_deg(src, dir)
32
+ def self.to_deg_225(src, dir)
33
33
  case src
34
34
  when String
35
35
  src = src.gsub(/_+/,'').gsub(/@/, '.')
36
- return src.to_f unless (src =~ MATCH[dir])
36
+ return src.to_r * Spatial::DEGREE if (src =~ /E[-+]/ || src !~ MATCH[dir])
37
37
  sign = ($1 == dir[1..1]) ? -1 : +1
38
38
  value = src.gsub(MATCH[dir], '').strip
39
39
  if ((value + "00000") =~ /^(\d+)\.(\d{2})(\d{2})(\d+)$/)
@@ -42,29 +42,53 @@ module When::Coordinates
42
42
  else
43
43
  deg, min, sec = value.split(/[^\d.]+/)
44
44
  end
45
- return sign * (deg.to_i + (min||0).to_f/60 + (sec||0).to_f/3600)
45
+ return sign * (deg.to_i * Spatial::DEGREE +
46
+ (min||0).to_f * (Spatial::DEGREE/60.0) +
47
+ (sec||0).to_f * (Spatial::DEGREE/3600.0))
46
48
  when NilClass
47
49
  0.0
48
50
  when Numeric
49
- src
51
+ src * Spatial::DEGREE
50
52
  else
51
53
  raise TypeError, "Invalid Location Type"
52
54
  end
53
55
  end
54
56
 
57
+ # 60進->10進変換(度単位)
58
+ #
59
+ # @param [String] src 60進法で表した方向付きの数値
60
+ # @param [String] dir 方向 ('NS' または 'EW')
61
+ #
62
+ # @return [Numeric] 10進変換した数値 (src が nil なら0.0を、Numeric ならそのままsrcを返す)
63
+ #
64
+ def self.to_deg(src, dir)
65
+ to_deg_225(src, dir) / Spatial::DEGREE
66
+ end
67
+
55
68
  # 10進->60進変換
56
69
  #
57
70
  # @param [Numeric] src 数値
58
71
  # @param [String] dir 方向 ('NS' または 'EW')
72
+ # @param [Integer] round 秒の小数点以下最大桁数
59
73
  #
60
74
  # @return [String] 60進変換した数値
61
75
  #
62
- def self.to_dms(src, dir)
76
+ def self.to_dms(src, dir, round=6)
63
77
  dir = (src >= 0) ? dir[0..0] : dir[1..1]
64
- deg, min = src.abs.divmod(1)
65
- min, sec = (60*min).divmod(1)
66
- sec = (60*sec).floor
67
- (['N','S'].include?(dir) ? "%02d.%02d%02d%s" : "%03d.%02d%02d%s") % [deg, min, sec, dir]
78
+ deg, min = src.abs.divmod(1)
79
+ min, sec = (60*min).divmod(1)
80
+ sec = (60*10**round*sec).round
81
+ fig = round + 2
82
+ round.times do
83
+ div, mod = sec.divmod(10)
84
+ if mod == 0
85
+ fig -= 1
86
+ sec = div
87
+ else
88
+ break
89
+ end
90
+ end
91
+ (['N','S'].include?(dir) ? "%02d.%02d%0#{fig}d%s" : "%03d.%02d%0#{fig}d%s") % [deg, min, sec, dir]
68
92
  end
69
93
 
70
94
  #
@@ -503,17 +527,21 @@ module When::Coordinates
503
527
  #
504
528
  def succ
505
529
  value = @current
506
- if (@z==@k) ||
507
- (@count_limit.kind_of?(Numeric) && @count >= @count_limit) ||
530
+ if (@count_limit.kind_of?(Numeric) && @count >= @count_limit) ||
508
531
  (@error.kind_of?(Numeric) && @e && @error >= @e.abs)
509
532
  @current = nil
510
533
  else
511
- @z = 1.0/(@z-@k)
512
- @k = @z.floor
513
- @e = @p[1].to_f/@q[1]-@x.to_f/@y
514
- @current = [@p[1], @q[1], @e]
515
- @p = [@p[1], @p[1]*@k + @p[0]]
516
- @q = [@q[1], @q[1]*@k + @q[0]]
534
+ if @z==@k
535
+ @e = 0
536
+ @current = [@p[1], @q[1], 0]
537
+ else
538
+ @z = 1.0/(@z-@k)
539
+ @k = @z.floor
540
+ @e = @p[1].to_f/@q[1]-@x.to_f/@y
541
+ @current = [@p[1], @q[1], @e]
542
+ @p = [@p[1], @p[1]*@k + @p[0]]
543
+ @q = [@q[1], @q[1]*@k + @q[0]]
544
+ end
517
545
  @count += 1
518
546
  end
519
547
  return value
@@ -1244,6 +1272,14 @@ module When::Coordinates
1244
1272
  end
1245
1273
  end
1246
1274
 
1275
+ # 設定情報を取得する
1276
+ #
1277
+ # @return [Hash] 設定情報
1278
+ #
1279
+ def _setup_info
1280
+ {:location => @default_location}
1281
+ end
1282
+
1247
1283
  # デフォルトの空間位置を読みだす
1248
1284
  #
1249
1285
  # @return [When::Coordinates::Spatial]
@@ -1277,6 +1313,9 @@ module When::Coordinates
1277
1313
  end
1278
1314
  end
1279
1315
 
1316
+ # @private
1317
+ HashProperty = [:label, [:alt, 0.0], [:datum, When::Ephemeris::Earth], :ref]
1318
+
1280
1319
  # Degree / Internal Location Unit(16")
1281
1320
  #
1282
1321
  # (3600 を 2 の因数で割りつくした値を単位とする)
@@ -1336,6 +1375,32 @@ module When::Coordinates
1336
1375
  #
1337
1376
  attr_reader :tz
1338
1377
 
1378
+ # 緯度文字列
1379
+ #
1380
+ # @param [Integer] round 秒の小数点以下最大桁数
1381
+ #
1382
+ # @return [String] 緯度文字列(DD.MMSSsss[NS])
1383
+ #
1384
+ def lat_s
1385
+ When::Coordinates.to_dms(lat / When::Coordinates::Spatial::DEGREE, 'NS', round=6)
1386
+ end
1387
+
1388
+ # 経度文字列
1389
+ #
1390
+ # @param [Integer] round 秒の小数点以下最大桁数
1391
+ #
1392
+ # @return [String] 経度文字列(DDD.MMSSsss[EW])
1393
+ #
1394
+ def long_s
1395
+ When::Coordinates.to_dms(long / When::Coordinates::Spatial::DEGREE, 'EW', round=6)
1396
+ end
1397
+
1398
+ # 高度 / m
1399
+ #
1400
+ # @return [Numeric]
1401
+ # @return [:Center] 天体の中心の場合
1402
+ #
1403
+ attr_reader :alt
1339
1404
  # 観測地の地心距離 / kmを返します。
1340
1405
  #
1341
1406
  # @return [Numeric]
@@ -1395,17 +1460,20 @@ module When::Coordinates
1395
1460
 
1396
1461
  # 要素の正規化
1397
1462
  def _normalize(args=[], options={})
1398
- @long = When::Coordinates.to_deg(@long, 'EW') * DEGREE if @long
1399
- @lat = When::Coordinates.to_deg(@lat, 'NS') * DEGREE if @lat
1400
- @datum = When.Resource(@datum || 'Earth', '_ep:')
1401
- if @tz.kind_of?(String)
1402
- @label ||= @tz
1403
- @tz = When::Parts::Timezone.tz_info[@tz]
1404
- end
1463
+
1464
+ # 時間帯による指定
1465
+ @tz = When::Parts::Timezone.tz_info[@tz] if @tz.kind_of?(String)
1405
1466
  if @tz
1406
- @long ||= @tz.longitude * DEGREE
1407
- @lat ||= @tz.latitude * DEGREE
1467
+ @label ||= @tz.label
1468
+ @long ||= @tz.longitude
1469
+ @lat ||= @tz.latitude
1408
1470
  end
1471
+
1472
+ # データの整形
1473
+ @label = When::BasicTypes::M17n.new(@label) if @label.kind_of?(Hash)
1474
+ @long = When::Coordinates.to_deg_225(@long, 'EW') if @long
1475
+ @lat = When::Coordinates.to_deg_225(@lat, 'NS') if @lat
1476
+ @datum = When.Resource(@datum || 'Earth', '_ep:')
1409
1477
  @long ||= 0.0
1410
1478
  @lat ||= 0.0
1411
1479
  @alt =
@@ -1416,6 +1484,21 @@ module When::Coordinates
1416
1484
  end
1417
1485
  end
1418
1486
 
1487
+ #
1488
+ # 空間位置オブジェクトの内容を Hash 化
1489
+ #
1490
+ # @param [Object] options When::Parts::Resource#to_h を参照
1491
+ # @option options [Symbol] :method :to_h を label の内容の Hash 書き出しのために追加
1492
+ #
1493
+ # @return [Hash] Hash 化した空間位置オブジェクト
1494
+ #
1495
+ def _to_h(options={})
1496
+ hash = super
1497
+ hash[:long] = long_s
1498
+ hash[:lat] = lat_s
1499
+ hash
1500
+ end
1501
+
1419
1502
  # 観測地の惑星中心を原点とする三次元座標
1420
1503
  #
1421
1504
  # @param [Numeric] t ユリウス日(Terrestrial Time)
@@ -1502,7 +1585,7 @@ module When::Coordinates
1502
1585
  # Formula
1503
1586
  instance_eval('class << self; attr_reader :formula; end') if @location && @border
1504
1587
  if respond_to?(:formula)
1505
- instance_eval('class << self; include When::Ephemeris::Formula::Methods; end')
1588
+ instance_eval('class << self; include When::Ephemeris::Formula::ForwardedFormula; end')
1506
1589
  @formula ||= When::Ephemeris::Formula.new({:location=>@location})
1507
1590
  @formula = When.Resource(Array(@formula), '_ep:')
1508
1591
  end
@@ -1587,10 +1670,10 @@ module When::Coordinates
1587
1670
 
1588
1671
  # 代表暦注
1589
1672
  #
1590
- # @return [When::CalendarTypes::CalendarNote]
1673
+ # @return [When::CalendarNote]
1591
1674
  # @return [Array<Array<klass, Array<klass, method, block>>>] 最外側のArray要素は年・月・日に対応
1592
1675
  #
1593
- # klass [String, When::CalendarTypes::CalendarNote, When::Coordinates::Residue]
1676
+ # klass [String, When::CalendarNote, When::Coordinates::Residue]
1594
1677
  #
1595
1678
  # method [String, Symbol] (デフォルト 'day', 'month' or 'year' (対応する桁による))
1596
1679
  #
@@ -1644,6 +1727,13 @@ module When::Coordinates
1644
1727
  @_diff_to_CE ||= @epoch_in_CE ? @epoch_in_CE - @origin_of_MSC : 0
1645
1728
  end
1646
1729
 
1730
+ # @private
1731
+ #
1732
+ # 対応する ::Date の start 属性
1733
+ def _default_start
1734
+ ::Date::GREGORIAN
1735
+ end
1736
+
1647
1737
  # protected
1648
1738
 
1649
1739
  #
@@ -1946,7 +2036,13 @@ module When::Coordinates
1946
2036
 
1947
2037
  # その他のメソッド
1948
2038
  # When::Coordinates::Temporal で定義されていないメソッドは
1949
- # 処理を @note or @formula[0] (When::Ephemeris::Formula) に委譲する
2039
+ # 処理を下記に移譲する(番号は優先順位)
2040
+ # When::CalendarNote
2041
+ # (1) @note
2042
+ # (2) SolarTerms
2043
+ # (3) LunarPhases
2044
+ # When::Ephemeris::Formula
2045
+ # (4)@formula[0]
1950
2046
  #
1951
2047
  def method_missing(name, *args, &block)
1952
2048
  unless When::Parts::MethodCash::Escape.key?(name)
@@ -1957,9 +2053,20 @@ module When::Coordinates
1957
2053
  end
1958
2054
  } unless When::Parts::MethodCash.escape(name)
1959
2055
  return @note.send(name, *(args + [self]), &block)
1960
- elsif When::Ephemeris::Formula.method_defined?(name)
2056
+ end
2057
+ ['SolarTerms', 'LunarPhases'].each do |note|
2058
+ if When.CalendarNote(note).respond_to?(name)
2059
+ instance_eval %Q{
2060
+ def #{name}(*args, &block)
2061
+ When.CalendarNote("#{note}").send("#{name}", *args, &block)
2062
+ end
2063
+ } unless When::Parts::MethodCash.escape(name)
2064
+ return When.CalendarNote(note).send(name, *args, &block)
2065
+ end
2066
+ end
2067
+ if When::Ephemeris::Formula.method_defined?(name)
1961
2068
  unless respond_to?(:forwarded_formula, true)
1962
- instance_eval('class << self; include When::Ephemeris::Formula::Methods; end')
2069
+ instance_eval('class << self; include When::Ephemeris::Formula::ForwardedFormula; end')
1963
2070
  @formula ||= When::Ephemeris::Formula.new({:location=>@location})
1964
2071
  @formula = When.Resource(Array(@formula), '_ep:')
1965
2072
  end
@@ -1,6 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  =begin
3
- Copyright (C) 2013 Takashi SUGA
3
+ Copyright (C) 2013-2014 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
@@ -33,7 +33,7 @@ class String
33
33
  def to_r
34
34
  case self
35
35
  when /\.|E/i
36
- to_f
36
+ to_f.to_r
37
37
  when /\//
38
38
  Rational
39
39
  Rational(*split(/\//).map {|v| v.to_i})
@@ -54,6 +54,26 @@ class String
54
54
  end
55
55
  end
56
56
 
57
+ #
58
+ # 浮動小数点数
59
+ #
60
+ class Float
61
+ unless const_defined?(:INFINITY)
62
+ # @private
63
+ INFINITY = MAX
64
+ end
65
+
66
+ unless method_defined?(:to_r)
67
+ Rational
68
+ # @private
69
+ def to_r
70
+ it = When::Coordinates::Residue.new(self, 1).enum_for
71
+ res = it.succ while it.has_next?
72
+ Rational(*res[0..1])
73
+ end
74
+ end
75
+ end
76
+
57
77
  #
58
78
  # 例外クラス
59
79
  #
@@ -1,6 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  =begin
3
- Copyright (C) 2013 Takashi SUGA
3
+ Copyright (C) 2013-2014 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
@@ -19,7 +19,7 @@ class Time
19
19
  #
20
20
  # 対応する When::TM::JulianDate を生成
21
21
  #
22
- # @param [Hash] options
22
+ # @param [Hash] options 以下の通り
23
23
  # @option options [When::TM::Clock] :clock
24
24
  # @option options [When::Parts::Timezone] :tz
25
25
  #
@@ -55,7 +55,27 @@ end
55
55
  #
56
56
  class Date
57
57
 
58
- include When::TM::TemporalPosition::Conversion if When::TM.const_defined?(:TemporalPosition)
58
+ if When::TM.const_defined?(:TemporalPosition)
59
+
60
+ include When::TM::TemporalPosition::Conversion
61
+
62
+ #
63
+ # 対応する When::TM::CalDate or DateAndTime を生成
64
+ #
65
+ # @param [Hash] options 暦法や時法などの指定
66
+ # see {When::TM::TemporalPosition._instance}
67
+ #
68
+ # @return [When::TM::CalDate, When::TM::DateAndTime]
69
+ #
70
+ # @note 暦法の指定がない場合、start メソッドの値によって
71
+ # Julian / Gregorian / Civil 暦法を選択する
72
+ #
73
+ def tm_position(options={})
74
+ options[:frame] ||= When::CalendarTypes::Christian._default_start(self)
75
+ super(options)
76
+ end
77
+ alias :to_tm_position :tm_position
78
+ end
59
79
 
60
80
  alias :__method_missing :method_missing
61
81
 
@@ -130,6 +150,18 @@ class Numeric
130
150
  end
131
151
  alias :pair :to_pair
132
152
 
153
+ #
154
+ # self を秒数とみなして When::Parts::Timezone::Base を取得
155
+ #
156
+ # @return [When::Parts::Timezone::Base]
157
+ #
158
+ # @note core/extension
159
+ #
160
+ def clock
161
+ When.Clock(self)
162
+ end
163
+ alias :to_clock :clock
164
+
133
165
  # メソッド名に相当する単位で表した When::TM::IntervalLength
134
166
  # @method unit_interval_length
135
167
  # @return [When::TM::IntervalLength]
@@ -233,6 +265,18 @@ class String
233
265
  end
234
266
  alias :to_calendar :calendar
235
267
 
268
+ #
269
+ # self を時間帯文字列とみなして When::Parts::Timezone::Base を取得
270
+ #
271
+ # @return [When::Parts::Timezone::Base]
272
+ #
273
+ # @note core/extension
274
+ #
275
+ def clock
276
+ When.Clock(self)
277
+ end
278
+ alias :to_clock :clock
279
+
236
280
  #
237
281
  # self をプレフィクス '_c:' を省略した IRI とみなして When::TM::CalendarNote を取得
238
282
  #
@@ -1147,35 +1147,7 @@ module When::Ephemeris
1147
1147
  #
1148
1148
  # 天体暦機能を When::TM::Calendar クラスに提供する
1149
1149
  #
1150
- module Methods
1151
-
1152
- # 月の位相が指定の周期番号パターンになる最も近い過去の日時
1153
- #
1154
- # @param [Numeric] date ユリウス日(Terrestrial Time)
1155
- # @param [When::TM::TemporalPosition] date
1156
- # @param [Numeric] n 相対周期番号(n=0 なら date または date の直前が基準)
1157
- # @param [Numeric] d 単位周期数
1158
- #
1159
- # @return [Numeric, When::TM::TemporalPosition] 周期番号が d で割って n になる日時
1160
- #
1161
- def nearest_past_from_lunar_phase(date, n=0, d=1)
1162
- @formula ||= When.Resource(['_ep:Formula?formula=12S', '_ep:Formula?formula=1L'])
1163
- @formula[-1].nearest_past(date, n, d)
1164
- end
1165
-
1166
- # 二十四節気が指定の周期番号パターンになる最も近い過去の日時
1167
- #
1168
- # @param [Numeric] date ユリウス日(Terrestrial Time)
1169
- # @param [When::TM::TemporalPosition] date
1170
- # @param [Numeric] n 相対周期番号(n=0 なら date または date の直前が基準)
1171
- # @param [Numeric] d 単位周期数
1172
- #
1173
- # @return [Numeric, When::TM::TemporalPosition] 周期番号が d で割って n になる日時
1174
- #
1175
- def nearest_past_from_solar_term(date, n=0, d=1)
1176
- @formula ||= When.Resource(['_ep:Formula?formula=12S', '_ep:Formula?formula=1L'])
1177
- @formula[0].nearest_past(date, n, d)
1178
- end
1150
+ module ForwardedFormula
1179
1151
 
1180
1152
  private
1181
1153
 
@@ -1262,18 +1234,17 @@ module When::Ephemeris
1262
1234
  root(time0, cn) {|t| time_to_cn(t)}
1263
1235
  end
1264
1236
 
1265
- # 当該日付のthiti の変化範囲
1237
+ # 当該日付の月の位相の変化範囲
1266
1238
  #
1267
1239
  # @param [When::TM::TemporalPosition] date 日付
1268
1240
  #
1269
- # @return [Range] 当該日付のthiti の変化範囲(朔を含む場合 nil)
1241
+ # @return [Array<Numeric>] 当該日付の月の位相の変化範囲
1270
1242
  #
1271
- def thiti_range(date)
1272
- date = date.floor
1273
- p0, p1 = [date, date.succ].map {|d|
1274
- (30.0 * time_to_cn(d)) % 30.0
1243
+ def phase_range(date)
1244
+ date = date.floor
1245
+ [date, date.succ].map {|d|
1246
+ time_to_cn(d)
1275
1247
  }
1276
- p0 >= p1 ? nil : p0...p1
1277
1248
  end
1278
1249
 
1279
1250
  # 指定の周期番号パターンになる最も近い過去の日時
@@ -1774,6 +1745,52 @@ module When::Ephemeris
1774
1745
  #
1775
1746
  class MeanLunation < Formula
1776
1747
 
1748
+ #
1749
+ # Lunar Calendar Formula
1750
+ #
1751
+ module LunarMethod
1752
+
1753
+ private
1754
+
1755
+ # 周期番号 -> 日時
1756
+ #
1757
+ # @param [Numeric] cn 周期番号
1758
+ # @param [Numeric] time0 日時の初期近似値
1759
+ #
1760
+ # @return [Numeric] ユリウス日
1761
+ #
1762
+ # @note 半ティティの日時の丸め誤差に配慮
1763
+ #
1764
+ def cn_to_time_(cn, time0=nil)
1765
+ time0 ||= (cn - @cycle_number_0m) / @cycle_number_1m
1766
+ return time0 if (cn * 60 - (cn * 60).round).abs > @cycle_precision
1767
+ ((time0 + 1.0/256 - @day_epoch) / @half_tithi).floor * @half_tithi + @day_epoch
1768
+ end
1769
+ end
1770
+
1771
+ #
1772
+ # Solar Calendar Formula for Fixed Year Length Method
1773
+ #
1774
+ module SolarMethod
1775
+
1776
+ private
1777
+
1778
+ # 周期番号 -> 日時
1779
+ #
1780
+ # @param [Numeric] cn 周期番号
1781
+ # @param [Numeric] time0 日時の初期近似値
1782
+ #
1783
+ # @return [Numeric] ユリウス日
1784
+ #
1785
+ # @note 太陽黄経が整数になる日時の丸め誤差に配慮
1786
+ #
1787
+ def cn_to_time_(cn, time0=nil)
1788
+ time0 ||= (cn - @cycle_number_0m) / @cycle_number_1m
1789
+ return time0 if (cn * 360 - (cn * 360).round).abs > @cycle_precision
1790
+ ((time0 + 1.0/256 - @day_epoch) / @solar_degree).floor * @solar_degree + @day_epoch
1791
+ end
1792
+ end
1793
+
1777
1794
  # 計算の基準経度 / 度
1778
1795
  # @return [Numeric]
1779
1796
  attr_reader :long
@@ -1851,88 +1868,44 @@ module When::Ephemeris
1851
1868
 
1852
1869
  private
1853
1870
 
1854
- # 周期番号 -> 日時
1855
- #
1856
- # @param [Numeric] cn 周期番号
1857
- # @param [Numeric] time0 日時の初期近似値
1858
- #
1859
- # @return [Numeric] ユリウス日
1860
- #
1861
- def cn_to_time_(cn, time0=nil)
1862
- time0 ||= (cn - @cycle_number_0m) / @cycle_number_1m
1863
- case @formula
1864
- when /S/ ; ((time0 + 1.0/256 - @day_epoch) / @solar_terms).floor * @solar_terms + @day_epoch
1865
- when /L/ ; ((time0 + 1.0/256 - @day_epoch) / @month_tithi).floor * @month_tithi + @day_epoch
1866
- end
1867
- end
1868
-
1869
1871
  # オブジェクトの正規化
1870
1872
  def _normalize(args=[], options={})
1871
1873
  Rational
1872
1874
  @time_standard ||= 'universal'
1873
1875
  @epoch_shift ||= 1721139 # 西暦 0 年 春分
1874
1876
  @day_shift ||= Rational(-1,2) # 夜半 -1/2, 日出 -1/4
1875
- @day_shift = @day_shift.to_r
1876
- @longitude_shift ||= Rational(-1,4) # 冬至 -1/4, 立春 -1/8
1877
- @longitude_shift = @longitude_shift.to_r
1878
- @day_epoch = @day_epoch.to_i + @day_shift
1879
- @year_length = @year_length.to_r
1880
- @lunation_length = @lunation_length.to_r
1881
- @month_length = 1 / (1.to_r/@year_length + 1.to_r/@lunation_length)
1882
- @denominator = [@year_length.denominator, @lunation_length.denominator].max
1883
- @solar_terms = @year_length / 24
1884
- @month_tithi = @lunation_length / 30
1885
- @year_epoch = 0
1886
- @year_epoch = @longitude_shift -_mean_sun_(@epoch_shift).to_i
1887
- @month_epoch = 0
1888
- @month_epoch = @longitude_shift -_mean_moon_(@epoch_shift).to_i
1889
- super
1890
- end
1891
- end
1892
-
1893
- #
1894
- # Solar Calendar Formula for Variable Year Length Method
1895
- #
1896
- class VariableYearLengthMethod < Formula
1897
-
1898
- # 日時 -> 周期番号
1899
- #
1900
- # @param [Numeric] t ユリウス日(Terrestrial Time)
1901
- # @param [When::TM::TemporalPosition] t
1902
- #
1903
- # @return [Numeric] 周期番号
1904
- #
1905
- def time_to_cn(t, cn0=nil)
1906
- cn0 ||= (t.to_f - @day_epoch) / @year_length + @year_epoch + @longitude_shift
1907
- root(cn0 * 12, t.to_f) {|cn| cn_to_time(cn) }
1908
- end
1909
-
1910
- # 周期番号 -> 日時
1911
- #
1912
- # @param [Numeric] cn 周期番号
1913
- # @param [Numeric] time0 日時の初期近似値
1914
- #
1915
- # @return [Numeric] ユリウス日
1916
- #
1917
- def cn_to_time_(cn, time0=nil)
1918
- t, n = (cn / 12.0 - @longitude_shift - @year_epoch).divmod(1)
1919
- @day_epoch + @year_length * t - @year_delta * t * (t-1) + (@year_length - 2 * @year_delta * t) * n
1920
- end
1921
-
1922
- private
1923
-
1924
- # オブジェクトの正規化
1925
- def _normalize(args=[], options={})
1926
- Rational
1927
- @time_standard ||= 'universal'
1928
- @day_shift ||= Rational(-1,2) # 夜半 -1/2, 日出 -1/4
1929
1877
  @day_shift = @day_shift.to_r
1930
1878
  @longitude_shift ||= Rational(-1,4) # 冬至 -1/4, 立春 -1/8
1931
1879
  @longitude_shift = @longitude_shift.to_r
1932
- @day_epoch = @day_epoch.to_f + @day_shift
1933
- @year_epoch = @year_epoch.to_f
1934
- @year_length = @year_length.to_f
1935
- @year_delta = @year_delta.to_f * 1.0E-6
1880
+ @day_epoch = (@day_epoch.to_f == @day_epoch.to_i ? @day_epoch.to_i : @day_epoch.to_f) + @day_shift
1881
+ @year_length = @year_length.to_r
1882
+ @year_delta = @year_delta.to_f * 1.0E-6 if @year_delta
1883
+ if @year_epoch
1884
+ @year_epoch = @year_epoch.to_f
1885
+ else
1886
+ @year_epoch = 0
1887
+ @year_epoch = @longitude_shift -_mean_sun_(@epoch_shift).to_i
1888
+ end
1889
+ @cycle_precision ||= 1.0E-8
1890
+ @cycle_precision = @cycle_precision.to_f
1891
+
1892
+ if @lunation_length && /S/i !~ @formula
1893
+ # 月の位相の計算
1894
+ @lunation_length = @lunation_length.to_r
1895
+ @month_length = 1 / (1.to_r/@year_length + 1.to_r/@lunation_length)
1896
+ @half_tithi = @lunation_length / 60
1897
+ if @month_epoch
1898
+ @month_epoch = @month_epoch.to_f
1899
+ else
1900
+ @month_epoch = 0
1901
+ @month_epoch = @longitude_shift -_mean_moon_(@epoch_shift).to_i
1902
+ end
1903
+ class << self; include LunarMethod; end
1904
+ else
1905
+ # 太陽黄経の計算
1906
+ @solar_degree = @year_length / 360
1907
+ class << self; include SolarMethod; end
1908
+ end
1936
1909
  super
1937
1910
  end
1938
1911
  end