diff --git a/lib/astronoby.rb b/lib/astronoby.rb index 214d18c..58863bf 100644 --- a/lib/astronoby.rb +++ b/lib/astronoby.rb @@ -21,6 +21,7 @@ require "astronoby/time/greenwich_sidereal_time" require "astronoby/time/local_sidereal_time" require "astronoby/util/astrodynamics" +require "astronoby/util/time" require "astronoby/util/trigonometry" require "astronoby/true_obliquity" require "astronoby/version" diff --git a/lib/astronoby/util/time.rb b/lib/astronoby/util/time.rb new file mode 100644 index 0000000..a6ad153 --- /dev/null +++ b/lib/astronoby/util/time.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +module Astronoby + module Util + module Time + # @param date [Date] + # @param decimal [Numeric] Hour of the day, in decimal hours + # @return [::Time] Date and time + def self.decimal_hour_to_time(date, decimal) + absolute_hour = decimal.abs + hour = absolute_hour.floor + + unless hour.between?(0, 24) + raise IncompatibleArgumentsError, "Hour must be between 0 and 24, got #{hour}" + end + + decimal_minute = 60 * (absolute_hour - hour) + absolute_decimal_minute = (60 * (absolute_hour - hour)).abs + minute = decimal_minute.floor + second = 60 * (absolute_decimal_minute - absolute_decimal_minute.floor) + + ::Time.utc(date.year, date.month, date.day, hour, minute, second).round + end + end + end +end diff --git a/spec/astronoby/util/time_spec.rb b/spec/astronoby/util/time_spec.rb new file mode 100644 index 0000000..2519e33 --- /dev/null +++ b/spec/astronoby/util/time_spec.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +RSpec.describe Astronoby::Util::Time do + describe "::decimal_hour_to_time" do + it "returns a Time object" do + date = Date.new + decimal = 0 + + expect(described_class.decimal_hour_to_time(date, decimal)).to be_a Time + end + + it "converts a decimal time to a Time format" do + date = Date.new(2024, 3, 14) + decimal = 12.34 + + time = described_class.decimal_hour_to_time(date, decimal) + + expect(time).to eq Time.utc(2024, 3, 14, 12, 20, 24) + end + + context "when the decimal time is out of range" do + it "raises an error" do + expect { described_class.decimal_hour_to_time(Date.new, 25) } + .to raise_error( + Astronoby::IncompatibleArgumentsError, + "Hour must be between 0 and 24, got 25" + ) + end + end + end +end