use core::fmt;
use std::fmt::Display;
use chrono::{NaiveDateTime, TimeZone};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum MidnightMethod {
Standard,
Jafari,
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum HighLatsMethod {
None,
NightMiddle,
OneSeventh,
AngleBased,
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum Format {
H24, H12, H12NS, Float, }
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Degrees {
pub degree: f64,
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Minutes {
pub minutes: f64,
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct AsrFactor {
pub factor: f64,
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(untagged))]
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum CalculationUnit {
#[cfg_attr(feature = "serde", serde(rename = "degree"))]
Degrees(Degrees),
#[cfg_attr(feature = "serde", serde(rename = "minutes"))]
Minutes(Minutes),
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq)]
pub struct Parameters {
pub imsak: CalculationUnit,
pub fajr: Degrees,
pub dhuhr: Minutes,
pub asr: AsrFactor,
pub maghrib: CalculationUnit,
pub isha: CalculationUnit,
pub midnight: MidnightMethod,
#[cfg_attr(feature = "serde", serde(rename = "highLats"))]
pub high_latitudes: HighLatsMethod,
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Default, Clone, PartialEq)]
pub struct Location {
pub latitude: f64,
pub longitude: f64,
#[cfg_attr(feature = "serde", serde(default))]
pub elevation: f64,
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Default, Clone, PartialEq)]
pub struct PraytimesOutput {
pub imsak: Option<NaiveDateTime>,
pub fajr: Option<NaiveDateTime>,
pub sunrise: Option<NaiveDateTime>,
pub dhuhr: Option<NaiveDateTime>,
pub asr: Option<NaiveDateTime>,
pub sunset: Option<NaiveDateTime>,
pub maghrib: Option<NaiveDateTime>,
pub isha: Option<NaiveDateTime>,
pub midnight: Option<NaiveDateTime>,
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone)]
pub struct FormattedTimes {
pub imsak: Option<String>,
pub fajr: Option<String>,
pub sunrise: Option<String>,
pub dhuhr: Option<String>,
pub asr: Option<String>,
pub sunset: Option<String>,
pub maghrib: Option<String>,
pub isha: Option<String>,
pub midnight: Option<String>,
}
impl PraytimesOutput {
pub fn format_times<TZ>(&self, format: &str, zone: &TZ) -> FormattedTimes
where
TZ: TimeZone,
TZ::Offset: Display,
{
FormattedTimes {
imsak: self.imsak.map(|d| format_time(d, format, zone)),
fajr: self.fajr.map(|d| format_time(d, format, zone)),
sunrise: self.sunrise.map(|d| format_time(d, format, zone)),
dhuhr: self.dhuhr.map(|d| format_time(d, format, zone)),
asr: self.asr.map(|d| format_time(d, format, zone)),
sunset: self.sunset.map(|d| format_time(d, format, zone)),
maghrib: self.maghrib.map(|d| format_time(d, format, zone)),
isha: self.isha.map(|d| format_time(d, format, zone)),
midnight: self.midnight.map(|d| format_time(d, format, zone)),
}
}
pub fn into_vec(&self) -> Vec<(PraytimeType, NaiveDateTime)> {
use PraytimeType::*;
let a = vec![
(Imsak, self.imsak),
(Fajr, self.fajr),
(Sunrise, self.sunrise),
(Dhuhr, self.dhuhr),
(Asr, self.asr),
(Sunset, self.sunset),
(Maghrib, self.maghrib),
(Isha, self.isha),
(Midnight, self.midnight),
];
return a
.into_iter()
.filter_map(|(t, p)| p.map(|p| (t, p)))
.collect();
}
}
pub fn format_time<TZ>(time: chrono::NaiveDateTime, format: &str, tz: &TZ) -> String
where
TZ: TimeZone,
TZ::Offset: Display,
{
let local = tz.from_utc_datetime(&time);
let formatted = format!("{}", local.format(format));
formatted
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq, Default)]
pub struct TuneOffsets {
pub imsak: Option<f64>,
pub fajr: Option<f64>,
pub sunrise: Option<f64>,
pub dhuhr: Option<f64>,
pub asr: Option<f64>,
pub sunset: Option<f64>,
pub maghrib: Option<f64>,
pub isha: Option<f64>,
pub midnight: Option<f64>,
}
#[derive(Debug, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
pub enum PraytimeType {
Imsak,
Fajr,
Sunrise,
Dhuhr,
Asr,
Sunset,
Maghrib,
Isha,
Midnight,
}
impl fmt::Display for PraytimeType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
PraytimeType::Imsak => write!(f, "imsak"),
PraytimeType::Fajr => write!(f, "fajr"),
PraytimeType::Sunrise => write!(f, "sunrise"),
PraytimeType::Dhuhr => write!(f, "dhuhr"),
PraytimeType::Asr => write!(f, "asr"),
PraytimeType::Sunset => write!(f, "sunset"),
PraytimeType::Maghrib => write!(f, "maghrib"),
PraytimeType::Isha => write!(f, "isha"),
PraytimeType::Midnight => write!(f, "midnight"),
}
}
}