A Kotlin Multiplatform SNTP (Simple Network Time Protocol) client library for accurate network time synchronization.
- π Multiplatform - Android, iOS, JVM Desktop, JavaScript, WASM
- β‘ Coroutine-based - Modern async API with Kotlin Coroutines
- π Automatic Fallback - Multiple NTP server pools with retry logic
- π οΈ Configurable - Builder pattern for flexible configuration
- π¦ Lightweight - Minimal dependencies
- π Well Documented - Comprehensive KDoc documentation
Add the dependency to your build.gradle.kts:
// For Kotlin Multiplatform projects
kotlin {
sourceSets {
commonMain.dependencies {
implementation("in.sitharaj:kronosync:1.0.0")
}
}
}
// For Android/JVM only projects
dependencies {
implementation("in.sitharaj:kronosync:1.0.0")
}import `in`.sitharaj.kronosync.KronoSync
import `in`.sitharaj.kronosync.SyncResult
// Initialize once at app startup
KronoSync.initialize()
// Sync with NTP servers
val result = KronoSync.sync()
when (result) {
is SyncResult.Success -> {
println("Synced! Offset: ${result.offset}")
println("Server: ${result.serverAddress}")
}
is SyncResult.Failure -> {
println("Failed: ${result.error}")
}
}
// Get network-synchronized time
val networkTime = KronoSync.now()
val timeMillis = KronoSync.currentTimeMillis()import `in`.sitharaj.kronosync.NtpConfig
import kotlin.time.Duration.Companion.seconds
KronoSync.initialize(
NtpConfig.Builder()
.ntpServers(listOf(
"time.google.com",
"time.apple.com",
"time.cloudflare.com"
))
.timeout(10.seconds)
.retryCount(3)
.retryDelay(1.seconds)
.build()
)For more control, use NtpClient directly instead of the singleton:
import `in`.sitharaj.kronosync.NtpClient
import `in`.sitharaj.kronosync.NtpConfig
val client = NtpClient(NtpConfig.DEFAULT)
// Sync
val result = client.sync()
// Get time
val now = client.now() // Returns null if not synced
val nowOrSystem = client.nowOrSystem() // Falls back to system time
// Get offset
val offset = client.offset()
// Check sync status
val isSynced = client.isSynchronized()
// Get full snapshot
val snapshot = client.snapshot()Add Internet permission to your AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET" />Initialize in your Application class:
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
KronoSync.initialize()
// Optional: sync in background
lifecycleScope.launch {
KronoSync.sync()
}
}
}Initialize in your app delegate or SwiftUI App:
import ComposeApp
@main
struct iOSApp: App {
init() {
KronoSyncKt.doInitialize()
}
var body: some Scene {
WindowGroup {
ContentView()
}
}
}Due to browser security restrictions, raw UDP sockets are not available. KronoSync uses HTTP-based time APIs as a fallback on these platforms.
| Method | Description |
|---|---|
initialize(config) |
Initialize with optional configuration |
sync() |
Sync with NTP servers (suspend) |
now() |
Get network time or null |
nowOrSystem() |
Get network time or system time |
currentTimeMillis() |
Get time in epoch milliseconds |
offset() |
Get clock offset duration |
isSynchronized() |
Check if synced |
snapshot() |
Get full time snapshot |
reset() |
Reset sync state |
| Method | Default | Description |
|---|---|---|
ntpServers(list) |
Google, Apple, Cloudflare, etc. | NTP server hostnames |
timeout(duration) |
10 seconds | Request timeout |
retryCount(count) |
3 | Retry attempts per server |
retryDelay(duration) |
1 second | Delay between retries |
syncOnInit(bool) |
true | Sync automatically |
cacheDuration(duration) |
Infinite | Cache expiration |
Run the sample application:
# Desktop
./gradlew :sample:composeApp:run
# Android
./gradlew :sample:composeApp:installDebug
# iOS
open sample/iosApp/iosApp.xcworkspace./gradlew :kronosync:publishToMavenLocal- Configure GPG signing in
~/.gradle/gradle.properties:
signing.keyId=YOUR_KEY_ID
signing.password=YOUR_KEY_PASSWORD
signing.secretKeyRingFile=/path/to/secring.gpg- Generate the bundle:
./gradlew :kronosync:zipBundle- Upload
kronosync/build/bundle/kronosync-bundle.zipat central.sonatype.com
Copyright 2024 Sitharaj Seenivasan
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Contributions are welcome! Please read our Contributing Guidelines first.
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
- RFC 4330 - Simple Network Time Protocol (SNTP)
- kotlinx-datetime - Multiplatform date/time library
- kotlinx-coroutines - Coroutines library