lib/when_exe/ephemeris.rb in when_exe-0.3.4 vs lib/when_exe/ephemeris.rb in when_exe-0.3.5

- old
+ new

@@ -1145,40 +1145,12 @@ include When::Ephemeris # # 天体暦機能を When::TM::Calendar クラスに提供する # - module Methods + module ForwardedFormula - # 月の位相が指定の周期番号パターンになる最も近い過去の日時 - # - # @param [Numeric] date ユリウス日(Terrestrial Time) - # @param [When::TM::TemporalPosition] date - # @param [Numeric] n 相対周期番号(n=0 なら date または date の直前が基準) - # @param [Numeric] d 単位周期数 - # - # @return [Numeric, When::TM::TemporalPosition] 周期番号が d で割って n になる日時 - # - def nearest_past_from_lunar_phase(date, n=0, d=1) - @formula ||= When.Resource(['_ep:Formula?formula=12S', '_ep:Formula?formula=1L']) - @formula[-1].nearest_past(date, n, d) - end - - # 二十四節気が指定の周期番号パターンになる最も近い過去の日時 - # - # @param [Numeric] date ユリウス日(Terrestrial Time) - # @param [When::TM::TemporalPosition] date - # @param [Numeric] n 相対周期番号(n=0 なら date または date の直前が基準) - # @param [Numeric] d 単位周期数 - # - # @return [Numeric, When::TM::TemporalPosition] 周期番号が d で割って n になる日時 - # - def nearest_past_from_solar_term(date, n=0, d=1) - @formula ||= When.Resource(['_ep:Formula?formula=12S', '_ep:Formula?formula=1L']) - @formula[0].nearest_past(date, n, d) - end - private # # メソッドのレシーバーとなる Formulaオブジェクトを取得する # @@ -1260,22 +1232,21 @@ def cn_to_time_(cn, time0=nil) time0 ||= (cn - @cycle_number_0m) / @cycle_number_1m root(time0, cn) {|t| time_to_cn(t)} end - # 当該日付のthiti の変化範囲 + # 当該日付の月の位相の変化範囲 # # @param [When::TM::TemporalPosition] date 日付 # - # @return [Range] 当該日付のthiti の変化範囲(朔を含む場合 nil) + # @return [Array<Numeric>] 当該日付の月の位相の変化範囲 # - def thiti_range(date) - date = date.floor - p0, p1 = [date, date.succ].map {|d| - (30.0 * time_to_cn(d)) % 30.0 + def phase_range(date) + date = date.floor + [date, date.succ].map {|d| + time_to_cn(d) } - p0 >= p1 ? nil : p0...p1 end # 指定の周期番号パターンになる最も近い過去の日時 # # @param [Numeric] date ユリウス日(Terrestrial Time) @@ -1772,10 +1743,56 @@ # # Luni-Solar Calendar Formula for Mean Lunation Type # class MeanLunation < Formula + # + # Lunar Calendar Formula + # + module LunarMethod + + private + + # 周期番号 -> 日時 + # + # @param [Numeric] cn 周期番号 + # @param [Numeric] time0 日時の初期近似値 + # + # @return [Numeric] ユリウス日 + # + # @note 半ティティの日時の丸め誤差に配慮 + # + def cn_to_time_(cn, time0=nil) + time0 ||= (cn - @cycle_number_0m) / @cycle_number_1m + return time0 if (cn * 60 - (cn * 60).round).abs > @cycle_precision + ((time0 + 1.0/256 - @day_epoch) / @half_tithi).floor * @half_tithi + @day_epoch + end + end + + # + # Solar Calendar Formula for Fixed Year Length Method + # + module SolarMethod + + private + + # 周期番号 -> 日時 + # + # @param [Numeric] cn 周期番号 + # @param [Numeric] time0 日時の初期近似値 + # + # @return [Numeric] ユリウス日 + # + # @note 太陽黄経が整数になる日時の丸め誤差に配慮 + # + def cn_to_time_(cn, time0=nil) + time0 ||= (cn - @cycle_number_0m) / @cycle_number_1m + return time0 if (cn * 360 - (cn * 360).round).abs > @cycle_precision + ((time0 + 1.0/256 - @day_epoch) / @solar_degree).floor * @solar_degree + @day_epoch + end + end + # 計算の基準経度 / 度 # @return [Numeric] attr_reader :long # 計算の元期(年) @@ -1849,91 +1866,47 @@ # alias :_true_moon_ :_mean_moon_ private - # 周期番号 -> 日時 - # - # @param [Numeric] cn 周期番号 - # @param [Numeric] time0 日時の初期近似値 - # - # @return [Numeric] ユリウス日 - # - def cn_to_time_(cn, time0=nil) - time0 ||= (cn - @cycle_number_0m) / @cycle_number_1m - case @formula - when /S/ ; ((time0 + 1.0/256 - @day_epoch) / @solar_terms).floor * @solar_terms + @day_epoch - when /L/ ; ((time0 + 1.0/256 - @day_epoch) / @month_tithi).floor * @month_tithi + @day_epoch - end - end - # オブジェクトの正規化 def _normalize(args=[], options={}) Rational @time_standard ||= 'universal' @epoch_shift ||= 1721139 # 西暦 0 年 春分 @day_shift ||= Rational(-1,2) # 夜半 -1/2, 日出 -1/4 - @day_shift = @day_shift.to_r + @day_shift = @day_shift.to_r @longitude_shift ||= Rational(-1,4) # 冬至 -1/4, 立春 -1/8 @longitude_shift = @longitude_shift.to_r - @day_epoch = @day_epoch.to_i + @day_shift + @day_epoch = (@day_epoch.to_f == @day_epoch.to_i ? @day_epoch.to_i : @day_epoch.to_f) + @day_shift @year_length = @year_length.to_r - @lunation_length = @lunation_length.to_r - @month_length = 1 / (1.to_r/@year_length + 1.to_r/@lunation_length) - @denominator = [@year_length.denominator, @lunation_length.denominator].max - @solar_terms = @year_length / 24 - @month_tithi = @lunation_length / 30 - @year_epoch = 0 - @year_epoch = @longitude_shift -_mean_sun_(@epoch_shift).to_i - @month_epoch = 0 - @month_epoch = @longitude_shift -_mean_moon_(@epoch_shift).to_i - super - end - end + @year_delta = @year_delta.to_f * 1.0E-6 if @year_delta + if @year_epoch + @year_epoch = @year_epoch.to_f + else + @year_epoch = 0 + @year_epoch = @longitude_shift -_mean_sun_(@epoch_shift).to_i + end + @cycle_precision ||= 1.0E-8 + @cycle_precision = @cycle_precision.to_f - # - # Solar Calendar Formula for Variable Year Length Method - # - class VariableYearLengthMethod < Formula - - # 日時 -> 周期番号 - # - # @param [Numeric] t ユリウス日(Terrestrial Time) - # @param [When::TM::TemporalPosition] t - # - # @return [Numeric] 周期番号 - # - def time_to_cn(t, cn0=nil) - cn0 ||= (t.to_f - @day_epoch) / @year_length + @year_epoch + @longitude_shift - root(cn0 * 12, t.to_f) {|cn| cn_to_time(cn) } - end - - # 周期番号 -> 日時 - # - # @param [Numeric] cn 周期番号 - # @param [Numeric] time0 日時の初期近似値 - # - # @return [Numeric] ユリウス日 - # - def cn_to_time_(cn, time0=nil) - t, n = (cn / 12.0 - @longitude_shift - @year_epoch).divmod(1) - @day_epoch + @year_length * t - @year_delta * t * (t-1) + (@year_length - 2 * @year_delta * t) * n - end - - private - - # オブジェクトの正規化 - def _normalize(args=[], options={}) - Rational - @time_standard ||= 'universal' - @day_shift ||= Rational(-1,2) # 夜半 -1/2, 日出 -1/4 - @day_shift = @day_shift.to_r - @longitude_shift ||= Rational(-1,4) # 冬至 -1/4, 立春 -1/8 - @longitude_shift = @longitude_shift.to_r - @day_epoch = @day_epoch.to_f + @day_shift - @year_epoch = @year_epoch.to_f - @year_length = @year_length.to_f - @year_delta = @year_delta.to_f * 1.0E-6 + if @lunation_length && /S/i !~ @formula + # 月の位相の計算 + @lunation_length = @lunation_length.to_r + @month_length = 1 / (1.to_r/@year_length + 1.to_r/@lunation_length) + @half_tithi = @lunation_length / 60 + if @month_epoch + @month_epoch = @month_epoch.to_f + else + @month_epoch = 0 + @month_epoch = @longitude_shift -_mean_moon_(@epoch_shift).to_i + end + class << self; include LunarMethod; end + else + # 太陽黄経の計算 + @solar_degree = @year_length / 360 + class << self; include SolarMethod; end + end super end end end