There is constantly a place on Earth where you would cast no shadow. Or more exactly, if you were a straight object like a traffic cone, you would not cast any visible shadow.
This happens when you right at the sub-solar point, meaning "right under the Sun". At this instant, the Sun is at the zenith, right above your head, 90° above the horizon.
This place on Earth constantly moves, act fast if you want to snap a strangely fascinating photo. But what exactly is happening?
First, let's have a quick astronomical recap.
Obliquity of the ecliptic
The Earth does its revolution around the Sun on a plane called the ecliptic. But as we know, the Earth also rotates on its axis in about 24 hours, along what we call the equatorial plane.
Our planet is tilted, meaning the ecliptic and equatorial planes are not the same. The angle between them is called the obliquity of the ecliptic. Its current value is 23.44° and it slightly changes over time (millennia), but this part will be for another day.
This tilt is what causes the seasons. As we go through the year, one hemisphere will have longer or shorter days.
But what does this have to do with having the Sun at zenith?
Sub-solar point
Because the Earth is round (if you don't agree, the rest of this article might be a bit less enjoyable) and tilted on its axis (that's the obliquity), we don't all receive the light rays with the same angle.
This also means there's always a place on Earth that receives the sun light perpendicularly to the surface. That's the sub-solar point!
Obviously this point doesn't stay there, let's not forget the Earth's rotation - it's always noon somewhere.
Now let's combine the two pieces of information we have: There is a place where the sunlight hits the surface perpendicularly, and this place changes constantly because of the Earth rotation and its revolution around the Sun.
Finding the exact spot: the theory
Now comes the fun part: finding that elusive spot.
To compute it, we need 2 pieces of information:
- the Sun's apparent declination
- the longitude of the meridian where the real solar noon happens
Lots of unfamiliar terms here, let's dig a little bit deeper and then we should be good with the theoretical stuff.
Declination
It's very similar as the geographic latitude, which is how North or South the location is compared to the equator. If you extended Earth's equator into space, it would trace the celestial equator. The declination is then how up or down the object is compared to the celestial equator.
Solar noon
Yes, there's a real noon... and a fake one. 😱
Actually, it's not fake, it's mean. Noon is commonly known as mid-day, when the Sun is at its highest in the sky. Mean noon is a standardised time that everyone in the same time zone agrees to use. Solar noon is when the Sun is at it's highest in the sky for a given observer, regardless of its legal time.
Actually finding the exact spot
Finally we can move to the practical part and actually compute the sub-solar point's coordinates.
We're using Astronoby, a library that enables to compute astronomical event and data in pure Ruby. It relies on ephemerides published by official administrations and institutes like NASA/JPL or the IMCCE.
The first action is to download one of these ephemerides, they are the fuel of the library. This needs to be done only once and then the file is stored locally, if you already used Astronoby it might not be necessary.
Astronoby::Ephem.download(
name: "inpop19a.bsp",
target: "tmp/inpop19a.bsp"
)
From there, the ephemeris can be loaded and used by Astronoby in any computation.
ephem = Astronoby::Ephem.load("tmp/inpop19a.bsp")
Then, we need to specify what time we want to know where the sub-solar point is. Astronoby abstracts time through a Instant
object.
time = Time.utc(2025, 6, 20)
instant = Astronoby::Instant.from_time(time)
Up to this point, we have everything we need to compute the Sun's apparent coordinates.
sun = Astronoby::Sun.new(ephem: ephem, instant: instant)
The sub-solar point's latitude is right there, described by th sun's apparent declination.
sub_solar_latitude = sun.apparent.equatorial.declination
The longitude is slightly more complicated as it is the difference between the apparent right ascension and the Greenwich sidereal time. We didn't explain these two new notions for simplicity's sake, and it might be confusing to compare and angle with a time, but astronomy allows that. Let's just say right ascension is the celestial equivalent of longitude, paired with declination it forms a full coordinate system for the sky. Sidereal time is a time scale that is based on the Earth's rate of rotation measured relative to the fixed stars.
The longitude is the difference between right ascension and sidereal time, normalised in a range between -180° and 180°.
right_ascension = sun.apparent.equatorial.right_ascension
sidereal_time = Astronoby::GreenwichSiderealTime
.from_utc(time.utc)
.time
longitude = right_ascension - Astronoby::Angle.from_hours(sidereal_time)
# Normalise to range [-180°, 180°]
sub_solar_longitude = Astronoby::Angle.from_degrees(
((longitude.degrees + 180) % 360 - 180)
)
That's it, we have our coordinates!
puts "At #{time}, the sub-solar point is at:"
puts " #{sub_solar_latitude.degrees.round(2)}°,#{sub_solar_longitude.degrees.round(2)}°"
# Output:
# At 2025-06-20 00:00:00 UTC, the sub-solar point is at:
# 23.43°,-179.62°
But wait, there's more!
You might be aware, but this post is supposedly published the day before June 21, 2025's June solstice. What's a solstice you may say? This is the moment in time where the Sun will reach it's highest or lowest (depending on the observer's hemisphere) altitude in the sky for the year.
The first thing, is that you can compute this instant easily with Astronoby.
Astronoby::EquinoxSolstice.june_solstice(2025, ephem)
# => 2025-06-21 02:42:19 UTC
Remember when we said at the beginning of this post that the Earth's tilt was 23.44°. Well, the second thing I want to show you is that with the beauty of geometry, we can compute this angle back by looking at the sub-solar point's coordinates during solstice!
time = Astronoby::EquinoxSolstice.june_solstice(2025, ephem)
instant = Astronoby::Instant.from_time(time)
# ... same instructions as before
# Output:
# At 2025-06-21 02:42:19 UTC, the sub-solar point is at:
# 23.44°,139.86°
This makes sense as solstices are moments where the Earth's tilt as the most effect on how we receive sunlight.
And guess what, we've actually named the extreme sub-solar latitudes 23.44° and -23.44° and you might have already heard them: Tropic of Cancer and Tropic of Capricorn.
Who would've guessed we could play with astronomy and geography, in Ruby? Now you can!
Check out on Astronoby for even more celestial wonders seen from Earth!
Credits:
Top comments (2)
Thanks @jance_jacobs , this is heartwarming!
A new blog article will come at some point this summer about when is the best moment to observe the Moon and the planets, stay tuned!
Great explanation! It's fascinating how the sub-solar point moves and how we can track it with Ruby. Thanks for making astronomy so accessible!