<p>Most formulas accept a Julian Day as input, but internally usually use the number of days (or years, or centuries) since Jan 1, 2000 12:00pm.  Take the function below, which accepts JD as input, but the first thing it does is compute n=jd-2451545.0, then uses n for the remainder of the calculations.  So it's an easy modification to just have it accept n as the parameter, and not use Julian Days at all in the calling program.</p>
<pre><code>    //Low precision sun position from Astronomical Almanac page C5 (2017 ed).
    //Accuracy 1deg from 1950-2050
    function sunPosition(jd)    {
        const torad=Math.PI/180.0;
        n=jd-2451545.0;
        L=(280.460+0.9856474*n)%360;
        g=((375.528+.9856003*n)%360)*torad;
        if(L&lt;0){L+=360;}
        if(g&lt;0){g+=Math.PI*2.0;}

        lamba=(L+1.915*Math.sin(g)+0.020*Math.sin(2*g))*torad;
        beta=0.0;
        eps=(23.439-0.0000004*n)*torad;
        ra=Math.atan2(Math.cos(eps)*Math.sin(lamba),Math.cos(lamba));
        dec=Math.asin(Math.sin(eps)*Math.sin(lamba));
        if(ra&lt;0){ra+=Math.PI*2;}
        return [ra/torad/15.0,dec/torad];
    }
</code></pre>
<p>Here is an example that uses this is function to <a href="https://www.celestialprogramming.com/risesetalgorithm.html" rel="nofollow noreferrer">compute the sun rise and set</a> for a given location.</p>
<p>The here is the <a href="https://www.celestialprogramming.com/risesetalgorithm.html" rel="nofollow noreferrer">Algorithm to solve for a give Altitude or Azimuth</a></p>

CC BY-SA 4.0
2022-06-04T08:39:23.350Z
Thanks! But the problem with this is that we still end up with e.g. for today 8189 as the Julian 2000 day. So with float precision on Arduino I think, we only have three digits left for the time fraction. This would result in a precision of almost 1,5 minutes … well, this is better than nothing. I'll try this out.
Tobias Leupold
CC BY-SA 4.0
2022-06-04T15:14:01.643Z
Arduino supports "double" types, just not on the Uno or Mega.  So you might also look into a different board if you can.
Greg Miller
CC BY-SA 4.0
2022-06-05T17:40:15.207Z
Of course, you can simply use a board that CAN calculate doubles. But the challenge is to do it with floats only ;-)
Tobias Leupold
CC BY-SA 4.0
2022-06-05T19:53:53.503Z
You should mention the language that code is written in. I guess it's JavaScript, and so it's using 64 bit double arithmetic.
PM 2Ring
CC BY-SA 4.0
2022-06-03T15:11:46.363Z
2022-06-03T16:50:07.430Z
2022-06-03T16:50:07.430Z
Greg Miller
<p>First, a direct answer to your question (as I understand it), and then a different suggestion.</p>
<p>The modulus you are looking for here that brings the Sun and Earth back to the same relative position (in a way that’s relevant for sunrise/sunset calculations rather than positions of stars) is simply a year.  More precisely, it is a <em><a href="https://en.wikipedia.org/wiki/Tropical_year" rel="nofollow noreferrer">tropical year</a></em>.   However, that definition doesn’t actually help you that much (at least if you want ~minute precision) because there are year-to-year variations of this of order 5 minutes or so due to the influence of the Moon and planets on Earth’s position.</p>
<p>That said, there is a pretty simple solution, using the code you already linked to.   That code calculates the Sun’s elevation for a given date and time.  To get the sunrise or sunset time, simply iterate over times in the day until you find the moment where the elevation is zero (though instead you probably want something -0.83 degrees, see explanation <a href="https://en.wikipedia.org/wiki/Sunrise#Angle" rel="nofollow noreferrer">here</a>).</p>
<p>Fewer than 12 iterations (0 to 12 hours) would get you the correct hour of sunrise, then &lt;60 iterations each to narrow in on the minute and second.  That might seem inefficient (and at some level it is) but it would happen in a tiny fraction of a second; you’re never going to notice the difference between that and some more efficient code you could spend a lot of time writing.</p>

CC BY-SA 4.0
2022-06-05T14:12:50.313Z
You don't have to iterate to find the 0 Alt point, it can be found directly: https://www.celestialprogramming.com/risesetalgorithm.html  .  Though some iteration will still be necessary, as you'll need to recompute the RA/Dec of the Sun at the rise/set times to get a more accurate result.
Greg Miller
CC BY-SA 4.0
2022-06-05T14:16:51.323Z
@GregMiller Agreed - it just depends on how much code the OP wants to rewrite to work around the float vs. double issue.  My suggestion is intended to make it possible to find the sunrise/set with the adequate-precision code already available, without having to work around precision issues in other code.
Eric Jensen
CC BY-SA 4.0
2022-06-05T17:39:03.667Z
Of course, I would like to find a way to calculate the moment in time for a given elevation using float precision only WITHOUT having to iterate around it … but this seems to be no trivial task …
Tobias Leupold
CC BY-SA 4.0
2022-06-05T20:00:05.997Z
@TobiasLeupold Using Greg's suggestion, you only need 2 or 3 iterations to get sunrise / sunset times, starting from the declination at (local) noon. That's using double arithmetic. Working with floats, you probably don't need to iterate at all, since your times have limited precision.
PM 2Ring
CC BY-SA 4.0
2022-06-05T20:02:03.940Z
Also, there's not much point in calculating sunrise / sunset times to better than 1 minute precision. The error due to variations in atmospheric refraction can easily be larger than that, depending on the weather.
PM 2Ring
CC BY-SA 4.0
2022-06-05T21:43:24.870Z
@Eric The tropical year can certainly be used to get the time in the next year when the Sun's RA & declination are repeated. But the time of day of that event will be ~5h48m later, due to the fractional part of the tropical year. So it takes a little more work to do the alt-azimuth calculations.
PM 2Ring
CC BY-SA 4.0
2022-06-05T13:57:19.520Z
2022-06-05T13:57:19.520Z
Eric Jensen
<p>There are quite some sources for astronomical calculation formulas, e.g. <a href="https://aa.quae.nl/en/reken/zonpositie.html" rel="nofollow noreferrer">Astronomy Answers: Position of the Sun</a>, which is e.g. used by KDE's <a href="https://invent.kde.org/plasma/plasma-workspace/-/blob/master/libcolorcorrect/suncalc.cpp" rel="nofollow noreferrer">Night Color</a> plugin to calculate the time of a sunset or sunrise (when the sun's elevation is equal to a given value).</p>
<p>I want to do such a calculation on an Arduino Uno board. The problem is that all those formulas depend on <code>double</code> precision calculations, because they take and return a Julian day with the time being the fraction part. The Arduino Uno only has <code>float</code> precision, so the interesting part, the fraction representing the time, is lost (the Julian day alone takes all the decimal places).</p>
<p>Apparently, it's possible to avoid this problem, e.g. Dr. David Brooks published code to do elevation and azimuth calculations using <code>float</code> precision only in <a href="https://instesre.org/ArduinoUnoSolarCalculations.pdf" rel="nofollow noreferrer">Arduino Uno solar calculations</a>. He splits the Julian day into an <code>integer</code> day part and a <code>float</code> time part.</p>
<p>However, those formulas only work for the current position of the sun at a given date, time and location, not vice versa. I'm interested in calculating the moment in time where the sun has e.g. a given elevation (a defined sunrise and sunset).</p>
<p>I thought that one approach to solve this could be to find the very first Julian day with the very same Earth-Sun constellation, where e.g. the sun had the same elevation at the same time. The day itself is not interesting, as I already know it – I only want to get the time. This way, the Julian day would be &lt;= 365, leaving at least four digits to the time fraction. This would lead to a precision of about 10 s, which would be more than sufficient for my use-case.</p>
<p>So: Is it possible to find the first Julian day with the same Earth-Sun constellation as a given date? Like some modulo operation for a Julian day?</p>
<p>Thanks for all help!</p>

CC BY-SA 4.0
2022-06-05T19:32:45.220Z
Arduino `float` is [IEEE-754 binary32](https://en.wikipedia.org/wiki/Single-precision_floating-point_format), which has a 24 bit significand.
PM 2Ring
CC BY-SA 4.0
2022-06-05T19:46:18.510Z
Using `float` for `T` (Julian centuries since 2000.1.1) currently gives a granularity of ~90 seconds. That is, if $T=0.22$ then the smallest time step that makes a difference to $T$ is around 90 seconds. I'll put a live demo program (in Python) in the next comment.
PM 2Ring
CC BY-SA 4.0
2022-06-05T19:47:32.560Z
[Granularity demo](https://sagecell.sagemath.org/?z=eJx1T0FqwzAQvOsVi3uxUjdxnTiUgqHQ0kNP_UERtgQGRxLS-uDfd7WxqENbX7yanZmduQMzOYXHBj7maVQWem1xDgugjijGi3cBwc4Xv4CKYL0QhrgdTftVKKLu46cOb2ohnLbl0_lU11IMakn4Kxmui-O5bVopxMtoUQfVoxi04UtlRBWwq_dNW0Ey7B5PdQVqRvc1-0Gh7t7VFLV8FkAfs1dTniXDPpBxWTBSVLDZJMvMp_GWTkBxvUrZ0iJZs-IAP-W2EqoGhgqQLB9A55OKg92TwwE2_ZkyjMYwhZgPV-Ztauc5tPMVFIlMr_TLoVIq9tj9sv4jVs6VapN090-TXD7Kbwjrm7M=&lang=python)
PM 2Ring
<algorithm><sunrise><sunset>
How to find the first Julian day with the same Earth-Sun constellation
Tobias Leupold
# How to find the first Julian day with the same Earth-Sun constellation

(Asked by: username_0 on 2022-06-03)

There are quite some sources for astronomical calculation formulas, e.g. [Astronomy Answers: Position of the Sun](https://aa.quae.nl/en/reken/zonpositie.html), which is e.g. used by KDE's [Night Color](https://invent.kde.org/plasma/plasma-workspace/-/blob/master/libcolorcorrect/suncalc.cpp) plugin to calculate the time of a sunset or sunrise (when the sun's elevation is equal to a given value).

I want to do such a calculation on an Arduino Uno board. The problem is that all those formulas depend on `double` precision calculations, because they take and return a Julian day with the time being the fraction part. The Arduino Uno only has `float` precision, so the interesting part, the fraction representing the time, is lost (the Julian day alone takes all the decimal places).

Apparently, it's possible to avoid this problem, e.g. Dr. David Brooks published code to do elevation and azimuth calculations using `float` precision only in [Arduino Uno solar calculations](https://instesre.org/ArduinoUnoSolarCalculations.pdf). He splits the Julian day into an `integer` day part and a `float` time part.

However, those formulas only work for the current position of the sun at a given date, time and location, not vice versa. I'm interested in calculating the moment in time where the sun has e.g. a given elevation (a defined sunrise and sunset).

I thought that one approach to solve this could be to find the very first Julian day with the very same Earth-Sun constellation, where e.g. the sun had the same elevation at the same time. The day itself is not interesting, as I already know it – I only want to get the time. This way, the Julian day would be <= 365, leaving at least four digits to the time fraction. This would lead to a precision of about 10 s, which would be more than sufficient for my use-case.

So: Is it possible to find the first Julian day with the same Earth-Sun constellation as a given date? Like some modulo operation for a Julian day?

Thanks for all help!

**Tags:** algorithm, sunrise, sunset

> **Comments:**
> **username_1**: Arduino `float` is [IEEE-754 binary32](https://en.wikipedia.org/wiki/Single-precision_floating-point_format), which has a 24 bit significand.  
> **username_1**: Using `float` for `T` (Julian centuries since 2000.1.1) currently gives a granularity of ~90 seconds. That is, if $T=0.22$ then the smallest time step that makes a difference to $T$ is around 90 seconds. I'll put a live demo program (in Python) in the next comment.  
> **username_1**: [Granularity demo](https://sagecell.sagemath.org/?z=eJx1T0FqwzAQvOsVi3uxUjdxnTiUgqHQ0kNP_UERtgQGRxLS-uDfd7WxqENbX7yanZmduQMzOYXHBj7maVQWem1xDgugjijGi3cBwc4Xv4CKYL0QhrgdTftVKKLu46cOb2ohnLbl0_lU11IMakn4Kxmui-O5bVopxMtoUQfVoxi04UtlRBWwq_dNW0Ey7B5PdQVqRvc1-0Gh7t7VFLV8FkAfs1dTniXDPpBxWTBSVLDZJMvMp_GWTkBxvUrZ0iJZs-IAP-W2EqoGhgqQLB9A55OKg92TwwE2_ZkyjMYwhZgPV-Ztauc5tPMVFIlMr_TLoVIq9tj9sv4jVs6VapN090-TXD7Kbwjrm7M=&lang=python)  

---

## 2 answers

### Answer by username_2 on 2022-06-03. Score: 4

Most formulas accept a Julian Day as input, but internally usually use the number of days (or years, or centuries) since Jan 1, 2000 12:00pm. Take the function below, which accepts JD as input, but the first thing it does is compute n=jd-2451545.0, then uses n for the remainder of the calculations. So it's an easy modification to just have it accept n as the parameter, and not use Julian Days at all in the calling program.

```
    //Low precision sun position from Astronomical Almanac page C5 (2017 ed).
    //Accuracy 1deg from 1950-2050
    function sunPosition(jd)    {
        const torad=Math.PI/180.0;
        n=jd-2451545.0;
        L=(280.460+0.9856474*n)%360;
        g=((375.528+.9856003*n)%360)*torad;
        if(L<0){L+=360;}
        if(g<0){g+=Math.PI*2.0;}

        lamba=(L+1.915*Math.sin(g)+0.020*Math.sin(2*g))*torad;
        beta=0.0;
        eps=(23.439-0.0000004*n)*torad;
        ra=Math.atan2(Math.cos(eps)*Math.sin(lamba),Math.cos(lamba));
        dec=Math.asin(Math.sin(eps)*Math.sin(lamba));
        if(ra<0){ra+=Math.PI*2;}
        return [ra/torad/15.0,dec/torad];
    }

```

Here is an example that uses this is function to [compute the sun rise and set](https://www.celestialprogramming.com/risesetalgorithm.html) for a given location.

The here is the [Algorithm to solve for a give Altitude or Azimuth](https://www.celestialprogramming.com/risesetalgorithm.html)

> **Comments:**
> **username_0**: Thanks! But the problem with this is that we still end up with e.g. for today 8189 as the Julian 2000 day. So with float precision on Arduino I think, we only have three digits left for the time fraction. This would result in a precision of almost 1,5 minutes … well, this is better than nothing. I'll try this out.  
> **username_2**: Arduino supports "double" types, just not on the Uno or Mega.  So you might also look into a different board if you can.  
> **username_0**: Of course, you can simply use a board that CAN calculate doubles. But the challenge is to do it with floats only ;-)  
> **username_1**: You should mention the language that code is written in. I guess it's JavaScript, and so it's using 64 bit double arithmetic.  

---

### Answer by username_3 on 2022-06-05. Score: 1

First, a direct answer to your question (as I understand it), and then a different suggestion.

The modulus you are looking for here that brings the Sun and Earth back to the same relative position (in a way that’s relevant for sunrise/sunset calculations rather than positions of stars) is simply a year. More precisely, it is a *[tropical year](https://en.wikipedia.org/wiki/Tropical_year)*. However, that definition doesn’t actually help you that much (at least if you want ~minute precision) because there are year-to-year variations of this of order 5 minutes or so due to the influence of the Moon and planets on Earth’s position.

That said, there is a pretty simple solution, using the code you already linked to. That code calculates the Sun’s elevation for a given date and time. To get the sunrise or sunset time, simply iterate over times in the day until you find the moment where the elevation is zero (though instead you probably want something -0.83 degrees, see explanation [here](https://en.wikipedia.org/wiki/Sunrise#Angle)).

Fewer than 12 iterations (0 to 12 hours) would get you the correct hour of sunrise, then <60 iterations each to narrow in on the minute and second. That might seem inefficient (and at some level it is) but it would happen in a tiny fraction of a second; you’re never going to notice the difference between that and some more efficient code you could spend a lot of time writing.

> **Comments:**
> **username_2**: You don't have to iterate to find the 0 Alt point, it can be found directly: https://www.celestialprogramming.com/risesetalgorithm.html  .  Though some iteration will still be necessary, as you'll need to recompute the RA/Dec of the Sun at the rise/set times to get a more accurate result.  
> **username_3**: @username_2 Agreed - it just depends on how much code the OP wants to rewrite to work around the float vs. double issue.  My suggestion is intended to make it possible to find the sunrise/set with the adequate-precision code already available, without having to work around precision issues in other code.  
> **username_0**: Of course, I would like to find a way to calculate the moment in time for a given elevation using float precision only WITHOUT having to iterate around it … but this seems to be no trivial task …  
> **username_1**: @username_0 Using username_2's suggestion, you only need 2 or 3 iterations to get sunrise / sunset times, starting from the declination at (local) noon. That's using double arithmetic. Working with floats, you probably don't need to iterate at all, since your times have limited precision.  
> **username_1**: Also, there's not much point in calculating sunrise / sunset times to better than 1 minute precision. The error due to variations in atmospheric refraction can easily be larger than that, depending on the weather.  
> **username_1**: @username_3 The tropical year can certainly be used to get the time in the next year when the Sun's RA & declination are repeated. But the time of day of that event will be ~5h48m later, due to the fractional part of the tropical year. So it takes a little more work to do the alt-azimuth calculations.  

---

