
Calculates astronomical times, sunrise/sunset (NOAA default), and Jewish zmanim for prayers; offers ComplexZmanimCalendar, lazy computed zman properties, metadata-rich definitions, and an allZmanim list.
A Kotlin Multiplatform library for Jewish calendar and zmanim calculations: sunrise, sunset and other astronomical times (NOAA algorithm by default), halachic times for prayer and other religious duties, Hebrew dates, holidays, the weekly parsha and Daf Yomi.
It is a Kotlin port of Eliyahu Hershfeld's KosherJava Zmanim API,
built on kotlinx-datetime so the same code runs on Android, iOS, desktop JVM and the browser.
See Project history and attribution for who wrote what.
| Target | Published artifact | Notes |
|---|---|---|
| Android | kosherkotlin-android |
minSdk 24 |
| JVM (desktop) | kosherkotlin-desktop |
JDK 17 toolchain |
| iOS |
kosherkotlin-iosarm64, -iossimulatorarm64, -iosx64
|
|
| JavaScript (browser) | kosherkotlin-js |
Kotlin/JS IR |
The library is on Maven Central. In a Kotlin Multiplatform project, depend on the root artifact and Gradle resolves the right variant for each target:
// build.gradle.kts
repositories {
mavenCentral()
}
kotlin {
sourceSets {
commonMain.dependencies {
implementation("io.github.elfifo4:kosherkotlin:1.0.1")
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.8.0")
}
}
}In an Android-only or JVM-only project, the same coordinates go in the regular dependencies block.
kotlinx-datetime types such as TimeZone, LocalDate and Instant appear in the public API, but
the published artifact does not yet export that dependency to consumers at compile time. Until that
is fixed, declare kotlinx-datetime yourself as shown above.
import kotlinx.datetime.TimeZone
import sternbach.software.kosherkotlin.ComplexZmanimCalendar
import sternbach.software.kosherkotlin.metadata.ZmanType
import sternbach.software.kosherkotlin.util.GeoLocation
val location = GeoLocation(
"Lakewood, NJ",
40.096, // latitude
-74.222, // longitude
29.02, // elevation in meters
TimeZone.of("America/New_York")
)
val calendar = ComplexZmanimCalendar(location) // defaults to today's date in that time zone
println(calendar.sunrise) // Instant?
println(calendar.alos72.momentOfOccurrence) // Instant?
println(calendar.shaahZmanis72Minutes.duration) // Duration
// Every opinion for a given kind of zman, with the rule each one is computed by
calendar.allZmanim
.filter { it.definition.type == ZmanType.ALOS }
.forEach { println("${it.definition} -> ${it.value}") }ZmanimCalendar holds the most commonly used zmanim. ComplexZmanimCalendar extends it with a much
larger set of opinions. For purely astronomical calculations, use AstronomicalCalendar.
To calculate for another day, set calendar.localDateTime.
import kotlinx.datetime.LocalDate
import sternbach.software.kosherkotlin.hebrewcalendar.HebrewDateFormatter
import sternbach.software.kosherkotlin.hebrewcalendar.JewishCalendar
val day = JewishCalendar(LocalDate(2026, 4, 11))
val formatter = HebrewDateFormatter()
println(formatter.format(day)) // the Hebrew date
println(formatter.formatParsha(day)) // "Shmini"
println(day.parshah) // the JewishCalendar.Parsha enum value; NONE on a weekday
println(day.isRoshChodesh)
println(day.dafYomiBavli)The port aims for an idiomatic Kotlin surface rather than a line-by-line translation:
calendar.alos72, not getAlos72()).Zman object, not a bare date. Zman.DateBased exposes momentOfOccurrence
(an Instant?, null where the sun does not reach the required position, as in polar regions).
Zman.ValueBased exposes duration. Both compute lazily.Zman carries a definition: structured metadata describing its type, the calculation
method and the authority it follows. allZmanim returns all of them as a list, so an app can
filter, group and label zmanim without hard-coding each one.The calculations themselves follow KosherJava, so its documentation applies: How to Use the Zmanim API, code samples and the FAQ.
library/ the published library; all code is in commonMain, with no platform-specific sources
src/commonMain/kotlin/sternbach/software/kosherkotlin/
AstronomicalCalendar.kt, ZmanimCalendar.kt, ComplexZmanimCalendar.kt, Zman.kt
hebrewcalendar/ JewishDate, JewishCalendar, HebrewDateFormatter, Daf Yomi, TefilaRules
metadata/ ZmanDefinition, ZmanType, ZmanAuthority, calculation methods
util/ GeoLocation, NOAACalculator, SunTimesCalculator
src/commonTest/ tests that run on every target
src/desktopTest/ JVM tests, including regression tests against KosherJava
composeApp/ Compose Multiplatform demo app (Android, desktop, iOS, web); not needed to use the library
iosApp/ Xcode project that hosts the iOS demo
./gradlew :library:desktopTestThe JVM test suite depends on the original com.kosherjava:zmanim artifact and compares this port's
output against it across dates and locations, so behavioural drift from the reference implementation
shows up as a test failure. Calendar logic that has no JVM dependency is also covered in
commonTest. CI runs the JVM suite on every push and pull request.
Requirements: JDK 17, and a local.properties file at the project root pointing to the Android SDK.
KDoctor can check the rest of the environment.
| Platform | Command |
|---|---|
| Android | ./gradlew :composeApp:assembleDebug |
| Desktop | ./gradlew :composeApp:run |
| Browser | ./gradlew :composeApp:jsBrowserDevelopmentRun |
| iOS | open iosApp/iosApp.xcodeproj in Xcode and run |
This repository is one link in a chain of work by several people:
Zman and metadata model, and
the migration from java.util/java.time to kotlinx-datetime that made the code multiplatform.
The sternbach.software.kosherkotlin package name is kept from that project.:library Gradle module, publishing it to Maven Central for Android, JVM, iOS and JS, upgrading
the toolchain and dependencies, a fix to the parsha calculation with regression tests, and
repairing the web target of the demo app. The full list is in the
commit history.ZmanimFormatter from KosherJava has not been ported.com.kosherjava class names.Maintainer instructions are in RELEASING.md.
Released under the GNU Lesser General Public License v2.1, the same license as KosherJava.
Every effort is made to produce accurate results, but please double-check before relying on these zmanim for halacha lemaaseh.
A Kotlin Multiplatform library for Jewish calendar and zmanim calculations: sunrise, sunset and other astronomical times (NOAA algorithm by default), halachic times for prayer and other religious duties, Hebrew dates, holidays, the weekly parsha and Daf Yomi.
It is a Kotlin port of Eliyahu Hershfeld's KosherJava Zmanim API,
built on kotlinx-datetime so the same code runs on Android, iOS, desktop JVM and the browser.
See Project history and attribution for who wrote what.
| Target | Published artifact | Notes |
|---|---|---|
| Android | kosherkotlin-android |
minSdk 24 |
| JVM (desktop) | kosherkotlin-desktop |
JDK 17 toolchain |
| iOS |
kosherkotlin-iosarm64, -iossimulatorarm64, -iosx64
|
|
| JavaScript (browser) | kosherkotlin-js |
Kotlin/JS IR |
The library is on Maven Central. In a Kotlin Multiplatform project, depend on the root artifact and Gradle resolves the right variant for each target:
// build.gradle.kts
repositories {
mavenCentral()
}
kotlin {
sourceSets {
commonMain.dependencies {
implementation("io.github.elfifo4:kosherkotlin:1.0.1")
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.8.0")
}
}
}In an Android-only or JVM-only project, the same coordinates go in the regular dependencies block.
kotlinx-datetime types such as TimeZone, LocalDate and Instant appear in the public API, but
the published artifact does not yet export that dependency to consumers at compile time. Until that
is fixed, declare kotlinx-datetime yourself as shown above.
import kotlinx.datetime.TimeZone
import sternbach.software.kosherkotlin.ComplexZmanimCalendar
import sternbach.software.kosherkotlin.metadata.ZmanType
import sternbach.software.kosherkotlin.util.GeoLocation
val location = GeoLocation(
"Lakewood, NJ",
40.096, // latitude
-74.222, // longitude
29.02, // elevation in meters
TimeZone.of("America/New_York")
)
val calendar = ComplexZmanimCalendar(location) // defaults to today's date in that time zone
println(calendar.sunrise) // Instant?
println(calendar.alos72.momentOfOccurrence) // Instant?
println(calendar.shaahZmanis72Minutes.duration) // Duration
// Every opinion for a given kind of zman, with the rule each one is computed by
calendar.allZmanim
.filter { it.definition.type == ZmanType.ALOS }
.forEach { println("${it.definition} -> ${it.value}") }ZmanimCalendar holds the most commonly used zmanim. ComplexZmanimCalendar extends it with a much
larger set of opinions. For purely astronomical calculations, use AstronomicalCalendar.
To calculate for another day, set calendar.localDateTime.
import kotlinx.datetime.LocalDate
import sternbach.software.kosherkotlin.hebrewcalendar.HebrewDateFormatter
import sternbach.software.kosherkotlin.hebrewcalendar.JewishCalendar
val day = JewishCalendar(LocalDate(2026, 4, 11))
val formatter = HebrewDateFormatter()
println(formatter.format(day)) // the Hebrew date
println(formatter.formatParsha(day)) // "Shmini"
println(day.parshah) // the JewishCalendar.Parsha enum value; NONE on a weekday
println(day.isRoshChodesh)
println(day.dafYomiBavli)The port aims for an idiomatic Kotlin surface rather than a line-by-line translation:
calendar.alos72, not getAlos72()).Zman object, not a bare date. Zman.DateBased exposes momentOfOccurrence
(an Instant?, null where the sun does not reach the required position, as in polar regions).
Zman.ValueBased exposes duration. Both compute lazily.Zman carries a definition: structured metadata describing its type, the calculation
method and the authority it follows. allZmanim returns all of them as a list, so an app can
filter, group and label zmanim without hard-coding each one.The calculations themselves follow KosherJava, so its documentation applies: How to Use the Zmanim API, code samples and the FAQ.
library/ the published library; all code is in commonMain, with no platform-specific sources
src/commonMain/kotlin/sternbach/software/kosherkotlin/
AstronomicalCalendar.kt, ZmanimCalendar.kt, ComplexZmanimCalendar.kt, Zman.kt
hebrewcalendar/ JewishDate, JewishCalendar, HebrewDateFormatter, Daf Yomi, TefilaRules
metadata/ ZmanDefinition, ZmanType, ZmanAuthority, calculation methods
util/ GeoLocation, NOAACalculator, SunTimesCalculator
src/commonTest/ tests that run on every target
src/desktopTest/ JVM tests, including regression tests against KosherJava
composeApp/ Compose Multiplatform demo app (Android, desktop, iOS, web); not needed to use the library
iosApp/ Xcode project that hosts the iOS demo
./gradlew :library:desktopTestThe JVM test suite depends on the original com.kosherjava:zmanim artifact and compares this port's
output against it across dates and locations, so behavioural drift from the reference implementation
shows up as a test failure. Calendar logic that has no JVM dependency is also covered in
commonTest. CI runs the JVM suite on every push and pull request.
Requirements: JDK 17, and a local.properties file at the project root pointing to the Android SDK.
KDoctor can check the rest of the environment.
| Platform | Command |
|---|---|
| Android | ./gradlew :composeApp:assembleDebug |
| Desktop | ./gradlew :composeApp:run |
| Browser | ./gradlew :composeApp:jsBrowserDevelopmentRun |
| iOS | open iosApp/iosApp.xcodeproj in Xcode and run |
This repository is one link in a chain of work by several people:
Zman and metadata model, and
the migration from java.util/java.time to kotlinx-datetime that made the code multiplatform.
The sternbach.software.kosherkotlin package name is kept from that project.:library Gradle module, publishing it to Maven Central for Android, JVM, iOS and JS, upgrading
the toolchain and dependencies, a fix to the parsha calculation with regression tests, and
repairing the web target of the demo app. The full list is in the
commit history.ZmanimFormatter from KosherJava has not been ported.com.kosherjava class names.Maintainer instructions are in RELEASING.md.
Released under the GNU Lesser General Public License v2.1, the same license as KosherJava.
Every effort is made to produce accurate results, but please double-check before relying on these zmanim for halacha lemaaseh.