Put time and distance on a scale
Before we can calculate a planet’s motion, we need to know how much time has passed and how its position is measured. A calendar date and a distance in kilometers are familiar ways to describe those things. In this lesson, we will translate them into the day counts, time offsets and distance units used by the preparation calculations, following what each change means as we go.
Before this lesson
Read “Start with recorded positions” first. The calculations here use subtraction, multiplication, division and powers such as u² = u × u. We will work through an example before writing each unfamiliar calculation in its general form.
What you will learn
By the end, you will be able to turn a day count into elapsed seconds, follow the engine’s approximate time model, and convert a position or velocity without losing track of its units.
Dotted-underlined terms open a definition beside the text. Select one to read more, then close it to continue.
Each step has its own check. Pass every step to complete the lesson. Your answers and checked steps are saved in this browser, so you can continue after leaving or reloading.
1. Convert Julian dates to ephemeris seconds
A calendar organizes time into days, months and years. That makes dates convenient to read, but finding the time between two dates means accounting for different month lengths and leap years. When calculating a planet’s motion, we can simplify that bookkeeping by counting days continuously. The elapsed time between two readings then becomes a subtraction: the later day count minus the earlier one.
Astronomers call this continuous day count a Julian date A Julian date is a continuous count of days with a fractional part for the time within a day. Whole-number boundaries fall at noon. For example, 2451545.25 is a quarter day after 2451545.0.The count must carry a time-scale label. A Julian date on one scale cannot be treated as a reading on another scale simply because both are day counts. Explanatory Supplement: Julian date history, section 15.1.10Jet Propulsion Laboratory: time conventions for planetary calculations. The fractional part records the time within a day, so we can describe part of a day without introducing hours and minutes into the calculation. Unlike an ordinary calendar day, each whole-number boundary falls at noon. Adding 0.25 to the count therefore moves us six hours beyond that boundary.
Behind the name: why “Julian”?
In 1583, Joseph Scaliger introduced a long cycle of years called the Julian period to bring several chronological cycles into one system. He called it Julian because it was based on Julian calendar years; the calendar itself takes its name from Julius Caesar.
Nineteenth-century astronomers adapted the system to count days. The resulting Julian date retained the name, but serves a different purpose from a date written in the Julian calendar: it gives us a continuous count that we can subtract directly.
There is one more detail to settle before we subtract. The count tells us how a date is written, but we also need to know which time scale supplies the reading. For this calculation, the dates must use Barycentric Dynamical Time This time scale is used to describe motion in the solar system. “Barycentric” refers to the solar system’s center of mass; “dynamical” refers to calculations of motion.For this step, you need to recognize the TDB label and supply dates already expressed on that scale. Converting from everyday clock time is a separate operation. Jet Propulsion Laboratory: time conventions for planetary calculations, the scale used to model motion in the solar system. We will keep that label beside the numbers so the assumption stays visible.
Suppose our reference reading is JD 2451545.0 TDB, which is noon on January 1, 2000 on that scale. A later reading of JD 2451545.25 TDB is a quarter day beyond it. Subtraction gives 0.25 days. Each TDB day contains 86,400 seconds, so multiplying by 86,400 gives an elapsed time of 21,600 seconds, or six hours.
(2451545.25 − 2451545.0) × 86400 = 21600 seconds
The same reasoning works for dates before the reference. JD 2451544.5 TDB is half a day earlier, so subtraction gives −0.5 days and multiplication gives −43,200 seconds. The minus sign tells us which side of the reference instant we are on.
This offset is called Ephemeris time in this calculation An ephemeris is a table or model describing celestial positions over time. Here, ephemeris time means elapsed TDB seconds from noon January 1, 2000 TDB, following the convention used by the Jet Propulsion Laboratory’s planetary-calculation software.ET has also named an older astronomical time standard. In this formula it is the TDB offset, not a request to convert to that historical standard. Jet Propulsion Laboratory: time conventions for planetary calculations. We can now write the calculation for any supplied TDB Julian date. In the equation, JD_TDB is that input day count, ET is the resulting offset, and s/day means seconds per day. The source-curve fitter uses this offset to describe its time intervals.
ET = (JD_TDB − 2451545.0) × 86400 s/day
What does J2000.0 refer to?
An epoch is a reference instant. J2000.0 names an astronomical epoch at noon on January 1, 2000 in Terrestrial Time “Terrestrial” means Earth-related. This astronomical time scale is used for calculations of celestial positions as seen from Earth.In practical timekeeping, TT is International Atomic Time (TAI) plus 32.184 seconds. TAI takes its abbreviation from the French Temps atomique international. TDB and TT are distinct time scales, even though their readings are close. United States Naval Observatory: Terrestrial TimeJet Propulsion Laboratory: time conventions for planetary calculations. The J identifies a Julian epoch and 2000.0 gives its year.
You may also see planetary software describe its TDB offset as “seconds past J2000.” Keep the convention in view: this formula uses noon January 1, 2000 TDB, while the astronomical epoch J2000.0 is specified in TT. Those are different instants.
See the teaching TypeScript
const jdToEt = (jdTdb: number): number => (jdTdb - 2451545.0) * 86400;Finite, correctly labeled inputs are assumed. This demonstrates the arithmetic; it does not fetch data or replace the engine.
Connect this step to the source
tools/jpl/cheby_fit.py
jd_to_et
Paths refer to the astrology-engine repository. Examples use invented inputs; a successful exercise is not an astronomical-accuracy test.
Sources for this section
Apply this step
Answer every part, then check. You can retry as often as you like.
2. Construct the engine time model
We have turned a supplied date into seconds for the source-curve fitter. The chart calculations need another view of time, because the sky we see depends on both the motion of celestial bodies and the rotation of Earth. These processes do not give us exactly the same kind of clock.
Imagine using Earth itself as a clock, reading how far it has turned. That is the idea behind Universal Time measured from Earth’s rotation UT1 measures time through Earth’s rotation, using astronomical observations. The numeral identifies this particular form of Universal Time.Because Earth does not rotate at a perfectly constant rate, UT1 and atomic-clock time gradually diverge. UTC is kept close to UT1, but their readings are not identical. United States Naval Observatory: Universal Time. Earth’s rotation varies slightly, so this clock does not advance at a perfectly steady rate. For calculations that need a uniform time scale, astronomers also use Terrestrial Time “Terrestrial” means Earth-related. This astronomical time scale is used for calculations of celestial positions as seen from Earth.In practical timekeeping, TT is International Atomic Time (TAI) plus 32.184 seconds. TAI takes its abbreviation from the French Temps atomique international. TDB and TT are distinct time scales, even though their readings are close. United States Naval Observatory: Terrestrial TimeJet Propulsion Laboratory: time conventions for planetary calculations, which follows atomic-clock time.
The difference between the two readings is called Delta T, written ΔT. The Greek letter delta means a difference here: subtract Earth-rotation time from Terrestrial Time, and express the result in seconds. This is the quantity the engine estimates when building its approximate time model.
ΔT = TT − UT1, in seconds
To follow the engine’s arithmetic, start with an instant represented by hifitime, the time library used by the runtime. Its Epoch An epoch is a specified instant. It can be the reference instant from which elapsed time is counted. In hifitime, Epoch is also the name of the value that represents an instant and supports expressing it on different time scales. value can express that instant on different time scales. The engine asks it for a UTC Julian date, subtracts 2451545.0, and stores the result in a field named ut. For a supplied UTC Julian date of 2451559.0, subtraction gives ut = 14 days.
At ut = 14 days, the model estimates ΔT as 63.86 seconds; the next section explains where that number comes from. We cannot add seconds directly to a value in days. Dividing by 86,400 first gives the correction in days, which we can then add to 14.
tt = 14 + 63.86 / 86400 = 14.00073912037 days (rounded)
Written generally, the two steps are below. JD_UTC means the Julian date returned on the UTC scale, and ΔT(ut) means the model’s estimate evaluated at that day offset. Later rotation and orientation formulas consume these ut and tt fields. This example begins after the library has supplied the UTC date; the arithmetic shown here does not implement the time-scale conversion itself.
ut = JD_UTC − 2451545.0
tt = ut + ΔT(ut) / 86400
See the teaching TypeScript
const modeledTt = (ut: number, deltaSeconds: number): number => ut + deltaSeconds / 86400;Finite, correctly labeled inputs are assumed. This demonstrates the arithmetic; it does not fetch data or replace the engine.
Connect this step to the source
src/astro/time.rs
AstroTime::from_tdb
Paths refer to the astrology-engine repository. Examples use invented inputs; a successful exercise is not an astronomical-accuracy test.
Sources for this section
Apply this step
Answer every part, then check. You can retry as often as you like.
3. Evaluate the piecewise Delta T approximation
The preceding step needed an estimate of the difference between atomic and Earth-rotation time. That difference changes over history, so one short formula would struggle to describe the whole range. The engine instead chooses among several formulas, each intended for a particular interval of years. This is called a piecewise approximation: the date determines which piece we evaluate.
Before choosing a piece, the engine turns its ut day offset into an approximate year. Return to ut = 14 days from the previous example. Subtracting 14 leaves zero, so the year is 2000. For other offsets, the engine divides the shifted day count by 365.24217 and adds it to 2000. These constants are choices in the current model, rather than a general way to convert every calendar date.
y = 2000 + (ut − 14) / 365.24217
Now suppose this calculation has given us y = 2020. That year lies in the piece covering 2005 up to, but not including, 2050. Within this piece, we measure years from 2000, so the local variable u is 2020 − 2000 = 20. The formula combines a constant, a term proportional to u, and a term proportional to u². A sum of terms like these is a polynomial.
ΔT = 62.92 + 0.32217 × 20 + 0.005589 × 20²
Work through the terms separately: 20² is 400, the linear term is 6.4434, and the squared term is 2.2356. Adding them to 62.92 gives 71.599 seconds. The coefficients are ordered [62.92, 0.32217, 0.005589]: the constant first, then the coefficient of u, then the coefficient of u².
ΔT = 62.92 + 6.4434 + 2.2356 = 71.599 seconds
We can also arrange that arithmetic from the inside out. Multiply the last coefficient by 20, add the next coefficient, multiply by 20 again, and finally add the constant. This is Horner evaluation. It gives the same answer while avoiding a separate calculation of each power, which is useful for the longer polynomials in the model.
ΔT = (0.005589 × 20 + 0.32217) × 20 + 62.92 = 71.599 seconds
The general rule for this piece is ΔT = 62.92 + 0.32217u + 0.005589u², with u = y − 2000. Each other piece has its own expression for u and its own coefficients. At y = 2000, the engine uses the earlier 1986–2005 piece. Its u is zero, leaving the constant 63.86 seconds used in the preceding section.
At a boundary, the upper limit belongs to the next piece. For y = 2005, we therefore use the 2005–2050 formula with u = 5, giving 64.670575 seconds. At exactly 2050, we move on again and must recompute u using the next piece’s rule. The complete interval table below lets you inspect those choices.
Where these estimates come from
Fred Espenak and Jean Meeus developed the polynomial expressions published by the National Aeronautics and Space Administration (NASA) for the Five Millennium Canon of Solar Eclipses. The formulas draw on estimates of how Earth’s rotation has differed from uniform time over history.
The engine uses that coefficient family with its own day-offset-to-year calculation. It does not apply the separate lunar-acceleration correction described for the Canon. Outside the middle intervals it still produces a result through extrapolation, without an uncertainty estimate. Reproducing its arithmetic tells us how the engine behaves; it does not establish timekeeping accuracy.
See the teaching TypeScript
const polynomial = (u: number, coefficients: readonly number[]): number =>
coefficients.reduceRight((acc, c) => acc * u + c, 0);
// Coefficients are ordered [a0, a1, a2, ...].Finite, correctly labeled inputs are assumed. This demonstrates the arithmetic; it does not fetch data or replace the engine.
All intervals in the current engine
Every result below is in seconds. P(u; a₀, a₁, …) means a₀ + a₁u + a₂u² + …, evaluated with the Horner function above. A superscript is a power: u³ = u × u × u. The interval tests use the engine’s approximate year y.
- y < −500
- u = (y − 1820) / 100
−20 + 32u² - −500 ≤ y < 500
- u = y / 100
P(u; 10583.6, −1014.41, 33.78311, −5.952053, −0.1798452, 0.022174192, 0.0090316521) - 500 ≤ y < 1600
- u = (y − 1000) / 100
P(u; 1574.2, −556.01, 71.23472, 0.319781, −0.8503463, −0.005050998, 0.0083572073) - 1600 ≤ y < 1700
- u = y − 1600
120 − 0.9808u − 0.01532u² + u³/7129 - 1700 ≤ y < 1800
- u = y − 1700
P(u; 8.83, 0.1603, −0.0059285, 0.00013336, −1/1174000) - 1800 ≤ y < 1860
- u = y − 1800
P(u; 13.72, −0.332447, 0.0068612, 0.0041116, −0.00037436, 0.0000121272, −0.0000001699, 0.000000000875) - 1860 ≤ y < 1900
- u = y − 1860
P(u; 7.62, 0.5737, −0.251754, 0.01680668, −0.0004473624, 1/233174) - 1900 ≤ y < 1920
- u = y − 1900
P(u; −2.79, 1.494119, −0.0598939, 0.0061966, −0.000197) - 1920 ≤ y < 1941
- u = y − 1920
P(u; 21.20, 0.84493, −0.076100, 0.0020936) - 1941 ≤ y < 1961
- u = y − 1950
29.07 + 0.407u − u²/233 + u³/2547 - 1961 ≤ y < 1986
- u = y − 1975
45.45 + 1.067u − u²/260 − u³/718 - 1986 ≤ y < 2005
- u = y − 2000
P(u; 63.86, 0.3345, −0.060374, 0.0017275, 0.000651814, 0.00002373599) - 2005 ≤ y < 2050
- u = y − 2000
62.92 + 0.32217u + 0.005589u² - 2050 ≤ y < 2150
- u = (y − 1820) / 100
−20 + 32u² − 0.5628(2150 − y) - 2150 ≤ y
- u = (y − 1820) / 100
−20 + 32u²
Connect this step to the source
src/astro/time.rs
delta_t_seconds; poly
Paths refer to the astrology-engine repository. Examples use invented inputs; a successful exercise is not an astronomical-accuracy test.
Sources for this section
Apply this step
Answer every part, then check. You can retry as often as you like.
4. Convert state units
We now have time expressed in the units required by the calculations. Position and velocity need the same attention. A vector measured in kilometers and a vector measured in another length unit can describe the same location, but the numerical components will differ. We need a conversion that changes their units while preserving their signs, axes and origin.
For solar-system distances, astronomers often use the Earth–Sun distance as a convenient scale. The corresponding length unit is called an Astronomical unit An astronomical unit is a length roughly equal to the average Earth–Sun distance. Since 2012 its definition has been fixed at exactly 149,597,870,700 meters, or 149,597,870.7 kilometers.AU/day combines this length unit with a day to express velocity. The unit applies separately to each component of a position or velocity vector. International Astronomical Union: the 2012 astronomical-unit definition. Its fixed value is 149,597,870.7 kilometers. A position component of that many kilometers is therefore 1 AU; dividing a kilometer component by this value gives the component in AU.
Take an invented position vector (149597870.7, 0, 0) km. Converting each component gives (1, 0, 0) AU. A component on the other side of the origin keeps its minus sign: −299195741.4 km becomes −2 AU. These numbers illustrate the unit conversion rather than an observed orbit.
position_AU = position_km / 149597870.7
How the astronomical unit became an exact length
Earlier definitions connected the astronomical unit to conventions used in calculating orbital motion. In 2012, the International Astronomical Union fixed it at exactly 149,597,870,700 meters. That decision lets us use one stated length in the conversion, without making the unit depend on an orbital calculation.
Velocity involves two units, so it needs two changes. Suppose a component is 1 kilometer per second. Dividing by 149,597,870.7 expresses the same component in AU per second. To express it per day, multiply by the 86,400 seconds in a day. Both steps are needed: the first changes the length unit, while the second changes the time unit.
1 km/s × (1 AU / 149597870.7 km) × (86400 s/day) ≈ 0.000577548327 AU/day
Notice how the units cancel in that expression: kilometers cancel with kilometers, and seconds cancel with seconds, leaving AU/day. For an invented velocity vector (0, 1, 0) km/s, the result is approximately (0, 0.000577548327, 0) AU/day. Written for any component, the conversion is:
velocity_AU/day = velocity_km/s × 86400 / 149597870.7
The engine’s KmStateProvider applies these conversions to all three components and keeps the frame label. Multiplying them by the same positive factor preserves direction. The source uses a precomputed reciprocal for the length conversion; division here makes the relationship between the units easier to follow.
There is one other kind of unit to distinguish before moving on. Small angles are often measured in arcseconds. An Arcsecond An arcsecond is 1/3,600 of a degree. The “arc” in its name indicates an angle, so it is distinct from a second of elapsed time. A full turn contains 360 degrees. International Bureau of Weights and Measures: units of measurement is 1/3,600 of a degree, so 7,200 arcseconds is 2 degrees. Despite the name, this measures an angle rather than elapsed time. Turning a distance into an angle requires geometry and a distance to the observer; neither of the time or length conversions above performs that calculation.
See the teaching TypeScript
const kmToAu = (km: number): number => km / 149597870.7;
const speedToAuPerDay = (kmPerSecond: number): number => kmToAu(kmPerSecond) * 86400;Finite, correctly labeled inputs are assumed. This demonstrates the arithmetic; it does not fetch data or replace the engine.
Connect this step to the source
tools/dataset-builder/src/astro/provider.rs
KmStateProvider::state_at
Paths refer to the astrology-engine repository. Examples use invented inputs; a successful exercise is not an astronomical-accuracy test.
Sources for this section
Apply this step
Answer every part, then check. You can retry as often as you like.
Your lesson checks
0 of 4 steps passed.
Use the feedback beside each check to retry any unfinished step.