use jiff::{Timestamp, civil::Date};
mod astronomy;
pub mod presets;
pub mod types {
pub mod config;
pub mod error;
pub mod location;
}
pub mod molad;
pub mod primitives;
pub mod prelude {
pub use super::presets;
pub use super::primitives::ZmanPrimitive;
pub use super::types::config::CalculatorConfig;
pub use super::types::error::ZmanimError;
pub use super::types::location::Location;
pub use super::{ZmanLike, ZmanPreset, ZmanimCalculator};
}
#[cfg(test)]
mod tests;
use crate::zmanim::{
primitives::ZmanPrimitive,
types::{config::CalculatorConfig, error::ZmanimError, location::Location},
};
#[cfg(feature = "alloc")]
extern crate alloc;
#[cfg(feature = "alloc")]
use alloc::string::String;
#[derive(Clone, Debug)]
pub struct ZmanimCalculator {
pub(crate) location: Location,
pub(crate) date: Date,
pub(crate) config: CalculatorConfig,
}
impl ZmanimCalculator {
pub fn new(location: Location, date: Date, config: CalculatorConfig) -> Self {
Self { location, date, config }
}
pub fn calculate(&self, zman: &impl ZmanLike) -> Result<Timestamp, ZmanimError> {
zman.calculate(self)
}
}
pub trait ZmanLike {
fn calculate(&self, calculator: &ZmanimCalculator) -> Result<Timestamp, ZmanimError>;
}
#[derive(Debug, Clone)]
pub struct ZmanPreset {
pub event: ZmanPrimitive,
pub method_name: &'static str,
pub name: &'static str,
#[cfg(feature = "alloc")]
pub(crate) description: fn(&ZmanimCalculator) -> String,
pub deprecated: bool,
}
impl ZmanLike for ZmanPreset {
fn calculate(&self, calculator: &ZmanimCalculator) -> Result<Timestamp, ZmanimError> {
self.event.calculate(calculator)
}
}
impl ZmanPreset {
#[cfg(feature = "alloc")]
pub fn description(&self, calculator: &ZmanimCalculator) -> String {
let mut desc = (self.description)(calculator);
if self.event.uses_elevation_from_config() {
if calculator.config.use_elevation {
desc.push_str(
"\n\nThis zman takes the configured location's elevation into account when it is calculated.",
);
} else {
desc.push_str("\n\nThis zman is calculated as though the configured location were at sea level.");
}
}
if self.event.uses_astronomical_chatzos_from_config() {
if calculator.config.use_astronomical_chatzos {
desc.push_str("\n\nThis zman uses astronomical chatzos (solar transit) as the midpoint of the day.");
} else {
desc.push_str("\n\nThis zman uses the midpoint between sunrise and sunset for chatzos.");
}
}
if self.event.uses_astronomical_chatzos_for_other_zmanim_from_config() {
if calculator.config.use_astronomical_chatzos_for_other_zmanim {
desc.push_str(
"\n\nThis zman divides the afternoon from astronomical chatzos when calculating shaos zmaniyos.",
);
} else {
desc.push_str(
"\n\nThis zman uses a fixed fraction of the sunrise-to-sunset interval for shaos zmaniyos, without dividing the day at astronomical chatzos.",
);
}
}
desc
}
}
#[cfg(feature = "defmt")]
impl defmt::Format for ZmanimCalculator {
fn format(&self, fmt: defmt::Formatter) {
let y = self.date.year();
let m = self.date.month();
let d = self.date.day();
defmt::write!(
fmt,
"ZmanimCalculator {{ location: {}, date: {=i16}-{=i8}-{=i8}, config: {} }}",
self.location,
y,
m,
d,
self.config
)
}
}
#[cfg(feature = "defmt")]
impl defmt::Format for ZmanPreset {
fn format(&self, fmt: defmt::Formatter) {
defmt::write!(fmt, "ZmanPreset {{ event: {}, name: {} }}", self.event, self.name)
}
}