Calculate New Moon Dates

In my last post (Calculate Future Solar Eclipses) I showed how to calculate the types of solar eclipses that would occur for a given date range. I took a shortcut and used a NewMoonData class that had a list of all known new moon dates that I culled from the timeanddate.com website. That worked just fine for the purposes of that blog post.

But in the real world who wants to hardcode every single new moon date into the far future? That’s not a realistic solution. I’m following up with an implementation in C# .NET, based on Jean Meeus’ algorithm he adopted from the ELP-2000/82 theory for the Moon. The results show the exact instant of the new moon phase (UTC) for any date from -1999 BCE to +3000 CE, accurate to within a few seconds.

The code is checked into my repo at FindNewMoonConsoleApp. Feel free to clone the code base and take it for a test ride. I won’t do a full walkthrough like with the solar eclipse calculations. I’ll just say that the general approach I took was to start with the first new moon in the J2000.0 epoch (6 Jan 2000) and enumerate over the mean new moon phases that follow. Starting with 6 Jan 2000 the program adds the lunar cycle of 29.5306 days to get 4 Feb 2000. Add the lunar cycle again and you get 5 Mar 2000, and so on for as many months and years as you like.

Sounds easy right? The problem is there are forces of gravity pulling on the Moon and Earth. And none of these bodies move at constant rates. So, the times of the mean phases of the moon just gets us in the ballpark of give or take a day or so. From there we have to apply an algorithm that corrects for all of the perturbations in order to get a more accurate date and time for each new moon.

Suppose I want to know the instant of the new moon in Dec 2022. I run the program and get: 12/23/2022 10:16:47 UTC. The Griffith Observatory, which uses the NASA/JPL Horizons system, rounds it up to 12/23/2022 10:17 UTC.

The program will produce results for every new moon that are accurate to within several seconds for any date range you provide.

Clear skies!

 

 

 

 

 

 

 

 

 

 

Calculate Future Solar Eclipses

According to Herodotus, who wrote The History around 430 BCE, a total solar eclipse interrupted a battle between the Lydians and the Medes:

[J]ust as the battle was growing warm, day was on a sudden changed into night. This event had been foretold by Thales, the Milesian, who forewarned the Ionians of it, fixing for it the very year in which it actually took place. The Medes and Lydians, when they observed the change, ceased fighting, and were alike anxious to have terms of peace agreed on.

(Source: Internet Classic Archives)

This “battle of the eclipse” took place in what is now Turkey, and the eclipse itself could have been the one that occurred on 28 May 585 BCE. Unfortunately, if Thales wrote anything it didn’t survive the centuries. So, we don’t know if he really did predict the eclipse or by what means he did it. All we have is Herodotus to go on. In any case, it’s the first mention in history of anyone predicting an eclipse so it’s interesting on that basis alone.

Wouldn’t it be cool if we could figure out when future solar eclipses occurred for us in the next decade or so? That’s what we’re going to do in this blog post so read on. Continue reading “Calculate Future Solar Eclipses”

Let’s Make a Sundial!

Let’s make a sundial that tells the hour of the day. I know what you’re thinking. Can’t I just go to my local garden store and buy one? Nope. Those are just for decoration only. A real sundial, one that accurately tells the time, must be built for your location (latitude). All sundials are local.

I recommend reading my previous post on building a solar calendar. Also, if you’ve never given much thought to the apparent motion of the sun across the sky, then check out my post on sidereal time. If you know all about sundials and you just want to build one, then read on!

Continue reading “Let’s Make a Sundial!”

Pretty Good Pipeline (PGP)

With apologies to Phil Zimmermann, I’ve put together a “pretty good pipeline” using Azure Pipelines, a multi-stage YAML file, and a couple of ARM templates to deploy a typical .NET Core 3.1 API to an Azure App Service. This won’t be a walkthrough or a “how to” so much as general guidance with links to relevant documentation for more information. From a high-level the pipeline will look something like this diagram:

I am not going to talk about containerization, A/B testing, the latest trends in DevOps, or continuous delivery where a dozen production releases are all in a day’s work.  This is just vanilla guidance for a typical mid-sized shop. If this still interests you then read on.

Continue reading “Pretty Good Pipeline (PGP)”

JSON Variable Substitution in Multi-Stage YAML Pipeline with Azure Key Vault

In my last post I showed how to configure JSON variable substitution with secret variables right in the pipeline. Now in this follow up post I want to expand on that to show how you could instead store your secrets in an Azure Key Vault and reference them in the pipeline. See the publicly visible TimeApi project on Azure DevOps for the source code, ARM templates, and the YAML file.

Continue reading “JSON Variable Substitution in Multi-Stage YAML Pipeline with Azure Key Vault”

JSON Variable Substitution in Multi-Stage YAML Azure Pipeline

If you made it past that long and technical article title then you are here for a purpose. Maybe you’re just getting started with the relatively new YAML experience in Azure Pipelines.  Or maybe you’ve been doing this awhile and found the variables guidance to be less than clear. In any case, in this article I’m going to show how to reference pipeline variables in an Azure Pipelines CI/CD multi-stage YAML file. See also the followup post to this one in which variables are moved into an Azure Key Vault.

Continue reading “JSON Variable Substitution in Multi-Stage YAML Azure Pipeline”

Calculate Distance Between Two Points on Earth

In two-dimensional space (a plane), the shortest distance between two points is a line. The shortest distance between two points on a sphere is the great-circle distance. The shorter arc described by the great circle running through the two points is then calculated by this well known formula below. Given the geographical longitude and latitude \(L_1, \phi_1\) of point P and \(L_2, \phi_2\) of point Q:

$$\cos d = \sin \phi_1 \space \sin \phi_2 + \cos \phi_1 \space \cos \phi_2 \space \cos (L_1 – L_2)$$

Where d is expressed in degrees:

$$d = \arccos (\sin \phi_1 \space \sin \phi_2 + \cos \phi_1 \space \cos \phi_2 \space \cos (L_1 – L_2))$$

By CheCheDaWaff – Own work, CC BY-SA 4.0, https://commons.wikimedia.org/w/index.php?curid=48187293

I once worked at a logistics company primarily as a database developer. I was asked to calculate distances between various ports in China and the U.S. in order to estimate fuel costs. I implemented the above great-circle algorithm in an Oracle PL/SQL package and it worked just fine. However, the Earth isn’t a sphere. Because of centrifugal force generated from the Earth’s rotation it bulges at the equator. It’s better to say that the Earth is a spheroid or an ellipsoid.

So while the great-circle algorithm is good enough what if we want even greater accuracy? To do that we need to take into account the Earth’s true shape as an ellipsoid. There are two variables we need. We need to know the equatorial radius of the Earth (a) and we need to know its flattening (f). Consider this ellipse that represents the Earth with an exaggerated equatorial bulge:

The equatorial radius AC (or BC) is labeled a and flattening f is the ratio of \(a – b \over a\). These values are constants accepted by the International Astronomical Union (IAU) and I can pull them from the wiki:

a = 6378.140 km

f = 0.00335281

Given these two constants we can now calculate the geodesic distance between two points on the Earth’s surface using Andoyer’s Formula. Here I’ve created the program in C# following Meeus’ Method as described in his book Astronomical Algorithms (p. 85). This method will produce an error of +/- 50 meters.

First there are two helper classes. DoubleExtensions has a method ToRadians that will be necessary for the trigonometric functions:

public static class DoubleExtensions
{
    public static double ToRadians(this double d)
    {
        return d * (Math.PI / 180); // convert degrees to radians
    }

    public static double ToDegrees(this double d)
    {
        return d * (180 / Math.PI); // convert radians to degrees
    }
}

And I created a small struct to wrap the geocoordinates of the two points between which we want to calculate the distance:

public struct GeoCoordinate
{
    public GeoCoordinate(double latitude, double longitude)
    {
        Latitude = latitude;
        Longitude = longitude;
        Name = "Unknown";
    }

    public GeoCoordinate(double latitude, double longitude, string name)
    {
        Latitude = latitude;
        Longitude = longitude;
        Name = name;
    }

    public double Latitude { get; }
    public double Longitude { get; }
    public string Name { get; }
}

With those two helpers in place the main program will calculate the distance between the Observatoire de Paris and the U.S. Naval Observatory in Washington, D.C.

class Program
{
    static void Main(string[] args)
    {
        // constants
        const double a = 6378.140;
        const double f = 0.00335281;

        var p = new GeoCoordinate(
            48.83698, -2.33652, "Observatoire de Paris"); 
        var q = new GeoCoordinate(
            38.921261, 77.06652, "U.S. Naval Observatory");

        double F = (p.Latitude + q.Latitude) / 2;
        double G = (p.Latitude - q.Latitude) / 2;
        double L = (p.Longitude - q.Longitude) / 2;

        double S = Math.Pow(Math.Sin(G.ToRadians()), 2) 
            * Math.Pow(Math.Cos(L.ToRadians()), 2) 
            + Math.Pow(Math.Cos(F.ToRadians()), 2) 
            * Math.Pow(Math.Sin(L.ToRadians()), 2);

        double C = Math.Pow(Math.Cos(G.ToRadians()), 2) 
            * Math.Pow(Math.Cos(L.ToRadians()), 2) 
            + Math.Pow(Math.Sin(F.ToRadians()), 2) 
            * Math.Pow(Math.Sin(L.ToRadians()), 2);

        double O = Math.Atan(Math.Sqrt(S / C));
        double R = Math.Sqrt(S * C) / O;
        double D = 2 * O * a;
        double H1 = (3 * R - 1) / (2 * C);
        double H2 = (3 * R + 1) / (2 * S);

        double s = D * (1 + f * H1 
            * Math.Pow(Math.Sin(F.ToRadians()), 2) 
            * Math.Pow(Math.Cos(G.ToRadians()), 2) 
            - f * H2 
            * Math.Pow(Math.Cos(F.ToRadians()), 2) 
            * Math.Pow(Math.Sin(G.ToRadians()), 2)
            );

        string d = Math.Round(s, 2).ToString();

        Console.WriteLine($"The distance between 
            {p.Name} and {q.Name} is {d} km (+/- 50 m).");
        Console.ReadLine();
    }
}

The output produces the correct result:

The distance between Observatoire de Paris and U.S. Naval Observatory is 6181.63 km (+/- 50 m).

 

 

 

Astronomical Calculations: Sidereal Time

What is Sidereal Time?

The vernal equinox for 2020 was last week (as of this writing) and I had planned on posting this on that day. But there’s a global pandemic spreading through the world right now and, like so many others in North America, I was preoccupied with other things. In any case, in honor of the vernal equinox this post is going to talk about sidereal time. If you’re an amateur astronomer interested in the algorithm for local sidereal time then skip down to the next section. If you’re coming in cold then read on!

Continue reading “Astronomical Calculations: Sidereal Time”

Astronomical Calculations: Moons of Jupiter

Introduction

In this post I’m going to walk through an algorithm for calculating the positions of the four Galilean moons of Jupiter for any given moment in time. This method was developed by Jean Meeus and published in his book Astronomical Algorithms (Willmann-Bell, 2nd Ed., 1998).

All source code is checked into my GitHub repo. You can see the working software in action here: https://moonsofjupiter.azurewebsites.net. If you’re a raw beginner and want to know what you’ve just stumbled upon before diving into this post here are some good places to start:

(1) Ernie Wright provides an introduction with some cool animations that show what Galileo saw at the eyepiece and what he sketched in his own notebook.

(2) Dominic Ford has all kinds of astronomy goodness, including a nice looking corkscrew diagram for the four Galilean moons.

(3) I published an example web site  to  accompany this post. It would be a good idea to play around with it a bit before proceeding so you get an idea of what we’re trying to do.

Continue reading “Astronomical Calculations: Moons of Jupiter”

Astronomical Calculations: Delta T

Historically, Greenwich Mean Time (GMT) — solar noon at the Royal Observatory in Greenwich, England — was used as a universal reference point for trains and ships across the British empire. It is a timekeeping system based on the Earth’s rotation.  And it is a “mean” (average) because the exact moment the Sun crosses the Observatory’s meridian varies throughout the year. (This is a function of the Earth’s elliptical orbit and  angular velocity that I won’t go into here; see the equation of time for a full explanation.)

Eventually we needed something more  universal than a time standard kept in sync with one spot on Earth. Enter the atomic clock. An atomic clock can keep an exact 24 hours, day after day, century after century regardless of when the Sun crosses the meridian of any spot on Earth. Using cesium-133 atoms as a reference point, an atomic clock has an error deviation of about one second in 1.4 million years! We refer to this time as International Atomic Time (TAI).

We now have a solid, universal fixed-length period. Is that it? Can we now just use TAI for our civil time? No because the Earth and the natural forces that affect it are not precise. Things speed up and slow down due to tidal friction and other smaller perturbations. In a nutshell, the Earth cannot keep in sync with the precision of an atomic clock. It’s rotation is slowing down. It’s just like a toy top that a child spins up. The top spins very fast in the first few seconds and then over time loses its angular momentum and gradually spins slower. Our Earth is like a top that is slowing down. But not to worry. Long before it wobbles to a stop it will have been swallowed up by an expanding Sun!

So on the one hand we have a very precise TAI. And on the other hand we have an uncooperative Earth that is slowing down gradually over time. So in 1972, an international standards body introduced Coordinated Universal Time (UTC), a time standard like GMT that is still based on the Earth’s rotation, but with adjustments based on the precision of the underlying TAI.

The idea is to allow UTC to follow the irregularity of the Earth’s rotational period but also to adjust it at regular intervals according to TAI. These adjustments are made by an international committee charged with tracking this deviation. Twice a year they decide whether to add leap seconds to UTC. It’s all incredibly nerdy and I’m going to leave that right there. But as I write this on 1 Feb 2020, I took note of the time as it reached 16:39:00 TAI. At that exact moment it was also 16:38:23 UTC. So TAI is currently 37 seconds ahead of UTC. (This is because TAI was 10 seconds ahead of UTC when it was adopted in 1972 and there have been 27 leap seconds since then.)

That’s all well and good for civil time. But in astronomy, in order to calculate eclipses or transits you need to know the exact orbital positions of the Sun, Moon and planets at a given moment in time. So we need yet another time scale called Terrestrial Time (TT). This is another uniform time scale that works over long distances and long periods of time. Along with TT is a current baseline called the J2000.0 epoch. Both TT and the current epoch will come into play shortly.

Finally that brings me to Delta T. From the wiki:

In precise timekeeping, ΔT (Delta T, delta-T, deltaT, or DT) is a measure of the cumulative effect of the departure of the Earth’s rotation period from the fixed-length day of atomic time. Formally it is the time difference obtained by subtracting Universal Time (UT, defined by the Earth’s rotation) from Terrestrial Time (TT, independent of the Earth’s rotation): ΔT = TT − UT. The value of ΔT for the start of 1902 is approximately zero; for 2002 it is about 64 seconds. So the Earth’s rotations over that century took about 64 seconds longer than would be required for days of atomic time.

In his book Astronomical Algorithms, Meeus lists a general algorithm you can follow to calculate an approximate value of ΔT. Here we let t be the time (in centuries which is why we divide by 100) measured from the current J2000.0 epoch:

$$t = {year -2000 \over 100}$$

For years after 2000 Meeus introduces another calculation published in a paper in Paris written by Chapront, Chapront-Touzé & Francou (1997):

$$ΔT = 102 + 102 t + 25.3 t^2$$

I do not have access to their paper so I can’t explain the use of these “magic numbers” but you can see them in use on this Delta T calculator on a retro 90s-era (but awesome) web site maintained by Professor van Gent of the University of Utrecht.

Next we add the following correction for years between 2000 and 2100:

$$0.37 * (year – 2100)$$

That’s it. Let’s implement this algorithm for the year 2020. I’m using C# language syntax and Visual Studio Code as my editor:

class Program
{
    static void Main(string[] args)
    {
        var year = 2020;
        var t = (year - 2000) / 100;
        var deltaT = 102 + (102 * t) + (25.3 * Math.Pow(t, 2));
        var correction = 0.37 * (year - 2100);
        var correctedDeltaT = deltaT + correction;

        Console.WriteLine("Corrected DT for the year {0} is: {1}", 
            year, 
            correctedDeltaT);
    }
}

And my output is +72.4 seconds. (Delta T is always expressed in positive terms.) So at the start of 2020 the Earth’s rotation was roughly 72.4 seconds behind UTC.

Now you’ll recall in my discussion of TAI and UTC above that when TAI was at 16:39:00 UTC was at 16:38:23, a difference of 37 seconds. What’s the relationship here?  Well, TT is always 32.184 seconds ahead of TAI. Why 32.184 seconds? Just take my word for it. It involves an offset from the start of TAI that takes into account an earlier time standard. With that bit of hand-waving out of the way here are our relationships when TAI was at 16:39:00:

TT == 16:39:32.184
TAI == 16:39:00
UTC == 16:38:23

So TT is about 69 seconds ahead of UTC. But if ΔT = TT − UT results in 69 what about our algorithm above that produced 72.4? Remember the leap second additions? Every time a leap second is added to UTC the gap between TT and UTC widens. Three leap seconds were added since the J2000.0 epoch began (2005, 2008, and 2016). This is why our algorithm uses J2000.0 epoch as its baseline.

NASA has published another algorithm for deriving ΔT that is specific for years between 2005 and 2050. If I implement their algorithm into C# code we get this:

private static double ApproximateDeltaT(int year)
{
    var t = year - 2000;
    return 62.92 + 0.32217 * t + 0.005589 * t * t;
}

This functions returns 71.599. These are approximations so we mustn’t worry about why the  two algorithms don’t produce the exact same results. The point to all of this is to know exactly when in TT an event like the next solar eclipse will occur so that you can convert it to UTC in order to observe it!