Skip to content

Commit

Permalink
Merge pull request #7 from insha/insha-issue-6-wrong-prayer-times
Browse files Browse the repository at this point in the history
Fixing the issue with the wrong prayer times
  • Loading branch information
insha authored Jan 12, 2021
2 parents 3392cc8 + 2414ef6 commit d25ffe7
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 13 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "salah"
version = "0.4.2"
version = "0.5.0"
authors = ["Farhan Ahmed <[email protected]>"]
edition = "2018"
description = "Islamic prayer time library for Rust"
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Add the following to your `Cargo.toml` file under the `[dependencies]` section:

```
[dependencies]
salah = "0.4.2"
salah = "0.5.0"
```

To get prayer times, use the `PrayerSchedule` struct passing in coordinates, date, and calculation parameters.
Expand Down
8 changes: 8 additions & 0 deletions src/astronomy/qiblah.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,4 +120,12 @@ mod tests {

assert_eq!(qiblah.0, 293.02072441441163);
}

#[test]
fn qiblah_direction_from_jakarta_indonesia() {
let jakarta = Coordinates::new(-6.18233995, 106.84287154);
let qiblah = Qiblah::new(jakarta);

assert_that!(qiblah.0).is_close_to(295.1442983825265, 0.0000001f64);
}
}
23 changes: 15 additions & 8 deletions src/astronomy/solar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,14 +194,8 @@ impl SolarTime {
let calculated_seconds =
((value - (calculated_hours + calculated_minutes / 60.0)) * 60.0 * 60.0).floor();

// Adjust the hour to be within 0..=23,
// wrapping around as needed; otherwise
// chrono method will panic.
let (adjusted_hour, adjusted_date) = if calculated_hours >= 24.0 {
((calculated_hours - 24.0) as u32, date.tomorrow())
} else {
(calculated_hours as u32, date.clone())
};
let (adjusted_hour, adjusted_date) =
SolarTime::hour_adjustment(calculated_hours, &date);

// Round to the nearest minute
let adjusted_mins = (calculated_minutes + calculated_seconds / 60.0).round() as u32;
Expand All @@ -222,6 +216,19 @@ impl SolarTime {

adjusted_time
}

fn hour_adjustment(calculated_hours: f64, date: &DateTime<Utc>) -> (u32, DateTime<Utc>) {
// Adjust the hour to be within 0..=23,
// wrapping around as needed; otherwise
// chrono method will panic.
if calculated_hours < 0.0 {
((calculated_hours + 24.0) as u32, date.yesterday())
} else if calculated_hours >= 24.0 {
((calculated_hours - 24.0) as u32, date.tomorrow())
} else {
(calculated_hours as u32, date.clone())
}
}
}

#[cfg(test)]
Expand Down
103 changes: 100 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ pub use chrono::{Date, DateTime, Datelike, Duration, Local, TimeZone, Timelike,
/// A convenience module appropriate for glob imports (`use salah::prelude::*;`).
pub mod prelude {
#[doc(no_inline)]
pub use crate::astronomy::unit::{Coordinates, Stride};
pub use crate::astronomy::qiblah::Qiblah;
#[doc(no_inline)]
pub use crate::astronomy::qiblah::Qiblah;
pub use crate::astronomy::unit::{Coordinates, Stride};
#[doc(no_inline)]
pub use crate::models::adjustments::{Adjustment, TimeAdjustment};
#[doc(no_inline)]
Expand All @@ -61,6 +61,8 @@ pub mod prelude {
#[cfg(test)]
mod tests {
use super::*;
use crate::models::high_altitude_rule::HighLatitudeRule;
use chrono::prelude::*;

#[test]
fn calculate_prayer_times() {
Expand Down Expand Up @@ -168,7 +170,6 @@ mod tests {
#[test]
fn calculate_qiyam_times() {
let date = Utc.ymd(2015, 7, 12);
// let qiyam_date = Utc.ymd(2015, 7, 13);
let params = Configuration::with(Method::NorthAmerica, Madhab::Hanafi);
let coordinates = Coordinates::new(35.7750, -78.6336);
let result = PrayerSchedule::new()
Expand Down Expand Up @@ -198,4 +199,100 @@ mod tests {
Err(_err) => assert!(false),
}
}

#[test]
fn calculate_times_for_singapore() {
let mut params = Configuration::with(Method::Singapore, Madhab::Shafi);

params.high_latitude_rule = HighLatitudeRule::MiddleOfTheNight;

// The adjustment below are based on the prayer times that are provided
// on the website (http://www.muis.gov.sg). I don't know the exact
// calculation that this site is using for the prayer times; therefore the
// use of time adjustment. However, these are within the 2 minute variance.
params.method_adjustments = Adjustment::new()
.fajr(1)
.sunrise(1)
.dhuhr(2)
.asr(1)
.maghrib(1)
.isha(1)
.done();

let result = PrayerSchedule::new()
.on(Utc.ymd(2021, 1, 13))
.for_location(Coordinates::new(1.370844612058886, 103.80145644060552))
.with_configuration(params)
.calculate();

match result {
Ok(schedule) => {
let hour = 3600;
let sgt_offset = FixedOffset::east(8 * hour);
let sgt_fajr = schedule.time(Prayer::Fajr).with_timezone(&sgt_offset);
let sgt_sunrise = schedule.time(Prayer::Sunrise).with_timezone(&sgt_offset);
let sgt_dhuhr = schedule.time(Prayer::Dhuhr).with_timezone(&sgt_offset);
let sgt_asr = schedule.time(Prayer::Asr).with_timezone(&sgt_offset);
let sgt_maghrib = schedule.time(Prayer::Maghrib).with_timezone(&sgt_offset);
let sgt_isha = schedule.time(Prayer::Isha).with_timezone(&sgt_offset);

assert_eq!(sgt_fajr.format("%-l:%M %p").to_string(), "5:50 AM");
assert_eq!(sgt_sunrise.format("%-l:%M %p").to_string(), "7:13 AM");
assert_eq!(sgt_dhuhr.format("%-l:%M %p").to_string(), "1:15 PM");
assert_eq!(sgt_asr.format("%-l:%M %p").to_string(), "4:39 PM");
assert_eq!(sgt_maghrib.format("%-l:%M %p").to_string(), "7:16 PM");
assert_eq!(sgt_isha.format("%-l:%M %p").to_string(), "8:30 PM");
}
Err(_err) => assert!(false),
}
}

#[test]
fn calculate_times_for_jakarta() {
let mut params = Configuration::with(Method::Egyptian, Madhab::Shafi);

// The adjustment below are based on the prayer times that are provided
// on the website (https://www.jadwalsholat.org/). I don't know the exact
// calculation that this site is using for the prayer times; therefore the
// use of time adjustment.
//
// It would be a good idea to get some more information on how the Fajr
// and Isha are calculated, since that's where the biggest variance is;
// however, the other times are within the 2 minute variance.
params.method_adjustments = Adjustment::new()
.fajr(-10)
.sunrise(-2)
.dhuhr(2)
.asr(1)
.maghrib(2)
.isha(4)
.done();

let result = PrayerSchedule::new()
.on(Utc.ymd(2021, 1, 12))
.for_location(Coordinates::new(-6.18233995, 106.84287154))
.with_configuration(params)
.calculate();

match result {
Ok(schedule) => {
let hour = 3600;
let wib_offset = FixedOffset::east(7 * hour);
let wib_fajr = schedule.time(Prayer::Fajr).with_timezone(&wib_offset);
let wib_sunrise = schedule.time(Prayer::Sunrise).with_timezone(&wib_offset);
let wib_dhuhr = schedule.time(Prayer::Dhuhr).with_timezone(&wib_offset);
let wib_asr = schedule.time(Prayer::Asr).with_timezone(&wib_offset);
let wib_maghrib = schedule.time(Prayer::Maghrib).with_timezone(&wib_offset);
let wib_isha = schedule.time(Prayer::Isha).with_timezone(&wib_offset);

assert_eq!(wib_fajr.format("%-l:%M %p").to_string(), "4:15 AM");
assert_eq!(wib_sunrise.format("%-l:%M %p").to_string(), "5:45 AM");
assert_eq!(wib_dhuhr.format("%-l:%M %p").to_string(), "12:03 PM");
assert_eq!(wib_asr.format("%-l:%M %p").to_string(), "3:28 PM");
assert_eq!(wib_maghrib.format("%-l:%M %p").to_string(), "6:16 PM");
assert_eq!(wib_isha.format("%-l:%M %p").to_string(), "7:31 PM");
}
Err(_err) => assert!(false),
}
}
}

0 comments on commit d25ffe7

Please sign in to comment.