Astronomical Calculations in Emacs
April 25, 2020

night

Having just entered the month of Ramadan, I thought now would be a good time to share a library I’ve been working on to calculate the 5 prayer times from within Emacs; times which are all based off of the position of the sun. The package can be found at https://github.com/zkry/awqat. These times fluctuate based on the movements of the sun making calculating them quite complicated. Luckily however, Emacs provides a nice suite of functions to make such calculations reducing the work needed greatly. In this article I will go through the solar.el library explaining how the various calculations are made, and showing the library I made. But first let me explain quickly what the five daily prayers are.

The 5 Daily Prayers

To Muslims, the five daily prayers (or Salat ٱلصَّلَاة‎) is the second pillar of Islam. The prayers involve movements of the body as well as recitation of the Quran and last for about five to ten minutes. The times for the prayers is determined entirely by the position of the sun. The five prayers are as follows:

  • Fajr, the morning prayer: begins when some degree of light starts to enter the night sky, ends at the start of sunrise.
  • Dhuhr, the noon prayer: begins at solar noon, and ends at the start of the following prayer.
  • Asr, the afternoon prayer: begins when an objects shadow is a certain times longer than at solar noon, ends at Maghrib.
  • Maghrib: begins at sunset, ends at Isha.
  • Isha: starts when the light of the sun is gone after sunset, ends at Fajr.

solar.el

Emacs contains many astronomical calculation functions in relation to calculating months and sunrise/sunset. You can see these functions in action when opening up the calendar (M-x calendar, press S over a day). You can also see the lunar phase by pressing M over a day. Emacs being as extensible as it is, we will be relying heavily on the functions provided by solar.el.

All of the functions in solar.el work with dates represented as the list of month, day, then year. Times are represented as floating point numbers.

Sunrise and sunset (Fajr and Maghrib)

Normally Emacs already has the functions to calculate the sunrise and sunset. Normally we could just use these for the ending time of Fajr and starting time of Maghrib. The function in question is solar-sunrise-sunset from solar.el. By executing (find-function 'solar-sunrise-sunset) you can see this functions implementation. Notice the magic number -0.61. This corresponds to the angle that the center of the sun is below the horizon to be considered a sunset. When the sun is at 0 degrees, half of the sun is still visible in theory. For the sun to be counted as set in Islam, there should be no sight of the sun at all and thus an angle of -1.66 degrees is more appropriate. Since this wasn’t parameterized in the code, I had to copy this function with the changed number.

Solar noon (Dhuhr)

For the solar noon calculation we can use the function solar-exact-local-noon directly. So for example, by evaluating (solar-exact-local-noon '(4 25 2020)) I get ((4 25 2020) 11.06910885471896). This time corresponds with solar noon where I live but the time is off. It should be an hour later than the number returned. For this there is the function dst-adjust-time which adjusts the time appropriately. Executing (dst-adjust-time '(4 25 2020) (cadr (solar-exact-local-noon '(4 25 2020)))) then gives me ((4 25 2020) 12.066666665486991 "CEST"). This time will still need to be adjusted for daylight savings. This will need to be adjusted for the time zone, stored in calendar-time-zone.

The time of Asr

The calculation for Asr was the only one where I had to add a little extra calculations. There are two ways to calculate this time depending on the school of law.

  • The time when the length of an objects shadow is equal to the length of the object plus the length of the object’s shadow at solar noon. (Hanbali, Shafii, and Maliki schools of law)
  • The time when the length of an objects shadow is equal to twice the length of the object plus the length of the objects shadow at solar noon. (hanafi school of law)

Height of the sun at noon

The first step to calculating this is to get the length of an objects shadow at solar noon. To do this we can utilize the solar.el function solar-horizontal-coordinates. This function takes a time (I’ll get more into what this time is), latitude, longitude, and a flag and returns the coordinates of the sun defined by the sun’s azimuth and height at that time.

The azimuth (from Arabic اَلسُّمُوت as-sumūt, ‘the directions’) of a celestial object is defined as the angle you would have to rotate, starting from true north, to see the object in front of you. The height of the sun is the angle you would have to look up to see the object starting from the horizon. So for example, if the sun was right above your head and you had no shadow, it’s height would be 90 degrees. The azimuth of the sun in our case doesn’t matter as for all angles, you’re shadow is still the same length.

To use this function however we need to give it the “time”. This function takes a list of Julian centuries and a time as arguments. This is a duration of time with a standard length of duration past the Julian epoch (which is close to noon January 1, 2000 in the Gregorian calendar). Luckily for us there is the solar.el function solar-julian-ut-centuries which will give us this time.

(solar-julian-ut-centuries '(4 28 2020))
; => 0.20321697467488023

This value of 0.203 should make sense since the epoch is on Jan 1 and we are in the year 2020 and a measurement of centuries. Since a Julian year is not a measurement of dates, we can’t just take the time since Jan 1, 2020 to calculate this value.

With the time in solar Julian years, we can now call solar-horizontal-coordinates.

(defun height-of-sun-at-noon (date)
  "Calculates the height of at solar noon on DATE."
  (let* ((exact-local-noon (solar-exact-local-noon date))
         (t0 (solar-julian-ut-centuries (car exact-local-noon)))
         (ut (cadr exact-local-noon))

         (hnoon (solar-horizontal-coordinates (list t0 ut)
                                              (calendar-latitude)
                                              (calendar-longitude) t)))
    hnoon))

(height-of-sun-at-noon '(4 28 2020))
; => (359.997058543083 51.934185161558496)
; The first value is the azimuth, second height. This means that the sun is 51.9 degrees up in
; the sky on noon at Apr 4, 2020 in Berlin.

Length of a shadow at noon

Now it’s time to use a little trigonometry to find how large an objects shadow is at noon.

diagram-of-shadow

Assuming that the length of the object is 1, we can make the calculation as follows:

(defun deg-to-rad (x)
  "Convert X from radians to degrees."
  (/ (* x float-pi) 180))

(defun length-of-shadow-at-noon (date)
  "Calculates the relative length of an objects shadow at solar noon on DATE."
  (let ((hn (cadr (height-of-sun-at-noon date))))
    (/ 1 (tan (deg-to-rad hn)))))

Calculating the Asr time

We are now finally ready to calculate the time of Asr. The function above gets the length of an object at solar noon noon. We then calculate how much we expect the length to be at the time of Asr. So for example, if the length of an object is 1m, and the sun is positioned so that its shadow is 0.2m at noon, then we want to know the time when the shadow will be 1.2m or 2.2m depending on the school of law. Using some more trigonometry we can calculate the angle of the sun. Then using the function we used to find the sunrise/sunset at -1.66, we can also find the time when the sun is above a certain angle of the horizon.

diagram-of-shadow-with-asr

(defun time-asr (date)
  "Calculate the time of asr on DATE.
If `asr-hanafi' is non-nil, use double the length of noon shadow."
  (let* ((s (length-of-shadow-at-noon date))
         (l (+ (if asr-hanafi 2 1) s))
         (h (rad-to-deg (atan (/ 1 l)))))
    (cadr (sunrise-sunset-angle date h))))

Not above that sunrise-sunset-angle is the function solar-sunrise-sunset copied with the -0.61 constant parameterized.

Isha and Fajr

The time of Isha and Fajr is a little tricky. Typically it is defined as the time when the sun is below a certain angle of the horizon. Remember, zero degrees happens at sun set. As the number of degrees decreases the sky gets darker and darker. At around -15 degrees, thy sky is completely dark.

Unlike the calculations for Asr, there are many different ideas on what this angle should be. To make matters even more difficult, there are places in the summer where the sun never reaches a low enough angle. In these cases, angle base calculations are foregone completely and again a vast amount of variety appears. Some add a fixed amount of time (like 1.5 hours), others go based off of a closer city with a lower latitude, others divide the night into parts and assign a prayer to those divisions. To give you an idea of how difficult things can be to compute consider the following chart showing the calculated prayer times for Isha by the Directorate of Religious Affairs of Turkey.

diagram-of-shadow-with-asr

The orange line is the time after sunset when Isha prayer starts for Istanbul, the red for the city Izmir. The blue line are the posted times for Berlin and light-blue for Oslo. The waviness of the orange line is due to the natural movement of the sun. The blue line is flat for most of the year, meaning that the time for Isha in Berlin/Oslo is just the time of sunset plus 1.2 hours. But then you see a dip in the blue line during the longest days. This is likely due to a provision in the plus-1.2-hour-algorithm for days when the sunset is very late (21:33 on June 20th). Also notice that there is a cap on this dip at one hour. I don’t know how this works exactly.

All of this aside, we can calculate the time of Isha and Fajr fairly easy by using our custom sunrise-sunset-angle function (the parameterized version of the solar.el solar-sunrise-sunset). We can pass in -15.0 to this function as the angle and it will give us the time that the sun is in this position. If the sun never goes that low for the calendar lat-lon, then solar midnight will be returned.

Conclusion

This concludes the calculation of all of the prayer times. I put together an Emacs package with all of the functionality mentioned in this article: https://github.com/zkry/awqat. You can use it as an addition to any prayer calculation program you’re currently using. Please be warned though that there may easily be bugs in this software and the times computed may be incorrect. Generally Dhuhr, Asr, and Maghrib can be calculated fairly accurately but if you are living at a high latitude, you may have to fiddle with the program to get the desired results.

Also don’t forget to look at the sky. As fun as it is living inside Emacs, looking at the night sky has a profound effect on the human soul (someone even made a challenge out of this https://mayskychallenge.com/ ).