Skip to content

Commit

Permalink
Calculates leap seconds for an instant (#54)
Browse files Browse the repository at this point in the history
To know the difference between universal time (UT) and dynamical time
(TD), we need to be aware of the leap seconds to take into account.

This supports leap seconds from 1800-01-01 to 2024-01-01 (with the most
recent leap second being added on 2017-01-01).
  • Loading branch information
rhannequin committed Apr 10, 2024
1 parent 92022b9 commit c557fea
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 0 deletions.
56 changes: 56 additions & 0 deletions lib/astronoby/util/time.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,62 @@ def self.decimal_hour_to_time(date, decimal)

::Time.utc(date.year, date.month, date.day, hour, minute, second).round
end

# @param instant [Numeric, Time, Date, DateTime]
# @return [Integer, Float] Number of leap seconds for the given instant
def self.terrestrial_universal_time_delta(instant)
# Source:
# Title: Astronomical Algorithms
# Author: Jean Meeus
# Edition: 2nd edition
# Chapter: 10 - Dynamical Time and Universal Time

jd = case instant
when Numeric
instant
when ::Time, ::Date, ::DateTime
Epoch.from_time(instant)
else
raise IncompatibleArgumentsError,
"Expected a Numeric, Time, Date or DateTime object, got #{instant.class}"
end

return 69 if jd >= 2457754.5
return 68 if jd >= 2457204.5
return 67 if jd >= 2456109.5
return 66 if jd >= 2454832.5
return 65 if jd >= 2453736.5
return 64 if jd >= 2451179.5
return 63 if jd >= 2450814.5

theta = ((jd - Epoch::J1900) / 365.25) / 100.0
if (2415020.5...2450814.5).cover?(jd) # 1900 - 1997
return -2.44 +
87.24 * theta +
815.20 * theta**2 -
2_637.80 * theta**3 -
18_756.33 * theta**4 +
124_906.15 * theta**5 -
303_191.19 * theta**6 +
372_919.88 * theta**7 -
232_424.66 * theta**8 +
58_353.42 * theta**9
elsif (2378496.5...2415020.5).cover?(jd) # 1800 - 1899
return -2.5 +
228.95 * theta +
5_218.61 * theta**2 +
56_282.84 * theta**3 +
324_011.78 * theta**4 +
1_061_660.75 * theta**5 +
2_087_298.89 * theta**6 +
2_513_807.78 * theta**7 +
1_818_961.41 * theta**8 +
727_058.63 * theta**9 +
123_563.95 * theta**10
end

0.0
end
end
end
end
36 changes: 36 additions & 0 deletions spec/astronoby/util/time_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,40 @@
end
end
end

describe "::terrestrial_universal_time_delta" do
it "returns the number of seconds between TT and UT for a given Julian Day" do
epoch = 2437665.5 # 1962-01-01T00:00:00

delta = described_class.terrestrial_universal_time_delta(epoch).round(2)

expect(delta).to eq 34.56
end

it "returns the number of seconds between TT and UT for a given Time object" do
time = Time.utc(1977, 1, 1) # 2443144.5

delta = described_class.terrestrial_universal_time_delta(time).round(2)

expect(delta).to eq 46.98
end

it "returns the number of seconds between TT and UT for a given Date object" do
date = Date.new(1980, 1, 1) # 2444239.5

delta = described_class.terrestrial_universal_time_delta(date).round(2)

expect(delta).to eq 50.07
end

context "when the Julian Day is out of range" do
it "returns 0" do
date = Date.new(1700, 1, 1) # 2341972.5

delta = described_class.terrestrial_universal_time_delta(date)

expect(delta).to eq 0
end
end
end
end

0 comments on commit c557fea

Please sign in to comment.