How Odd Was the Full Moon on Halloween 2020? Once in a Blue Moon and a Lifetime!

November 4, 2020 — Vitaliy Kaurov, Academic Director, Wolfram Science and Innovation Initiatives

Halloween this year had a surprise up its sleeve. In rare celestial serendipity, the night of costume metamorphosis also featured a full moon, which helped to conjure the spooky mood. Because it might have been the first and last full-moon Halloween that some people witnessed in their lifetime (cue ominous music), I think it was significantly underrated. Moreover, it was the day of a blue moon (the second full moon within a month), but that is not a surprise, as any Halloween’s full moon is always a blue moon. The Moon’s color did not change, though, at least for those away from the smoke of volcanos and forest fires that are capable of turning it visibly blue. To appreciate the science and uniqueness of a full moon this Halloween, I built this visualization that tells the whole story in one picture. This is how I did it.

Let’s start by verifying that the Halloween 2020 Moon was indeed full. The recent Wolfram Function Repository contribution MoonPhaseDate computes the date of the next or previous full moon and confirms our assertion:

["Full",TimeDirection->-1]

TimeDirection -> –1 means we are looking into the past, as Halloween already happened. There is more going on under the hood, though. The Wolfram Language has automatically determined my time zone and its offset:

$TimeZone

This is the same offset as in New York City, and could be different in another location:

TimeZoneOffset/@{(Entity["New York City", Entity["City",{"NewYork","NewYork","UnitedStates"}], "Entity[\"City\", {\"NewYork\", \"NewYork\", \"UnitedStates\"}]", "city"]),(Entity["Sydney", Entity["City",{"Sydney","NewSouthWales","Australia"}], "Entity[\"City\", {\"Sydney\", \"NewSouthWales\", \"Australia\"}]", "city"])}

It might be surprising to see that in Sydney the full moon occurred not on Halloween, but a day later:

["Full",TimeZone->11,TimeDirection->-1]

To better understand this, we have to realize that while the news media may say that there will be a full moon on a particular date, its actual duration is just an instant when “the lunar hemisphere facing Earth... is completely sunlit and appears as a circular disk.” The exact event depends on observers’ locations on Earth, or less granularly, their time zones. This is why we see different dates and times for New York City and Sydney. Nevertheless, those who went out to celebrate Halloween at 8pm on October 31 in either city could witness the same full moon “phase”:

Values[MoonPhase[
{(DateObject["Sat 31 Oct 2020 20:00:00""GMT"-5, DateObject[{2020,10,31,20,0,0},"Instant","Gregorian",-5.`]]),(DateObject["Sat 31 Oct 2020 20:00:00""GMT+"11, DateObject[{2020,10,31,20,0,0},"Instant","Gregorian",11.`]])},"Name"]]

The named phases are discrete and separated by thresholds of illumination percentage, and a phase is still considered full even a bit earlier or later than the actual moment of a full moon. Moreover, the Moon still looks almost identically full to the naked eye during the either the next or previous day. It’s quite apparent from the Moon calendar for October 2020:

Grid[Partition[Labeled[#2,DateValue[#,"Day"]]&@@@MoonPhase[DateRange[(DateObject["Thu 1 Oct 2020", DateObject[{2020,10,1},"Day","Gregorian",-5.`]]),(DateObject["Sat 31 Oct 2020", DateObject[{2020,10,31},"Day","Gregorian",-5.`]])],"Icon"]["Path"],7,7,4,""],Frame->All]

So people celebrating Halloween around the world could still enjoy the spectacle of at least a very-close-to-fully-illuminated Moon independent of their location, and as far as all things spooky are concerned, that’s the only thing that matters. By the way, there is a neat way to get a realistic visual of Moon phases thanks to the PlanetaryMoon entity:

Manipulate[Show[moon,ViewPoint->Left,ViewAngle->Pi/6,Lighting->{{"Directional",White,ImageScaled[{Sin[t],0,Cos[t]}]}},Background->Black],{t,0,2 Pi},
Initialization:>(moon=(Entity["Moon", Entity["PlanetaryMoon","Moon"], "Entity[\"PlanetaryMoon\", \"Moon\"]", "planetary moon"])["TexturedSurface"])]

So how rare is a full moon on Halloween? Let’s take one thousand years spanning five hundred years in both the past and future. Astronomers often use JulianDate for calculations, which is a special continuous day count. For simplicity, we precomputed the Julian dates of all full moons in the chosen time period. They are stored in the form of Iconize in the attached notebook:

fullmoonJDs=;

To find all days on which full moons occur in at least one time zone, we need to form a band covering all time zones without gaps:

fullMoonDatesP14=FromJulianDate[#,TimeZone->14]&/@fullmoonJDs;
fullMmoonDatesP12=FromJulianDate[#,TimeZone->12]&/@fullmoonJDs;
fullMoonDatesM12=FromJulianDate[#,TimeZone->-12]&/@fullmoonJDs;

We should join these lists and remove all duplicates, preliminarily reducing all TimeObjects to the granularity of a day and removing time zone information with TimeZone -> None to simplify comparison of dates:

fullmoonDates=Union[DateObject[#,"Day",TimeZone->None]&/@Join[fullMoonDatesP14,fullMmoonDatesP12,fullMoonDatesM12]];

Because a single Julian date of a full moon can convert to different dates in different time zones, we obtained more standard calendar days than the original Julian dates:

Length/@{fullmoonJDs,fullmoonDates}

Using function DateSelect (which is new in the upcoming Version 12.2), it is easy to get only those full moons that happen on Halloween in at least one time zone:

alltimezones=DateSelect[fullmoonDates,#Month==10&&#Day==31&];
Length[alltimezones]

There are just 65 of those out of all 25,795 full-moon days within a span of one thousand years! The years when these rare events occur can be concisely summarized with a timeline:

TimelinePlot[AssociationThread[DateValue[#,"Year"]&/@
alltimezones->alltimezones],]

If one considers a specific location and time zone, these events become even more seldom. Let’s define a function that finds all full moon dates for a given TimeZoneOffset:

singleTimezone[offset_]:=DateSelect[DateObject[#,"Day",TimeZone->None]&/@(FromJulianDate[#,TimeZone->offset]&/@fullmoonJDs),#Month==10&&#Day==31&]

For instance, in New York City, we now have only 40 incidences of a full moon on Halloween and a big gap of 35 years in the past where no incidences happened:

TimelinePlot[AssociationThread[DateValue[#,"Year"]&/@#->#],]&@singleTimezone[TimeZoneOffset[(Entity["New York City", Entity["City",{"NewYork","NewYork","UnitedStates"}], "Entity[\"City\", {\"NewYork\", \"NewYork\", \"UnitedStates\"}]", "city"])]]

For Sydney’s time zone, there are even fewer: just 25 such events:

TimelinePlot[AssociationThread[DateValue[#,"Year"]&/@#->#],]&@singleTimezone[TimeZoneOffset[(Entity["Sydney", Entity["City",{"Sydney","NewSouthWales","Australia"}], "Entity[\"City\", {\"Sydney\", \"NewSouthWales\", \"Australia\"}]", "city"])]]

For someone born right after 1955 in New York City who had never traveled (at least not on Halloween), the 2020 full moon on Halloween was the first such event in their life, and the next one will happen in 2039. The time span between 1955 and 2039 is 84 years and is on the order of the average human lifespan:

It is probable for a considerable number of people born right after 1955 in New York City that they will never see a full moon on Halloween again: the one in 2020 may be the last as well as the first in their lives. This would especially be the case if they were to relocate to Sydney (or somewhere else with a similar time zone), where after 2020 the next event is even later—in 2058—making the needed lifespan to witness the second event about one hundred years.

To build the visualization shown at the beginning of the post, we first need to focus on a single time zone, say New York City’s, and zoom in from a one thousand–year span to a one hundred–year span (plus or minus 50 years from today). This helps avoid overcrowded plots while still including enough data to yield an informative visual:

fullmoonDatesNYC=DateObject[#,"Day",TimeZone->None]&/@(FromJulianDate[#,TimeZone->TimeZoneOffset[(Entity["New York City", Entity["City",{"NewYork","NewYork","UnitedStates"}], "Entity[\"City\", {\"NewYork\", \"NewYork\", \"UnitedStates\"}]", "city"])]]&/@fullmoonJDs);

I will separate the visualization into past and future parts placed one above the other. It is a good idea to use vertical space for a long time series. For each part (past and future), I will introduce four variables: all full-moon days, full moons that happen in October, full moons that happen on the 31st of a month and their intersections, which are the dates of each full-moon Halloween:

past=NumericalSort@DateSelect[fullmoonDatesNYC,1970<#Year<=2020&];
pastOCT=DateSelect[past,#Month==10&];
past31=DateSelect[past,#Day==31&];
pastOCT31=Intersection[pastOCT,past31]

The key detail is associating each full-moon date with its day number in the month. This will help us see the uneven but steady change of this date with the passage of time, only sometimes taking value 31 and even more rarely doing so in October. Let’s do this for the future part now:

future=NumericalSort@DateSelect[fullmoonDatesNYC,2020<#Year<2070&];
futureOCT=DateSelect[future,#Month==10&];
future31=DateSelect[future,#Day==31&];
futureOCT31=Intersection[futureOCT,future31]

To do a casual correctness check, one can easily verify that the intersection dates here are the same as shown on the timeline plot for New York City. We will also need special markers for the various datasets we have, which are quite easy to build:

markers=Graphics[{#,Thick,Circle[]},ImageSize->15]&/@{Darker@Green,Blue,Red}

Here is what each label represents, with a black dot being the default marker for every data point automatically generated by the plotting function (hence it does not need to be created beforehand):

- Halloween full moon 
  - Every full moon 
 - October full moon 
 - Full moon on the 31st or blue moon

Finally, we can get everything together in a single image that demonstrates visually the infrequency of a full moon on Halloween among all days, full-moon days, October full moons and blue moons. The thickness of the gray dashed lines covers approximately the duration of October every year. The red dashed line represents the 31st day of a month. For a full moon (black dot) to fall on Halloween, it needs to appear in the intersection of a gray and a red line (all such intersections representing Halloween every year):

DateListPlot[Tooltip/@Transpose[{#,DateValue[#,"Day"]}]&/@{past,pastOCT,past31,pastOCT31},]

After similarly building the future part, with a little work, everything can be combined into the final top image. I mentioned earlier that a Halloween Moon is always a blue moon (the second full moon within a month). That follows from the so-called synodic period of the Moon phase, which is shorter than the 31-day length of October:

This can also be clearly seen in the top visualization, as every red circle marking Halloween’s full moon also has a corresponding green circle below on the same gray line, which is the first full moon in that month of October. The same logic goes for all blue circles, except they are not Halloween’s but other months’ blue moons.

In old times, superstition often led people to believe that rare celestial events were bad omens. Halley’s comet was said to foretell the defeat of King Harold II by William the Conqueror in 1066. The June 17, 1135, eclipse precipitated civil war after the death of King Henry I. How great is it to live in an age of knowledge where comets do not dictate human affairs? Let’s celebrate that—and Halloween—with adventures in computational exploration and make the choice to interpret this oddity of celestial dynamics as a sign of things taking a turn for the better.

I would like to express special thanks to José Martín-García, Jeffrey Bryant, Nick Lariviere and Christopher Carlson, who have transformed my understanding of astronomy and been a kind, indispensable help.

Visit Wolfram Community or the Wolfram Function Repository to embark on your own computational adventures!