
High-precision Islamic prayer times and Qibla calculations using exact solar positions (VSOP87), nullable outputs for polar extremes, dual-tier metadata, configurable calculation methods and madhab support.
A high-precision Islamic prayer times and Qibla calculation library for Kotlin Multiplatform (Android, iOS, JVM, JS).
Ported from the robust tauqeet-js library, maintaining 1:1 mathematical precision based on VSOP87 algorithms.
tauqeet-js.tauqeet-kmp is designed to be mathematically rigorous. Rather than relying on arbitrary approximations (such as faking Asr times with hardcoded fallbacks), the engine natively propagates clean Long? (nullable) values when an astronomical event mathematically does not occur (e.g., during Polar Night or the Midnight Sun).
null is returned instead of an invalid time.metadata.isPolarDay and metadata.isPolarNight boolean flags explicitly inform the UI layer when the engine has entered a non-convergent state, allowing developers to safely degrade the interface or warn the user.The library exposes metadata in two tiers to support both simple UIs and deep astronomical debugging without sacrificing performance:
Simple UI Metadata (PrayerTimesMetadata):
Attached by default to PrayerTimesResult.metadata. It features zero-overhead fields indicating the configuration parameters applied (method, madhab, highLatitudeRule) and extreme state flags (isPolarDay, isPolarNight).
Advanced Astronomical Metadata (AstronomicalMetadata):
An opt-in mapping of the exact internal solar mechanics generated during the iterative hour-angle calculations. When includeAdvancedMetadata = true is passed to the engine, it populates astronomicalMetadata with granular, per-event data classes (TwilightMetadata, SunriseSunsetMetadata, DhahwaKubraMetadata, DhuhrMetadata, AsrMetadata).
To maintain physical precision, fields use explicit unit suffixes:
_deg (Degrees)_min (Minutes of time)_arcmin (Arcminutes)elevationMeters (Meters)Add the Maven Central repository and the dependency to your build.gradle.kts:
repositories {
mavenCentral()
}
dependencies {
implementation("io.github.h-ghulam-hasnain:tauqeet-kmp:0.2.0")
}Install the package via npm:
npm install tauqeet-jsIf using CocoaPods, include the shared framework in your Podfile (assuming integration via KMP plugin).
For cleaner call sites and safer request construction, use the unified DSL request object:
import com.tauqeet.library.Tauqeet
import com.tauqeet.library.prayers.prayerRequest
import com.tauqeet.library.prayers.CalculationMethod
val tauqeet = Tauqeet(method = CalculationMethod.MWL)
val times = tauqeet.computePrayerTimes(
prayerRequest {
latitude = 51.5072
longitude = -0.1276
date = com.tauqeet.library.DateComponents(2026, 7, 23)
timeZoneOffset = 1.0
includeAdvancedMetadata = true
calculation {
method = CalculationMethod.MWL
highLatitudeRule = com.tauqeet.library.prayers.HighLatitudeRule.MIDDLE_OF_NIGHT
}
}
)The older flat overloads are still supported, but the request DSL is the preferred public entry point.
import com.tauqeet.library.Tauqeet
import com.tauqeet.library.prayers.CalculationMethod
import com.tauqeet.library.prayers.Madhab
import com.tauqeet.library.toTimeString
import com.tauqeet.library.prayers.toISOTimes
fun main() {
val tauqeet = Tauqeet(
method = CalculationMethod.MWL,
madhab = Madhab.SHAFI
)
// Compute for London, UK (UTC+1 in summer)
// We explicitly enable `includeAdvancedMetadata` for astronomical logs
val times = tauqeet.computePrayerTimes(
prayerRequest {
latitude = 51.5072
longitude = -0.1276
date = com.tauqeet.library.DateComponents(2026, 7, 23)
timeZoneOffset = 1.0
includeAdvancedMetadata = true
}
)
println("Fajr: ${times.fajr?.toTimeString() ?: "N/A"}")
println("Sunrise: ${times.sunrise?.toTimeString() ?: "N/A"}")
println("Dhahwa Kubra: ${times.dhahwaKubra?.toTimeString() ?: "N/A"}")
println("Dhuhr: ${times.dhuhr?.toTimeString() ?: "N/A"}")
println("Asr: ${times.asr?.toTimeString() ?: "N/A"}")
println("Maghrib: ${times.maghrib?.toTimeString() ?: "N/A"}")
println("Isha: ${times.isha?.toTimeString() ?: "N/A"}")
// The raw times are returned as nullable Long (milliseconds since midnight)
println("Raw Sunrise ms: ${times.sunrise}")
// Simple UI Metadata details
println("Method Used: ${times.metadata?.method}")
println("High Lat Rule: ${times.metadata?.highLatitudeRule}")
println("Is Polar Day: ${times.metadata?.isPolarDay}")
// Advanced Astronomical Metadata (safely access event-specific mechanics)
times.astronomicalMetadata?.fajr?.let { fajrMeta ->
println("\nFajr Calculation Status: ${fajrMeta.status}")
println("Solar Declination: ${fajrMeta.DEC_deg}°")
println("Equation of Time: ${fajrMeta.EOT_min} mins")
}
// Qibla Direction (Bearing & Distance)
val qibla = tauqeet.qiblaDirection(51.5072, -0.1276)
println("\nQibla Bearing: ${qibla?.bearing} degrees")
println("Distance to Mecca: ${qibla?.distanceKm} km")
}MWL (Muslim World League)ISNA (Islamic Society of North America)EGYPT (Egyptian General Authority of Survey)MAKKAH (Umm al-Qura University)KARACHI (University of Islamic Sciences, Karachi)TEHRAN (Institute of Geophysics, University of Tehran)JAFARI (Shia Ithna Ashari)ALGERIA (18° Fajr, 12° Isha)GULF, KUWAIT, QATAR, SINGAPORE, FRANCE, TURKEY, RUSSIA)CUSTOM: You can pass your own CalculationMethodParameters to computePrayerTimes or Tauqeet instance for custom angles.The library supports all classical schools of thought. SHAFI mathematically encompasses MALIKI, HANBALI, and JAAFARI (shadow factor 1), while HANAFI uses shadow factor 2. For convenience, aliases (MALIKI, HANBALI, JAAFARI) are included in the enum.
tauqeet-kmp maintains 100% mathematical parity with the original TypeScript tauqeet-js suite.
The test suite explicitly uses property-based testing and strict invariant checks across diverse global conditions, including:
Fajr < Sunrise < Dhuhr < Asr < Maghrib < Isha even across chaotic midnight boundaries.MIDDLE_OF_NIGHT, SEVENTH_OF_NIGHT) above the Arctic Circle (e.g. Tromsø) during the midnight sun.All tests run continuously against both native JVM configurations and Javascript environments on CI to assure behavioral unity across target ecosystems.
A high-precision Islamic prayer times and Qibla calculation library for Kotlin Multiplatform (Android, iOS, JVM, JS).
Ported from the robust tauqeet-js library, maintaining 1:1 mathematical precision based on VSOP87 algorithms.
tauqeet-js.tauqeet-kmp is designed to be mathematically rigorous. Rather than relying on arbitrary approximations (such as faking Asr times with hardcoded fallbacks), the engine natively propagates clean Long? (nullable) values when an astronomical event mathematically does not occur (e.g., during Polar Night or the Midnight Sun).
null is returned instead of an invalid time.metadata.isPolarDay and metadata.isPolarNight boolean flags explicitly inform the UI layer when the engine has entered a non-convergent state, allowing developers to safely degrade the interface or warn the user.The library exposes metadata in two tiers to support both simple UIs and deep astronomical debugging without sacrificing performance:
Simple UI Metadata (PrayerTimesMetadata):
Attached by default to PrayerTimesResult.metadata. It features zero-overhead fields indicating the configuration parameters applied (method, madhab, highLatitudeRule) and extreme state flags (isPolarDay, isPolarNight).
Advanced Astronomical Metadata (AstronomicalMetadata):
An opt-in mapping of the exact internal solar mechanics generated during the iterative hour-angle calculations. When includeAdvancedMetadata = true is passed to the engine, it populates astronomicalMetadata with granular, per-event data classes (TwilightMetadata, SunriseSunsetMetadata, DhahwaKubraMetadata, DhuhrMetadata, AsrMetadata).
To maintain physical precision, fields use explicit unit suffixes:
_deg (Degrees)_min (Minutes of time)_arcmin (Arcminutes)elevationMeters (Meters)Add the Maven Central repository and the dependency to your build.gradle.kts:
repositories {
mavenCentral()
}
dependencies {
implementation("io.github.h-ghulam-hasnain:tauqeet-kmp:0.2.0")
}Install the package via npm:
npm install tauqeet-jsIf using CocoaPods, include the shared framework in your Podfile (assuming integration via KMP plugin).
For cleaner call sites and safer request construction, use the unified DSL request object:
import com.tauqeet.library.Tauqeet
import com.tauqeet.library.prayers.prayerRequest
import com.tauqeet.library.prayers.CalculationMethod
val tauqeet = Tauqeet(method = CalculationMethod.MWL)
val times = tauqeet.computePrayerTimes(
prayerRequest {
latitude = 51.5072
longitude = -0.1276
date = com.tauqeet.library.DateComponents(2026, 7, 23)
timeZoneOffset = 1.0
includeAdvancedMetadata = true
calculation {
method = CalculationMethod.MWL
highLatitudeRule = com.tauqeet.library.prayers.HighLatitudeRule.MIDDLE_OF_NIGHT
}
}
)The older flat overloads are still supported, but the request DSL is the preferred public entry point.
import com.tauqeet.library.Tauqeet
import com.tauqeet.library.prayers.CalculationMethod
import com.tauqeet.library.prayers.Madhab
import com.tauqeet.library.toTimeString
import com.tauqeet.library.prayers.toISOTimes
fun main() {
val tauqeet = Tauqeet(
method = CalculationMethod.MWL,
madhab = Madhab.SHAFI
)
// Compute for London, UK (UTC+1 in summer)
// We explicitly enable `includeAdvancedMetadata` for astronomical logs
val times = tauqeet.computePrayerTimes(
prayerRequest {
latitude = 51.5072
longitude = -0.1276
date = com.tauqeet.library.DateComponents(2026, 7, 23)
timeZoneOffset = 1.0
includeAdvancedMetadata = true
}
)
println("Fajr: ${times.fajr?.toTimeString() ?: "N/A"}")
println("Sunrise: ${times.sunrise?.toTimeString() ?: "N/A"}")
println("Dhahwa Kubra: ${times.dhahwaKubra?.toTimeString() ?: "N/A"}")
println("Dhuhr: ${times.dhuhr?.toTimeString() ?: "N/A"}")
println("Asr: ${times.asr?.toTimeString() ?: "N/A"}")
println("Maghrib: ${times.maghrib?.toTimeString() ?: "N/A"}")
println("Isha: ${times.isha?.toTimeString() ?: "N/A"}")
// The raw times are returned as nullable Long (milliseconds since midnight)
println("Raw Sunrise ms: ${times.sunrise}")
// Simple UI Metadata details
println("Method Used: ${times.metadata?.method}")
println("High Lat Rule: ${times.metadata?.highLatitudeRule}")
println("Is Polar Day: ${times.metadata?.isPolarDay}")
// Advanced Astronomical Metadata (safely access event-specific mechanics)
times.astronomicalMetadata?.fajr?.let { fajrMeta ->
println("\nFajr Calculation Status: ${fajrMeta.status}")
println("Solar Declination: ${fajrMeta.DEC_deg}°")
println("Equation of Time: ${fajrMeta.EOT_min} mins")
}
// Qibla Direction (Bearing & Distance)
val qibla = tauqeet.qiblaDirection(51.5072, -0.1276)
println("\nQibla Bearing: ${qibla?.bearing} degrees")
println("Distance to Mecca: ${qibla?.distanceKm} km")
}MWL (Muslim World League)ISNA (Islamic Society of North America)EGYPT (Egyptian General Authority of Survey)MAKKAH (Umm al-Qura University)KARACHI (University of Islamic Sciences, Karachi)TEHRAN (Institute of Geophysics, University of Tehran)JAFARI (Shia Ithna Ashari)ALGERIA (18° Fajr, 12° Isha)GULF, KUWAIT, QATAR, SINGAPORE, FRANCE, TURKEY, RUSSIA)CUSTOM: You can pass your own CalculationMethodParameters to computePrayerTimes or Tauqeet instance for custom angles.The library supports all classical schools of thought. SHAFI mathematically encompasses MALIKI, HANBALI, and JAAFARI (shadow factor 1), while HANAFI uses shadow factor 2. For convenience, aliases (MALIKI, HANBALI, JAAFARI) are included in the enum.
tauqeet-kmp maintains 100% mathematical parity with the original TypeScript tauqeet-js suite.
The test suite explicitly uses property-based testing and strict invariant checks across diverse global conditions, including:
Fajr < Sunrise < Dhuhr < Asr < Maghrib < Isha even across chaotic midnight boundaries.MIDDLE_OF_NIGHT, SEVENTH_OF_NIGHT) above the Arctic Circle (e.g. Tromsø) during the midnight sun.All tests run continuously against both native JVM configurations and Javascript environments on CI to assure behavioral unity across target ecosystems.