Skip to content

About

Rust port of KosherJava for Jewish Holidays, Zmanim, and Torah/Talmud learning schedules (i.e. Daf Yomi, Pirkei Avos etc.) .

Topics

Resources

Contributing

Stars

3 stars

Watchers

1 watching

Forks

Repository files navigation

kosher-rust

Jewish calendar, zmanim and daily learning schedules for Rust. A port of KosherJava, checked against it on every commit.

  • Calendar: Hebrew dates, holidays, fasts, the weekly parsha, the molad.
  • Zmanim: sunrise, sof zman shma, candle lighting and over 160 other halachic times for any place on earth.
  • Limudim: Daf Yomi, Mishna Yomis, Yerushalmi, Tehillim, Pirkei Avos and more.

no_std compatible: it builds for microcontrollers, with or without an allocator.

cargo add kosher-rust jiff

The Hebrew calendar

A jiff::civil::Date (or ICU date) converts to a HebrewDate, which answers questions about that day. Pass a Region wherever Israel and the diaspora differ. A HebrewDate covers 1 January of year 1 through the end of Hebrew year 9999, and the conversion fails outside that range.

use jiff::civil::date;
use kosher_rust::{HebrewDate, Region};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let day = HebrewDate::try_from(date(2024, 4, 23))?;
    assert_eq!(day.to_string(), "15 Nisan 5784");

    for special_day in day.special_days(Region::Diaspora) {
        println!("{special_day} ({})", special_day.hebrew());   // Pesach (פסח)
    }
    assert!(day.is_assur_bemelacha(Region::Diaspora));
    assert!(day.year().is_leap());

    let shabbos = HebrewDate::try_from(date(2024, 5, 4))?;
    println!("{}", shabbos.parsha(Region::Israel).unwrap());   // Achrei Mos
    Ok(())
}

Zmanim

Give a Location and a date to Zmanim, then ask for any Zman. Times come back as jiff::Timestamp, so convert them to the local time zone to display them.

use jiff::{civil::date, tz::TimeZone};
use kosher_rust::{Location, Zman, Zmanim};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let tz = TimeZone::get("America/New_York")?;
    let lakewood = Location::new(40.09, -74.22)?.with_elevation(30.0)?;
    let zmanim = Zmanim::new(lakewood, date(2024, 4, 23), Some(tz));

    let shma = zmanim.get_zoned(Zman::SofZmanShmaGra)?;
    println!("{}", shma.strftime("%H:%M")); // 09:31

    for zman in Zman::ALL {
        if let Ok(time) = zmanim.get_zoned(zman) {
            println!("{:<45} {}", zman.name(), time.strftime("%H:%M:%S"));
        }
    }
    Ok(())
}

get returns an error when a time doesn't exist that day. For example, in the far north in summer the sun never sinks 16.1° below the horizon, so there is no alos at 16.1°.

To pick the solar algorithm (NOAA, Meeus or SPA), use elevation everywhere, or change the candle-lighting offset, build the calculator with Zmanim::with_config and a zmanim::Config.

Time zones

You can calculate zmanim without a time zone, but there are some limitations. In these cases you get ZmanimError::TimeZoneRequired.

  • The get_zoned function always returns this error when no time zone was provided. If you would like to use this function, you must provide a time zone.
  • The get function returns this error for any zman when the location is more than 150° east or west of Greenwich. For example, Auckland, New Zealand is at 174.76° east, so none of its zmanim can be calculated without a time zone.
  • The get function returns this error for the four Kiddush Levana zmanim, even for locations close to Greenwich.
    • TchilasZmanKidushLevana3Days
    • TchilasZmanKidushLevana7Days
    • SofZmanKidushLevanaBetweenMoldos
    • SofZmanKidushLevana15Days

Learning schedules

Each schedule answers on(date) with that day's portion, or None when nothing is scheduled.

use jiff::civil::date;
use kosher_rust::limudim::{DafYomiBavli, MishnaYomis, Schedule};

let day = date(2024, 4, 23);
println!("{}", DafYomiBavli.on(day).unwrap());   // Bava Metzia 55
println!("{}", MishnaYomis.on(day).unwrap());    // Nazir 5:5-6

MyZmanim

kosher_rust::myzmanim calculates zmanim the way MyZmanim does. Use it when your users compare your times with that site.

To match the site, you need the same inputs MyZmanim uses for the location. These are its latitude and longitude, the observer's elevation, and the elevations of the eastern and western horizons. MyZmanim doesn't publish these values, but you can usually get them from its API, app or website. With them, 92% of times match the site to within one second and 99.8% to within two.

Keep in mind when doing a comparison, MyZmanim.com does not calculate times for the exact point you search for. It groups places into areas, finds the area your point is in, and shows the times for that area. For example, two points on opposite ends of Lakewood have slightly different sunrises, but the website shows the same sunrise for both, to the second. If you use the coordinates you searched with, your times will differ slightly from the site. Use MyZmanim's coordinates for the area instead.

use std::time::Duration;

use jiff::{civil::date, tz::TimeZone};
use kosher_rust::Location;
use kosher_rust::myzmanim::{MyZman, MyZmanim};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let jerusalem = Location::new(31.778, 35.235)?
        .with_elevation(754.0)?
        .with_horizons(754.0, 0.0)?;
    let times = MyZmanim::new(jerusalem, date(2026, 11, 6), Some(TimeZone::get("Asia/Jerusalem")?))
        .candle_lighting(Duration::from_mins(40));
    println!("Candle lighting: {}", times.get_zoned(MyZman::CandleLighting)?.strftime("%H:%M"));
    Ok(())
}

Port status

This port is tracked against KosherJava commit 0dde7ae, which is master after the 3.0.0 release. CI compares it with that version on every commit, using random dates and locations for every zman, the Hebrew calendar and Daf Yomi.

The zmanim, the three astronomical calculators, the Hebrew calendar and both Daf Yomi calculators are ported. Not ported yet:

  • HebrewDateFormatter
  • ZmanimFormatter
  • TefilaRules
  • The tekufos
  • SunTimesCalculator
  • getZmanMolad, getPolarPlagHaminchaBenIshChai, getPolarStartOfDayTeshuvosVehanhagos and getPolarPlagHaminchaTeshuvosVehanhagos
  • getLocalMeanTime, getTimeAtAzimuth90Or270, getSunriseSolarDipFromOffset, getSunsetSolarDipFromOffset and getPercentOfShaahZmanisFromDegrees
  • The distance and bearing methods of GeoLocation
  • isErevRoshChodesh, isErevYomTovSheni, isTomorrowShabbosOrYomTov and isTonightMutarBemelacha

Open an issue if you need one.

Features

Feature Default
alloc yes Zman::description(), a paragraph explaining each zman to your users
defmt no defmt::Format on the public types, for embedded logging

License

LGPL-2.1-or-later. Based on KosherJava by Eliyahu Hershfeld.

About

Rust port of KosherJava for Jewish Holidays, Zmanim, and Torah/Talmud learning schedules (i.e. Daf Yomi, Pirkei Avos etc.) .

Topics

Resources

Contributing

Stars

3 stars

Watchers

1 watching

Forks

Releases

Contributors

Languages