Friday, August 6, 2010

Prayer Times Calculations: Pure C++ Code

[25-March-2017] Update: For brothers and sisters in Indonesia or any country below the equator, thanks to Reza's comment,  the code now works correctly.
[18-January-2012 Update: I refined the code to make it easier and more elegant to use]
[06-July-2011 Update: I found this page http://praytimes.org/calculation#Implementation ]

This idea came to me when a friend of mine was asking for an 'offline database' for prayer times. I searched for algorithms to make my own database and almost all search results lead to the same algorithm. And all codes are divided into two categories: a simple but approximate one, and a complicated but precise one. I tried with the complicated one to understand it but it needs more time because of its nested functions and -unfortunately- it is not a priority right now. So I went with the easy one as a start.

One thing I noticed is that every person is trying to make the ultimate use of the framework he is working on (mostly dotNet). But come on, it is all about calculations. Why don't you make a code that can be easily converted from one language/platform to another? That's why I wanted to make that code. It has a major problem till now as it produces times later than my Egyptian calendar up to 5 minutes !!! Only later not earlier.


Anyways, here is the code, and I hope I can reach better results in the near future (in-sha'a Allah).


 The parameters needed are:
  • Year/Month/Day of the desired day.
  • Longitude/Latitude/Time Zone of the desired place.
  • Fajr Twilight/ Esha Twilight which differ in calculations from one country to another.


Organization
Angle of the sun under the Horizon (Fajr)
Angle of the sun under the Horizon (Isha)
Region
University Of Islamic Sciences, Karachi
18 Degrees
18 Degrees
Pakistan, Bangladesh,
India, Afghanistan, Parts of Europe
North America
15 Degrees
15 Degrees
Parts of the USA, Canada, Parts of the UK
Muslim World League
18 Degrees
17 Degrees
Europe, The Far East, Parts of the USA
Umm Al-Qura Committee
19 Degrees
90 minutes after the Sunset Prayer
120 minutes (in Ramadan only)
The Arabian Peninsula
Egyptian General Authority of Survey
19.5 Degrees
17.5 Degrees
Africa, Syria, Iraq, Lebanon, Malaysia, Parts of the USA


The only library used in this function was
#include <math.h>
to use the trigonometric functions (sin, cos,...)


The function takes the data of Year/Month/Day/Longitude/Latitude/TimeZone/FajrTwilight/IshaTwilight plus 6 references to double variables (Fajr/SunRise/Zuhr/Asr/Maghrib/Isha). These 6 variables are the ones to return data into. I also added some supporting functions to help in some number conversions (for example, Radians to Degrees and vise versa).

//convert Degree to Radian
double degToRad(double degree)
{
    return ((3.1415926 / 180) * degree);
}

//convert Radian to Degree
double radToDeg(double radian)
{
    return (radian * (180/3.1415926));
}

//make sure a value is between 0 and 360
double moreLess360(double value)
{
    while(value > 360 || value < 0)
    {
        if(value > 360)
            value -= 360;

        else if (value <0)
            value += 360;
    }

    return value;
}

//make sure a value is between 0 and 24
double moreLess24(double value)
{
    while(value > 24 || value < 0)
    {
        if(value > 24)
            value -= 24;

        else if (value <0)
            value += 24;
    }

    return value;
}

//convert the double number to Hours and Minutes
void doubleToHrMin(double number, int &hours, int &minutes)
{
    hours = floor(moreLess24(number));
    minutes = floor(moreLess24(number - hours) * 60);
}

void calcPrayerTimes(int year, int month, int day,
                     double longitude, double latitude, int timeZone,
                     double fajrTwilight, double ishaTwilight,
                     double &fajrTime, double &sunRiseTime, double &zuhrTime,
                     double &asrTime, double &maghribTime, double &ishaTime)
{
    double D = (367 * year) - ((year + (int)((month + 9) / 12)) * 7 / 4) + (((int)(275 * month / 9)) + day - 730531.5);

    double L = 280.461 + 0.9856474 * D;
    L = moreLess360(L);

    double M = 357.528 + (0.9856003) * D;
    M = moreLess360(M);

    double Lambda = L + 1.915 * sin(degToRad(M)) + 0.02 * sin(degToRad(2 * M));
    Lambda = moreLess360(Lambda);

    double Obliquity = 23.439 - 0.0000004 * D;
    double Alpha = radToDeg(atan((cos(degToRad(Obliquity)) * tan(degToRad(Lambda)))));
    Alpha = moreLess360(Alpha);

    Alpha = Alpha - (360 * (int)(Alpha / 360));
    Alpha = Alpha + 90 * (floor(Lambda / 90) - floor(Alpha / 90));

    double ST = 100.46 + 0.985647352 * D;
    double Dec = radToDeg(asin(sin(degToRad(Obliquity)) * sin(degToRad(Lambda))));
    double Durinal_Arc = radToDeg(acos((sin(degToRad(-0.8333)) - sin(degToRad(Dec)) * sin(degToRad(latitude))) / (cos(degToRad(Dec)) * cos(degToRad(latitude)))));

    double Noon = Alpha - ST;
    Noon = moreLess360(Noon);


    double UT_Noon = Noon - longitude;


    ////////////////////////////////////////////
    // Calculating Prayer Times Arcs & Times //
    //////////////////////////////////////////

    // 2) Zuhr Time [Local noon]
    zuhrTime = UT_Noon / 15 + timeZone;

    // Asr Hanafi
    //double Asr_Alt =radToDeg(atan(2 + tan(degToRad(abs(latitude - Dec)))));

    // Asr Shafii
    double Asr_Alt = radToDeg(atan(1 + tan(degToRad(abs(latitude - Dec)))));
    double Asr_Arc = radToDeg(acos((sin(degToRad(90 - Asr_Alt)) - sin(degToRad(Dec)) * sin(degToRad(latitude))) / (cos(degToRad(Dec)) * cos(degToRad(latitude)))));
    Asr_Arc = Asr_Arc / 15;
    // 3) Asr Time
    asrTime = zuhrTime + Asr_Arc;

    // 1) Shorouq Time
    sunRiseTime = zuhrTime - (Durinal_Arc / 15);

    // 4) Maghrib Time
    maghribTime = zuhrTime + (Durinal_Arc / 15);


    double Esha_Arc = radToDeg(acos((sin(degToRad(ishaTwilight)) - sin(degToRad(Dec)) * sin(degToRad(latitude))) / (cos(degToRad(Dec)) * cos(degToRad(latitude)))));
    // 5) Isha Time
    ishaTime = zuhrTime + (Esha_Arc / 15);

    // 0) Fajr Time
    double Fajr_Arc = radToDeg(acos((sin(degToRad(fajrTwilight)) - sin(degToRad(Dec)) * sin(degToRad(latitude))) / (cos(degToRad(Dec)) * cos(degToRad(latitude)))));
    fajrTime = zuhrTime - (Fajr_Arc / 15);

    return;
}



So, if I take Cairo as an example:
  • Date: 18-1-2012
  • Longitude: 30.2
  • Latitude: 30
  • Time Zone: +2 
  • Fajr Twilight: -19.5
  • Esha Twilight: -17.5
the function will be used like this:
double fajr, sunRise, zuhr, asr, maghrib, isha;
calcPrayerTimes(2012,1,18, 30.2, 30, 2, -19.5, -17.5, fajr, sunRise, zuhr, asr, maghrib, isha);

Note that these prayer times are still "double" and should be converted to a time format. I made the doubleToHrMin function (you can find it before the calcPrayerTimes fnction) which splits the number into Hours and Minutes. It takes the double and two references to int variables. Here is how to use it:

int hours, minutes;
doubleToHrMin(fajr, hours, minutes);

Now you have the prayer time as Hour/Minute to use it however you want.

So, in brief:
- I first add the above code block to my code, then use it whenever I want like this example:

double fajr, sunRise, zuhr, asr, maghrib, isha;
calcPrayerTimes(2012,1,18, 30.2, 30, 2, -19.5, -17.5,
                fajr, sunRise, zuhr, asr, maghrib, isha);

int hours, minutes;

doubleToHrMin(fajr, hours, minutes);
std::cout << "Fajr: " << hours << ":" << minutes << std::endl;

doubleToHrMin(sunRise, hours, minutes);
std::cout << "Sunrise: " << hours << ":" << minutes << std::endl;

doubleToHrMin(zuhr, hours, minutes);
std::cout << "Zuhr: " << hours << ":" << minutes << std::endl;

doubleToHrMin(asr, hours, minutes);
std::cout << "Asr: " << hours << ":" << minutes << std::endl;

doubleToHrMin(maghrib, hours, minutes);
std::cout << "Maghrib: " << hours << ":" << minutes << std::endl;

doubleToHrMin(isha, hours, minutes);
std::cout << "Isha: " << hours << ":" << minutes << std::endl;


(view the full prayer times example in this online IDE)

I hope it is useful to someone looking for the pure algorithm with no framework dependencies, and I hope I come back to it one more time to see the problem of these extra resulting minutes.


Resources:

جمعية الفلك بالقطيف
Muslim Programmers & Designers Community
Tanzil.info (1),(2)
PrayTime.info
IslamCity.com
IslamWare.com

69 comments:

  1. jazaka allaho khayran

    ReplyDelete
    Replies
    1. Can someone please help me on how to do this code on codeblock and run to compile please as i am trying keep failing ,, Jazakallah khair

      Delete
    2. Hi.
      I'm terribly sorry for the very late reply. Here is the same code in a complete example in an online C++ editor: https://ideone.com/sqNLrg

      Delete
  2. can you please put all this together? i mean i'm a little confused about how to arrange all this code (i'm still a beginner at programming)

    ReplyDelete
    Replies
    1. You are totally right, I made it in a hurry so it is somehow confusing. I promise to edit this entry and make it much more easier. It will be finished by this weekend in-sha'a Allah.

      Delete
    2. I made some changes plus a code example. I guess it is now more friendly. :)

      Delete
  3. Assalamualaikum, from Malaysia here. we're a building a halal database, still under development & testing phase. I humbly request your permission to use your code as a reference to implement prayertime query to our website @ www.ishalal.com, by time we go live i'll credit you properly. Thsnk you.

    ReplyDelete
    Replies
    1. و عليكم السلام و رحمة الله و بركاته
      Please do. And good luck with your project.

      Delete
    2. Thank you Mr. Mahmoud, here is a semi-direct translation of your code in Go-lang, but the result is not correct and i'm not familiar with algorithm in used. It would be great to hear your advice on this.

      https://gist.github.com/2917151

      Delete
  4. Assalamualaikum, Mahmoud bhai can you tell me the formula to get midnight that applies on this algorith to this algorith plz i am in realy need of this.looking forward to your possitive response.thankyou

    ReplyDelete
    Replies
    1. Well, I don't understand the question. Isn't midnight always at 12:00am (or 00:00)?

      Delete
  5. midnight means ending time of isha namaz.it is different according to different mathhabs i.e(hanafi,shafi,hanbli,jafri....).calculation formulas are given in this link(http://praytimes.org/calculation#Implementation )for example according to shafi isha ends at(sunrise-sunset)/2.but when i aplly this formula to your code i gets wrong answer.scince you have shortened the algorithm.can you tell how this formula apply to your algo..plz help me out.thanxz alot

    ReplyDelete
    Replies
    1. If this is the case, then sunrise is "sunRiseTime" in the code and sunset is "maghribTime" in the code.
      So it would be (sunRiseTime-maghribTime)/2 then use doubleToHrMin to get the time in Hour and Minute.

      Delete
  6. but applying this formula i am not getting the correct result.

    ReplyDelete
  7. Replies
    1. these formulas are wrong, i have to calculate asr shaafi and hanafi and my sir had given me this formula whch i hav converted in c++ format, still its giving wrong calcution, need ur help asap.. the values in constructor are of lahore pakistan

      class Asar_Hanafi:public Maghrib
      {
      public:
      Asar_Hanafi(double l, double lt, double t, double la, double d):Maghrib(l,lt,t,la,d)
      {
      localtime= lt;
      longitude=l;
      twilight=t;
      lattitude=la;
      declination=d;
      }
      double getA()
      {
      double a,b,c,d;
      b=lattitude-declination;
      c=(2+tan(b*PI/180));
      d=atan(c)*PI/180;
      cout<<d<<endl;
      return d;
      }
      double getA_HH(double d)
      {
      double l, b, A_HH,c,f,e;
      l=sin(d*(PI/180));
      b=(sin(lattitude*PI/180)*sin(declination*PI/180));
      e=(l-b);
      c=(cos(lattitude*PI/180)*cos(declination*PI/180));
      f=e/c;
      A_HH=acos(d)*180.0/PI;
      return A_HH;
      }
      double getZA_H()
      {
      double a, b, c, d;
      a=((longitude-localtime)/15);
      b= -3.7/60;
      c= 12+a+b;
      return c;
      }

      void getA_H(double A_HH, double c)
      {
      double l,m,q;
      l=A_HH/15;
      m=c+l;
      double t= int(m);
      double w=((m-t)*60);
      q=int (w);
      cout<<t<<"hour"<<q<<"min"<<endl;

      }
      };
      class Asar_Shafi:public Maghrib
      {
      public:
      Asar_Shafi(double l, double lt, double t, double la, double d):Maghrib(l,lt,t,la,d)
      {
      localtime= lt;
      longitude=l;
      twilight=t;
      lattitude=la;
      declination=d;
      }
      double getA()
      {
      double a,b,c,d;
      b=lattitude-declination;
      c=(1+tan(b*PI/180));
      cout<<c<<endl;
      // in d cot inverse should be taken bt ye prob krha hai, and same prob arhi hai asr SHAFI mein bhi..

      d=atan(c)*PI/180;
      //cout<<a<<endl;
      return d;
      }
      double getA_SH(double d)
      {
      double l, b, A_HH,c,f,e;
      l=sin(d*(PI/180));
      b=(sin(lattitude*PI/180)*sin(declination*PI/180));
      e=(l-b);
      c=(cos(lattitude*PI/180)*cos(declination*PI/180));
      f=e/c;
      A_HH=acos(d)*180.0/PI;
      return A_HH;
      }
      double getZA_S()
      {
      double a, b, c, d;
      a=((longitude-localtime)/15);
      b= -3.7/60;
      c= 12+a+b;
      return c;
      }

      void getA_S(double A_HH, double c)
      {
      double l,m,q;
      l=A_HH/15;
      m=c+l;
      double t= int(m);
      double w=((m-t)*60);
      q=int (w);
      cout<<t<<"hour"<<q<<"min"<<endl;

      }

      Delete
  8. Salam Bro,
    Would you be able to kindly explain how to get
    Fajr Twilight:
    Esha Twilight:

    I searched in google and could not find anything.

    ReplyDelete
    Replies
    1. I did not calculate them, but got them as constants. I searched for values for my city: Cairo.

      Delete
  9. Salam brother Mahmoud, thank you very much for the code. The code run as-is on Arduino sketch.

    ReplyDelete
    Replies
    1. Wa Alaykom Alsalam,
      Glad to hear that. C++ is great (actually, C is greater) :D

      Delete
  10. Assalamualaikum brother Mahmoud..I am a beginner in C programming language.I need your help. How to add the Imsyak time that is 10 minutes before fajr time in the listing program above?

    ReplyDelete
    Replies
    1. Waalaykom Assalam,
      You can subtract hours from the return values before converting them to hourMinute. So in case of minutes, you subtract a fraction of an hour. Like this (note the .0 to make sure a float is returned):
      imsaak = fajr - (10/60.0);
      then do the conversion like this:
      int hours, minutes;
      doubleToHrMin(imsaak, hours, minutes);

      Delete
    2. I 've added the imsyak time to the list of program..it's working!
      Thank you very..very..very much my brother..wassalam.

      Delete
  11. Assalamualaikum , thanks for your explanation about prayer times calculation. i use your calculation for my project and its work great. its working.
    I use microcontroller and two different display to display prayer time. ther first i use seven segment and then i try to use LCD display with mp3 player to play adzan automaticaly. thank you very much.

    ReplyDelete
    Replies
    1. Walaykom Assalam,
      Thank you so much for your comment. It encourages me to keep sharing to see beautiful output like yours.

      Delete
    2. Can you pls send me your email Duwi Arsana

      Delete
  12. Assalamu alaykum brother Mahmoud,

    Thank you for the code, i can run it smoothly. For Fajr, Sunrise, Zuhr, Maghrib and Isya the time later around 1-4 minutes than standard prayer time. But for Asr the result different from standard prayer time. In my place in Jakarta, Asr should be on 15:13 but the result from above code 13:33.

    Could you mind give clue, why that happen and what correction should i implemented in code.

    Jazaka Allaho khayran

    ReplyDelete
    Replies
    1. Walaykom Assalam,

      How about trying to change the last two numbers in the function call (fajrTwilight and ishaTwilight)?
      I gave a table of some organizations and their used degrees. So maybe you can look for the approved organization in Pakistan (the first row in the table I gave has Pakistan) and try with it.

      Jazaka Allahu khayran brother.

      Delete
  13. جزاك الله عنا وعن الامة خيرا

    ReplyDelete
  14. Assalamu'alaikum,

    Brother, you really did a good job with this algortithm; I myself have no idea how to get all the formulas. I managed to port it to C#; works like a charm -- especially with the Egyptian calculation one. For sure I will put you in credit when I use this algorithm in my project.

    Keep sharing good things, bro.. and jazaakallaahu khairan..

    ReplyDelete
    Replies
    1. I'm glad I could help. Thank you for your comment.

      Delete
  15. Assalamu'alaiku akhii.
    It is great tutorial. Thanks for your explaination about prayer times calculation.

    I use your calculation with C Code blocks and I found trouble with ashar time. My location is 112.217E, 7.533S (-7.533) East Java Indonesia.

    I use your calculation for my project to with AVR

    thanks a lot

    ReplyDelete
    Replies
    1. وعليكم السلام ورحمة الله وبركاته
      So the Isha prayer time is not exactly as it should be for your location?

      Delete
    2. isya' time is ok but ashar time is not exactly

      Delete
    3. I don't know what to say. I used already-written mathematical equations to write this code, but I don't know much about changing the equation itself.

      Delete
    4. I have ported this to C# and Java; both give correct result. Of course you can't compare down to minutes with your local adzan call. Maybe try with different twilight/angle.

      Delete
  16. Gooooood jobb
    thank you for your program, in Algeria constants:
    Fajr Twilight: -19.5
    Esha Twilight: -17.5
    remain unchanged as cairo?

    ReplyDelete
    Replies
    1. Hello Far Zeha,

      I'm glad I could help :)
      The angles depend on the organization you follow in your country for prayer calculations. I use "Egyptian General Authority of Survey" values for Cairo and "Muslim World League" values for Berlin.

      Delete
  17. thank you for the answer.
    I have another question:
    I want to add a constant offset after calculating time of prayer.
    how to do it ?
    example:
    Fajr: 5:24 + 10 ==> 5:34

    ReplyDelete
    Replies
    1. You can add/subtract hours from the return values before converting them to hourMinute. So in case of minutes, you add a fraction of an hour. Like this (note the .0 to make sure a float is returned):
      new_fajr = fajr + (10/60.0);
      then do the conversion like this:
      int hours, minutes;
      doubleToHrMin(new_fajr, hours, minutes);

      Delete
  18. شكرا جزيلا و جزاك الله كل خير

    ReplyDelete
  19. i try to use the calculation into my arduino, but i have problem with this code
    int main() {
    double fajr, sunRise, zuhr, asr, maghrib, isha;
    calcPrayerTimes(2012,1,18, 30.2, 30, 2, -19.5, -17.5,
    fajr, sunRise, zuhr, asr, maghrib, isha);

    int hours, minutes;

    doubleToHrMin(fajr, hours, minutes);
    std::cout << "Fajr: " << hours << ":" << minutes << std::endl;

    doubleToHrMin(sunRise, hours, minutes);
    std::cout << "Sunrise: " << hours << ":" << minutes << std::endl;

    doubleToHrMin(zuhr, hours, minutes);
    std::cout << "Zuhr: " << hours << ":" << minutes << std::endl;

    doubleToHrMin(asr, hours, minutes);
    std::cout << "Asr: " << hours << ":" << minutes << std::endl;

    doubleToHrMin(maghrib, hours, minutes);
    std::cout << "Maghrib: " << hours << ":" << minutes << std::endl;

    doubleToHrMin(isha, hours, minutes);
    std::cout << "Isha: " << hours << ":" << minutes << std::endl;
    }

    need help

    ReplyDelete
    Replies
    1. "std::cout << "Maghrib: " << hours << ":" << minutes << std::endl;" will not run in arduino.
      replace these from.....
      doubleToHrMin(fajr, hours, minutes);
      Serial.print("Fajr ");
      Serial.print(hours);
      Serial.print(":");
      Serial.println(minutes);

      Delete
  20. could you plz send me your email Mahmoud Adly Ezzat

    ReplyDelete
  21. السلام علیکم
    i just wanted to know if you give us permisson to use your code !
    we want to make clock for masque

    ReplyDelete
    Replies
    1. وعليكم السلام ورحمة الله وبركاته
      Yes, sure! Go ahead.

      Delete
    2. thanks
      i saw something in your code that i cant figure out !
      you used "int timeZone" so what will happen in case that timezone is 3.5 it will saved to int timezone as 3 ! is it correct ?

      Delete
    3. Yes, right.
      I haven't used similar timezones before, so I did not put that in mind. =)

      Delete
  22. many thanks in advance
    how can i get table of cities, Country, longitude, latitude and time Zone

    ReplyDelete
    Replies
    1. For all the cities, you can find databases and lists online.

      Delete
  23. Assalamualaikum brother,
    Could you give example to calculate praying time for Indonesia Region.

    Thanks for your kindness,
    Dedy Yasriady

    ReplyDelete
    Replies
    1. Wa'alaykom Assalam,

      I have an example at the end of the post. Or here is the full example in one file https://ideone.com/sqNLrg

      The passed parameter will depend on your country. So for example, Jakarta should have somthing like this:

      Date: 15-2-2017
      Longitude: 106.8227
      Latitude: -6.1745
      Time Zone: +7
      Fajr Twilight: -19.5 (depends on the approved calculation method in your country)
      Esha Twilight: -17.5 (depends on the approved calculation method in your country)

      Delete
  24. This comment has been removed by the author.

    ReplyDelete
  25. This comment has been removed by the author.

    ReplyDelete
  26. Assalamu'alaikum my brother Mahmoud Adly Ezzat.
    Thank you for the code, this is very usefull.
    I'm from Indonesia. I think there's something you need to change about Asr time. Because when I set the location in Indonesia(with long : 112.75, lat :-7.492, and timeZone : 7), the Asr time wouldn't work correctly. In line 102 from ideone.com :

    double Asr_Alt = radToDeg(atan(1 + tan(degToRad(latitude - Dec))));

    it should be like this :

    double Asr_Alt = radToDeg(atan(1 + tan(degToRad(abs(latitude - Dec)))));

    The reason is, because not every place's latitude is positive value, while from many reference website I've search, the value inside tan should be positive. Hope this can help others. Thank you.
    :)

    Best Regards,
    Reza

    ReplyDelete
    Replies
    1. وعليكم السلام ورحمة الله وبركاته :)
      Thanks A LOT for this note.

      Delete
    2. i am from Indonesia too..

      its my code
      float waktuAshr(float dzuhr, float Dec){
      float Zm,To,cTo,cHa,Ha;

      Zm=Latitude - Dec;
      if(Zm<0){Zm=-1*Zm;} //if negative :D
      cHa=tan(Zm*RadtoDeg)+Mazhab;
      Ha=acot(cHa)*DegtoRad;

      cTo=(sin(Ha*RadtoDeg)/cos(Latitude*RadtoDeg)/cos(Dec*RadtoDeg))-(tan(Latitude*RadtoDeg)*tan(Dec*RadtoDeg));
      To=acos(cTo)*DegtoRad/15;
      return dzuhr+To;
      }
      my project with P10
      https://www.facebook.com/restia.fatmasari/videos/1493457524072443/

      Delete
  27. thanks you so much this is the best

    ReplyDelete
  28. Please help me!, how to do this code on codevision AVR???

    ReplyDelete
    Replies
    1. Hi Fareed,
      I am sorry I am not familiar with with tool.
      But generally speaking, this is pure C++ code. It ran on different online and offline compilers and even on some microcontroller boards.
      So I believe that if you have "Hello World" code on this tool, you can replace it with my code and it should work :)
      Good luck.

      Delete
    2. i have coded it with atmega32 cvavr

      Delete
    3. Mau dong, ajarin/bimbing buat pembelajaran

      Delete
  29. Replies
    1. Yes sure. Some commenters above mentioned that it worked fine. It is simply C++ :)

      Delete