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
@@ -79,7 +79,7 @@ end
79
79
  #
80
80
  # 例外クラス
81
81
  #
82
- unless Object.const_defined?(:StopIteration)
82
+ unless ::Object.const_defined?(:StopIteration)
83
83
  # @private
84
84
  class StopIteration < IndexError
85
85
  end
@@ -33,20 +33,22 @@ end
33
33
  # Extensions to Date class
34
34
  #
35
35
  # @private
36
- class Date
36
+ if ::Object.const_defined?(:Date) && ::Date.method_defined?(:+)
37
+ class Date
37
38
 
38
- alias :_plus_ :+
39
- def +(other)
40
- other.kind_of?(When::TM::Duration) ? self + other.rational_duration : self._plus_(other)
41
- end
39
+ alias :_plus_ :+
40
+ def +(other)
41
+ other.kind_of?(When::TM::Duration) ? self + other.rational_duration : self._plus_(other)
42
+ end
42
43
 
43
44
 
44
- alias :_minus_ :-
45
- def -(other)
46
- case other
47
- when When::TM::Duration ; self - other.rational_duration
48
- when When::TimeValue ; self._minus_(kind_of?(DateTime) ? other.to_date_time : other.to_date)
49
- else ; self._minus_(other)
45
+ alias :_minus_ :-
46
+ def -(other)
47
+ case other
48
+ when When::TM::Duration ; self - other.rational_duration
49
+ when When::TimeValue ; self._minus_(other.to_date_or_datetime)
50
+ else ; self._minus_(other)
51
+ end
50
52
  end
51
53
  end
52
54
  end
@@ -5,7 +5,6 @@
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
7
7
 
8
- require 'date'
9
8
  require 'when_exe/core/duration'
10
9
 
11
10
  #
@@ -53,55 +52,49 @@ end
53
52
  #
54
53
  # Extensions to Date class
55
54
  #
56
- class Date
57
-
58
- if When::TM.const_defined?(:TemporalPosition)
55
+ if ::Object.const_defined?(:Date) && ::Date.method_defined?(:+)
56
+ class Date
57
+
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_pos(options={})
74
+ options[:frame] ||= When::CalendarTypes::Christian._default_start(self)
75
+ super(options)
76
+ end
77
+ alias :to_tm_pos :tm_pos
78
+ end
59
79
 
60
- include When::TM::TemporalPosition::Conversion
80
+ alias :__method_missing :method_missing
61
81
 
82
+ # その他のメソッド
62
83
  #
63
- # 対応する When::TM::CalDate or DateAndTime を生成
64
- #
65
- # @param [Hash] options 暦法や時法などの指定
66
- # see {When::TM::TemporalPosition._instance}
84
+ # @note
85
+ # self で定義されていないメソッドは
86
+ # tm_pos で変換して処理する
67
87
  #
68
- # @return [When::TM::CalDate, When::TM::DateAndTime]
69
- #
70
- # @note 暦法の指定がない場合、start メソッドの値によって
71
- # Julian / Gregorian / Civil 暦法を選択する
72
- #
73
- def tm_pos(options={})
74
- options[:frame] ||= When::CalendarTypes::Christian._default_start(self)
75
- super(options)
76
- end
77
- alias :to_tm_pos :tm_pos
78
- end
79
-
80
- alias :__method_missing :method_missing
81
-
82
- # その他のメソッド
83
- #
84
- # @note
85
- # self で定義されていないメソッドは
86
- # tm_pos で変換して処理する
87
- #
88
- def method_missing(name, *args, &block)
89
- return __method_missing(name, *args, &block) if When::Parts::MethodCash::Escape.key?(name)
90
- self.class.module_eval %Q{
91
- def #{name}(*args, &block)
92
- result = tm_pos.send("#{name}", *args, &block)
93
- case result
94
- when When::TM::DateAndTime ; result.to_date_time
95
- when When::TM::CalDate ; result.to_date
96
- else ; result
88
+ def method_missing(name, *args, &block)
89
+ return __method_missing(name, *args, &block) if When::Parts::MethodCash::Escape.key?(name)
90
+ self.class.module_eval %Q{
91
+ def #{name}(*args, &block)
92
+ result = tm_pos.send("#{name}", *args, &block)
93
+ result.kind_of?(When::TimeValue) ? result.to_date_or_datetime : result
97
94
  end
98
- end
99
- } unless When::Parts::MethodCash.escape(name)
100
- result = tm_pos.send(name, *args, &block)
101
- case result
102
- when When::TM::DateAndTime ; result.to_date_time
103
- when When::TM::CalDate ; result.to_date
104
- else ; result
95
+ } unless When::Parts::MethodCash.escape(name)
96
+ result = tm_pos.send(name, *args, &block)
97
+ result.kind_of?(When::TimeValue) ? result.to_date_or_datetime : result
105
98
  end
106
99
  end
107
100
  end
@@ -289,12 +289,10 @@ module When::Ephemeris
289
289
  def root(t0, y0=nil, delta=0, count=10, error=1E-6, &func)
290
290
 
291
291
  # 近似値0,1
292
- # printf("y0=%20.7f\n",y0)
293
- d = [0.01, error * 10].max
294
- t = [t0-d, t0+d ]
292
+ diff = [0.01, error*1000].min
293
+ t = [t0-diff, t0+diff ]
295
294
  y = [func.call(t[0]), func.call(t[1])]
296
295
  y.map! {|y1| _adjust(y1, y0, delta)} unless delta==0
297
- # printf("t=%20.7f,L=%20.7f\n",t[1],y[1])
298
296
 
299
297
  # 近似値2(1次関数による近似)
300
298
  t << (y0 ? (t[1]-t[0])/(y[1]-y[0])*(y0-y[0])+t[0] : t0)
@@ -319,15 +317,19 @@ module When::Ephemeris
319
317
 
320
318
  if y0
321
319
  # 判別式
322
- if (d = b*b-4*a*(c-y0)) < 0
323
- i = -1
324
- break
320
+ if (discriminant = b*b-4*a*(c-y0)) < 0
321
+ # 近似値(1次関数による近似)
322
+ if y12 == 0
323
+ i = -1
324
+ break
325
+ end
326
+ t << t12/y12*(y0-y[1]) + t[1]
327
+ else
328
+ # 近似値(2次関数による近似)
329
+ sqrtd = Math.sqrt(discriminant)
330
+ sqrtd = -sqrtd if b < 0
331
+ t << (t[2] + 2*(y0-c)/(b+sqrtd)) # <-桁落ち回避
325
332
  end
326
-
327
- # 近似値(2次関数による近似)
328
- sqrtd = Math.sqrt(d)
329
- sqrtd = -sqrtd if b < 0
330
- t << (t[2] + 2*(y0-c)/(b+sqrtd)) # <-桁落ち回避
331
333
  else
332
334
  t << (t[2] - b / (2*a))
333
335
  end
@@ -1117,7 +1119,7 @@ module When::Ephemeris
1117
1119
  #
1118
1120
  # @return [Numeric]
1119
1121
  #
1120
- def eclipse(t, target, base=Earth)
1122
+ def phase_of_eclipse(t, target, base=Earth)
1121
1123
  t = +t
1122
1124
  distance = acos(self.coords(t, base).spherical_law_of_cosines(target.coords(t, base))) / CIRCLE
1123
1125
  self_radius = self.apparent_radius(t, base)
@@ -1477,6 +1479,33 @@ module When::Ephemeris
1477
1479
  day_event_in_the_day(t, 0, When.Resource('_ep:Moon'))
1478
1480
  end
1479
1481
 
1482
+ # 日食の情報
1483
+ #
1484
+ # @param [When::TM::TemporalPosition] date
1485
+ # @param [Range<When::TM::TemporalPosition>] date
1486
+ # @param [Block] block
1487
+ #
1488
+ # @return [Array<String, Numeric, Array<Array<Numeric or When::TM::TemporalPosition, String>>>] 食の情報(のArray(dateがRangeの場合))
1489
+ # @see When::Coordinates::Spatial#eclipse_info
1490
+ #
1491
+ def solar_eclipse(date, &block)
1492
+ location.solar_eclipse(date, &block)
1493
+ end
1494
+
1495
+ # 月食の情報
1496
+ #
1497
+ # @param [When::TM::TemporalPosition] date
1498
+ # @param [Range<When::TM::TemporalPosition>] date
1499
+ # @note Rangeの場合午前6時より前は前日扱い
1500
+ # @param [Block] block
1501
+ #
1502
+ # @return [Array<String, Numeric, Array<Array<Numeric or When::TM::TemporalPosition, String>>>] 食の情報(のArray(dateがRangeの場合))
1503
+ # @see When::Coordinates::Spatial#eclipse_info
1504
+ #
1505
+ def lunar_eclipse(date, &block)
1506
+ location.lunar_eclipse(date, &block)
1507
+ end
1508
+
1480
1509
  # 恒星の出没と太陽の位置関係に関するイベントの日時
1481
1510
  #
1482
1511
  # @param [Numeric] t ユリウス日(Terrestrial Time)
@@ -1568,7 +1597,7 @@ module When::Ephemeris
1568
1597
  @long, @lat, @alt = [@location.long / When::Coordinates::Spatial::DEGREE,
1569
1598
  @location.lat / When::Coordinates::Spatial::DEGREE,
1570
1599
  @location.alt] if @location
1571
- @formula ||= '1L'
1600
+ @formula ||= '1S'
1572
1601
  @time_standard ||= 'dynamical'
1573
1602
  @is_dynamical = (@time_standard[0..0].downcase == 'd')
1574
1603
 
@@ -0,0 +1,149 @@
1
+ # -*- coding: utf-8 -*-
2
+ =begin
3
+ Copyright (C) 2014 Takashi SUGA
4
+
5
+ You may use and/or modify this file according to the license described in the LICENSE.txt file included in this archive.
6
+ =end
7
+
8
+ class When::Coordinates::Spatial
9
+
10
+ # @private
11
+ EclipseHalfYear = (346 + (14*3600+52*60+54.965) / 86400) / 2
12
+
13
+ # @private
14
+ EclipseRange = (75.0..120.0) # 82.05003457775217..114.62097737290446
15
+
16
+ # 日食の情報
17
+ #
18
+ # @param [When::TM::TemporalPosition] date
19
+ # @param [Range<When::TM::TemporalPosition>] date
20
+ # @param [Block] block
21
+ #
22
+ # @return [Array<String, Numeric, Array<Array<Numeric or When::TM::TemporalPosition, String>>>] 食の情報(のArray(dateがRangeの場合))
23
+ # @see When::Coordinates::Spatial#eclipse_info
24
+ #
25
+ def solar_eclipse(date, &block)
26
+ if date.kind_of?(Range)
27
+ last = date.last.to_i
28
+ last -= 1 if date.exclude_end?
29
+ first = date.first.to_i
30
+ date = date.first
31
+ end
32
+ clock = date.clock && (date.clock.tz_prop || date.clock.label)
33
+ cn = @mean.time_to_cn(date).round
34
+ list = []
35
+ loop do
36
+ unless @ecls.key?([cn,clock.to_s])
37
+ time = @mean.cn_to_time(cn)
38
+ data = EclipseRange.include?(time % EclipseHalfYear) ?
39
+ eclipse_info(@mean._to_seed_type(time, date), self, When.Resource('_ep:Sun'), When.Resource('_ep:Moon')) : nil
40
+ @ecls[[cn,clock.to_s]] = data ? [data[2][data[2].size / 2][0].to_i, data] : nil
41
+ end
42
+ key, info = @ecls[[cn,clock.to_s]]
43
+ return info unless first
44
+ list << (block_given? ? yield(info) : info) if key && first <= key && key <= last
45
+ break if (key || first) >= last
46
+ cn += 1
47
+ end
48
+ return list
49
+ end
50
+
51
+ # 月食の情報
52
+ #
53
+ # @param [When::TM::TemporalPosition] date
54
+ # @param [Range<When::TM::TemporalPosition>] date
55
+ # @note Rangeの場合午前6時より前は前日扱い
56
+ # @param [Block] block
57
+ #
58
+ # @return [Array<String, Numeric, Array<Array<Numeric or When::TM::TemporalPosition, String>>>] 食の情報(のArray(dateがRangeの場合))
59
+ # @see When::Coordinates::Spatial#eclipse_info
60
+ #
61
+ def lunar_eclipse(date, &block)
62
+ if date.kind_of?(Range)
63
+ last = date.last.to_i
64
+ last -= 1 if date.exclude_end?
65
+ first = date.first.to_i
66
+ date = date.first
67
+ end
68
+ clock = date.clock && (date.clock.tz_prop || date.clock.label)
69
+ cn = (@mean.time_to_cn(date)+0.25).floor+0.5
70
+ list = []
71
+ loop do
72
+ unless @ecls.key?([cn,clock.to_s])
73
+ time = @mean.cn_to_time(cn)
74
+ data = EclipseRange.include?(time % EclipseHalfYear) ?
75
+ eclipse_info(@mean._to_seed_type(time, date), When.Resource('_ep:Earth'), When.Resource('_ep:Moon'),
76
+ When.Resource('_ep:Shadow'), [self, When.Resource('_ep:Moon')]) : nil
77
+ @ecls[[cn,clock.to_s]] = data ? [(data[2][data[2].size / 2][0]-When::PT6H).to_i, data] : nil
78
+ end
79
+ key, info = @ecls[[cn,clock.to_s]]
80
+ return info unless first
81
+ list << (block_given? ? yield(info) : info) if key && first <= key && key <= last
82
+ break if (key || first) >= last
83
+ cn += 1
84
+ end
85
+ return list
86
+ end
87
+
88
+ # 食の情報
89
+ #
90
+ # @param [Numeric] date ユリウス日(Terrestrial Time)
91
+ # @param [When::TM::TemporalPosition] date
92
+ # @param [When::Ephemeris::Datum or When::Coordinates::Spatial] location 観測地
93
+ # @param [When::Ephemeris::Datum] target 隠される天体
94
+ # @param [When::Ephemeris::Datum] base 隠す天体
95
+ # @param [Array<When::Coordinates::Spatial, When::Ephemeris::Datum>] l_for_h 高度を計算する観測地と対象天体
96
+ #
97
+ # @return [Array<String, Numeric, Array<Array<Numeric or When::TM::TemporalPosition, String>>>] 食の情報
98
+ #
99
+ # [ String - 食の種類 'T' 皆既食, 'A' 金環食, 'P' 部分食, 'B' 帯食]
100
+ # [ Numeric - 最大食分 ]
101
+ # [ Array - 第1~4接触の日時と地平座標(高度/方位角) ]
102
+ #
103
+ def eclipse_info(date, location, target, base, l_for_h=[location, base])
104
+
105
+ tc = When::Ephemeris.root(+date) {|t| # 離角最小日時
106
+ base.elongation(t, target, location)**2
107
+ }
108
+ mag = base.phase_of_eclipse(tc, target, location) # 食分
109
+ return nil unless mag >= 0 # 食なし
110
+
111
+ t1, t4 = [-0.1, +0.1].map {|dt| # 第1, 第4接触
112
+ When::Ephemeris.root(tc+dt, 0) {|t|
113
+ base.phase_of_eclipse(t, target, location)
114
+ }
115
+ }
116
+
117
+ if mag >= 1
118
+ category = 'T'
119
+ t2, t3 = [-0.01, +0.01].map {|dt| # 第2, 第3接触
120
+ When::Ephemeris.root(tc+dt, 1.0) {|t|
121
+ base.phase_of_eclipse(t, target, location)
122
+ }
123
+ }
124
+ elsif target.phase_of_eclipse(tc, base, location) >= 1
125
+ category = 'A'
126
+ t2, t3 = [-0.01, +0.01].map {|dt| # 第2, 第3接触
127
+ When::Ephemeris.root(tc+dt, 1.0) {|t|
128
+ target.phase_of_eclipse(t, base, location)
129
+ }
130
+ }
131
+ else
132
+ category = 'P'
133
+ end
134
+ ts = [t1,t2,tc,t3,t4].compact
135
+
136
+ form = When::Ephemeris::Formula.new(:location=>l_for_h[0])
137
+ height, azimuth = ts.map {|t| # 基準天体の高度・方位角
138
+ coord = form._coords(t, HORIZONTAL, l_for_h[1])
139
+ [coord.theta * 360, ((0.5-coord.phi)-(0.5-coord.phi).floor) * 360]
140
+ }.transpose
141
+ return nil unless height.max >= 0 # 見えない食
142
+ category += 'B' if height.min < 0 # 地平線下で食が始まる/終わる
143
+
144
+ [category, mag, [ts.map {|t| form._to_seed_type(t, date)}, height, azimuth].transpose]
145
+
146
+ rescue RangeError
147
+ nil
148
+ end
149
+ end
@@ -58,8 +58,10 @@ class When::CalendarNote
58
58
  #
59
59
  # @return [When::TM::CalDate] date またはその直後のイベントの日時
60
60
  #
61
- def event_eval(date, parameter=@event, precision=date.precision)
62
- num, den = parameter.kind_of?(String) ? parameter[/\d.*\z/].split(/\//, 2) : parameter
61
+ def event_eval(date, parameter=@event, precision=nil)
62
+ date = When.when?(date) unless date.kind_of?(When::TimeValue)
63
+ precision ||= date.precision
64
+ num, den = parameter.kind_of?(String) ? (parameter[/\d.*\z/]||'').split(/\//, 2) : parameter
63
65
  num = (num || @num).to_f
64
66
  den = (den || @den).to_f
65
67
  date = date.floor(precision) if precision < date.precision
@@ -67,14 +69,24 @@ class When::CalendarNote
67
69
  is_date_and_time = options.key?(:clock) || precision > When::DAY
68
70
  options[:precision] = precision
69
71
  options[:clock] ||= date.frame.time_basis || When::TM::Clock.local_time
72
+ sdn = _the_date(date, num, den)
73
+ time = When::TM::JulianDate._d_to_t(sdn)
74
+ if @formula.is_dynamical
75
+ time = date.time_standard.from_dynamical_time(time)
76
+ time += options[:clock].universal_time(sdn.round) if options[:clock].kind_of?(When::CalendarTypes::LocalTime)
77
+ end
78
+ event = date.frame.jul_trans(When::TM::JulianDate.universal_time(time), options)
79
+ is_date_and_time ? event : event.to_cal_date
80
+ end
81
+
82
+ # the event date
83
+ def _the_date(date, num, den)
70
84
  quot, mod = (@formula.time_to_cn(date)*30.0).divmod(den)
71
85
  cycle = quot * den + num
72
86
  cycle += den if mod > (num % den)
73
- time = When::TM::JulianDate._d_to_t(@formula.cn_to_time(cycle/30.0))
74
- time = date.time_standard.from_dynamical_time(time) if @formula.is_dynamical
75
- event = date.frame.jul_trans(When::TM::JulianDate.universal_time(time), options)
76
- is_date_and_time ? event : event.to_cal_date
87
+ @formula.cn_to_time(cycle/30.0)
77
88
  end
89
+ private :_the_date
78
90
 
79
91
  # 日付に対応する座標
80
92
  #
@@ -114,7 +126,7 @@ class When::CalendarNote
114
126
  def event_time(date, event_name, event)
115
127
  etime = term(date - When.Duration('P3D'), event, When::SYSTEM)
116
128
  if formula.respond_to?(:year_length) && formula.denominator && formula.denominator < 100000
117
- fraction = etime.clk_time.universal_time
129
+ fraction = etime.clk_time.local_time
118
130
  fraction += When::TM::Duration::DAY * (etime.to_i - date.to_i)
119
131
  fraction = (fraction / When::TM::Duration::DAY * formula.denominator * 1000 + 0.5).floor / 1000.0
120
132
  fraction = fraction.to_i if fraction == fraction.to_i
@@ -159,6 +171,26 @@ class When::CalendarNote
159
171
  end
160
172
  end
161
173
 
174
+ #
175
+ # 冬至を定気で計算し、その他の二十四節気を前後の冬至の日時を時間で等分して求める
176
+ #
177
+ class SolarTermsRevised < SolarTerms
178
+
179
+ # the event date
180
+ def _the_date(date, num, den)
181
+ quot, mod = @formula.time_to_cn(date).divmod(12)
182
+ quot += 1 if mod >= 9
183
+ range = [12*quot-3, 12*quot+9].map {|cn| [cn*30, @formula.cn_to_time(cn)]}
184
+ time = @formula.is_dynamical ? +date : date.to_f
185
+ now = [range[0][0] + (range[1][0] - range[0][0]) / (range[1][1] - range[0][1]) * (time - range[0][1]), time]
186
+
187
+ quot, mod = now[0].divmod(den)
188
+ cycle = quot * den + num
189
+ cycle += den if mod > (num % den)
190
+ range[0][1] + (range[1][1] - range[0][1]) / (range[1][0] - range[0][0]) * (cycle - range[0][0])
191
+ end
192
+ end
193
+
162
194
  #
163
195
  # 月の位相
164
196
  #